OpenCV手工实现灰度及RGB直方图

 

手工实现灰度及RGB直方图 !库

1. 灰度图像直方图

算法

1. 图片灰度化;

2. 遍历Mat,统计各灰度级的像素个数;

3. 根据opencv画点线函数,绘制坐标轴及像素分布图

源码(编译环境:VS2017+OpenCV) 补充:三通道直方图(即RGB彩色图象直方图在后面)

 1 #include <iostream>
 2 #include <string>
 3 #include <algorithm>
 4 #include <opencv2/opencv.hpp>
 5 #include <opencv2/imgproc/imgproc.hpp>
 6 #include <opencv2/core/core.hpp>
 7 #include <opencv2/highgui/highgui.hpp>
 8 using namespace cv;
 9 using namespace std;
10 //直方图绘制函数,参数vector<int> nums 是灰度图片256级灰度的像素个数
11 void drawHist(vector<int> nums)
12 {
13     Mat hist = Mat::zeros(600, 800, CV_8UC3);
14     auto Max = max_element(nums.begin(), nums.end());//max迭代器类型,最大数目
15     putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
16     //*********绘制坐标系************//
17     Point o = Point(100, 550);
18     Point x = Point(700, 550);
19     Point y = Point(100, 150);
20     //x轴
21     line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
22     //y轴
23     line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);
24 
25     //********绘制灰度曲线***********//
26     Point pts[256];
27     //生成坐标点
28     for (int i = 0; i < 256; i++)
29     {
30         pts[i].x = i * 2 + 100;
31         pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//归一化到[0, 300]
32         //显示横坐标
33         if ((i + 1) % 16 == 0)
34         {
35             string num = format("%d", i + 1);
36             putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
37         }
38     }
39     //绘制线
40     for (int i = 1; i < 256; i++)
41     {
42         line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2);
43     }
44     //显示图像
45     imshow("直方图" ,hist);
46 }
47 //计算直方图,统计各灰度级像素个数
48 void calHist(const string img)
49 {
50     Mat src, grey;
51     //读取图象
52     src = imread(img);
53     if (!src.data)
54     {
55         cout << "Image: " + img + " 读取失败" << endl;
56         return;
57     }
58     //先转为灰度图
59     cvtColor(src, grey, COLOR_BGR2GRAY);
60     imshow("灰度图", grey);
61     //计算各灰度级像素个数
62     vector<int> nums(256);
63     for (int i = 0; i < grey.rows; i++)
64     {
65         uchar* p = grey.ptr<uchar>(i);
66         for (int j = 0; j < grey.cols; j++)
67         {
68             nums[p[j]]++;
69         }
70     }
71     drawHist(nums);
72 }
73 
74 int main()
75 {
76     string img = "D:\\trashBox\\testIMG\\lena.bmp";
77     calHist(img);
78     
79     waitKey(0);
80     return 0;
81 }

效果图

直方图hist

 2. RGB彩色图象直方图

源码

#include <iostream>
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;

//单通道图片直方图绘制
void drawHist(vector<int> nums)
{
    Mat hist = Mat::zeros(600, 800, CV_8UC3);
    auto Max = max_element(nums.begin(), nums.end());//max迭代器类型,最大数目
    putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
    //*********绘制坐标系************//
    Point o = Point(100, 550);
    Point x = Point(700, 550);
    Point y = Point(100, 150);
    //x轴
    line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
    //y轴
    line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);

    //********绘制灰度曲线***********//
    Point pts[256];
    //生成坐标点
    for (int i = 0; i < 256; i++)
    {
        pts[i].x = i * 2 + 100;
        pts[i].y = 550 - int(nums[i]*(300.0/(*Max)));//归一化到[0, 300]
        //显示横坐标
        if ((i + 1) % 16 == 0)
        {
            string num = format("%d", i + 1);
            putText(hist, num, Point(pts[i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
        }
    }
    //绘制线
    for (int i = 1; i < 256; i++)
    {
        line(hist, pts[i - 1], pts[i], Scalar(0, 255, 0), 2);
    }
    //显示图像
    imshow("直方图" ,hist);
}

//三通道图片直方图绘制
void drawHist(vector<int> &r, vector<int> &g, vector<int> &b)
{
    Mat hist = Mat::zeros(600, 800, CV_8UC3);
    putText(hist, "Histogram", Point(150, 100), FONT_HERSHEY_DUPLEX, 1, Scalar(255, 255, 255));
    //*********绘制坐标系************//
    Point o = Point(100, 550);
    Point x = Point(700, 550);
    Point y = Point(100, 150);
    //x轴
    line(hist, o, x, Scalar(255, 255, 255), 2, 8, 0);
    //y轴
    line(hist, o, y, Scalar(255, 255, 255), 2, 8, 0);

    //********绘制灰度曲线***********//
    auto Max_r = max_element(r.begin(), r.end());
    auto Max_g = max_element(g.begin(), g.end());
    auto Max_b = max_element(b.begin(), b.end());
    Point pts[3][256];
    //生成坐标点
    for (int i = 0; i < 256; i++)
    {
        pts[0][i].x = i * 2 + 100;
        pts[0][i].y = 550 - int(r[i] * (300.0 / (*Max_r)));//归一化到[0, 300]
        pts[1][i].x = i * 2 + 100;
        pts[1][i].y = 550 - int(g[i] * (300.0 / (*Max_g)));//归一化到[0, 300]
        pts[2][i].x = i * 2 + 100;
        pts[2][i].y = 550 - int(b[i] * (300.0 / (*Max_b)));//归一化到[0, 300]
        //显示横坐标
        if ((i + 1) % 16 == 0)
        {
            string num = format("%d", i + 1);
            putText(hist, num, Point(pts[0][i].x, 570), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
        }
    }
    //绘制线
    for (int i = 1; i < 256; i++)
    {
        line(hist, pts[0][i - 1], pts[0][i], Scalar(255, 0, 0), 2);
        line(hist, pts[1][i - 1], pts[1][i], Scalar(0, 255, 0), 2);
        line(hist, pts[2][i - 1], pts[2][i], Scalar(0, 0, 255), 2);
    }
    //显示图像
    imshow("直方图", hist);
}

//灰度直方图计算
void calHist(const string img)
{
    Mat src, grey;
    //读取图象
    src = imread(img);
    if (!src.data)
    {
        cout << "Image: " + img + " 读取失败" << endl;
        return;
    }
    //先转为灰度图
    cvtColor(src, grey, COLOR_BGR2GRAY);
    imshow("灰度图", grey);
    //计算各灰度级像素个数
    vector<int> nums(256);
    for (int i = 0; i < grey.rows; i++)
    {
        uchar* p = grey.ptr<uchar>(i);
        for (int j = 0; j < grey.cols; j++)
        {
            nums[p[j]]++;
        }
    }
    drawHist(nums);
}

//多通道直方图计算
void calHist(const string img, int pattern)
{
    Mat src, grey;
    //读取图象
    src = imread(img);
    if (!src.data)
    {
        cout << "Image: " + img + " 读取失败" << endl;
        return;
    }
    imshow("原图像",src);
    //计算各灰度级像素个数
    vector<int> r(256, 0);
    vector<int> g(256, 0);
    vector<int> b(256, 0);
    for (int i = 0; i < src.rows; i++)
    {
        uchar* p = src.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++)
        {
            r[p[j * 3 + 0]]++;
            g[p[j * 3 + 1]]++;
            b[p[j * 3 + 2]]++;
        }
    }
    drawHist(r, g, b);
}

int main()
{
    string img = "D:\\trashBox\\testIMG\\tiger.jpg";
    calHist(img);//计算灰度直方图
    calHist(img, 0);//计算三色直方图
    
    waitKey(0);
    return 0;
}

算法

1. 遍历Mat,统计RGB三通道各灰度级的像素个数;

2. 根据opencv画点线函数,绘制坐标轴及像素分布图

效果

 

三色(三通道)直方图

 

posted @ 2019-05-11 19:47  yocichen  阅读(4229)  评论(0编辑  收藏  举报