3.2直方图处理

3.2.1灰度直方图

 1 //////3.2.1灰度直方图方法2:
 2 ////Source Code:https://blog.csdn.net/gone_huilin/article/details/53222806
 3 #include <opencv2\opencv.hpp>  
 4 int main()
 5 {
 6     // 图像源获取及判断 
 7     cv::Mat Image, ImageGray;
 8     Image = cv::imread("D:\\lena.jpg");
 9     if (Image.empty())
10         return -1;
11     cv::imshow("Image", Image);
12     // 转换为灰度图像
13     cv::cvtColor(Image, ImageGray, CV_BGR2GRAY);
14     // 定义直方图参数
15     const int channels[1] = { 0 };
16     const int histSize[1] = { 256 };
17     float pranges[2] = { 0,255 };
18     const float* ranges[1] = { pranges };
19     cv::MatND hist;
20     // 计算直方图
21     cv::calcHist(&ImageGray, 1, channels, cv::Mat(), hist, 1,
22         histSize, ranges);
23     // 初始化画布参数
24     int hist_w = 500;
25     int hist_h = 500;
26     int nHistSize = 255;
27     // 区间
28     int bin_w = cvRound((double)hist_w / nHistSize);
29     cv::Mat histImage(hist_w, hist_h,
30         CV_8UC3, cv::Scalar(0, 0, 0));
31     // 将直方图归一化到范围 [ 0, histImage.rows ]
32     normalize(hist, hist, 0, histImage.rows,
33         cv::NORM_MINMAX, -1, cv::Mat());
34     // 在直方图画布上画出直方图
35     for (int i = 1; i < nHistSize; i++)
36     {
37         line(histImage, cv::Point(bin_w*(i - 1),
38             hist_h - cvRound(hist.at<float>(i - 1))),
39             cv::Point(bin_w*(i),
40                 hist_h - cvRound(hist.at<float>(i))),
41             cv::Scalar(0, 0, 255), 2, 8, 0);
42     }
43     // 显示直方图
44     cv::imshow("histImage", histImage);
45     cv::waitKey();
46     return 0;
47 }
View Code

 

 1 ////3.2.1灰度直方图
 2 ////Source Code:https://blog.csdn.net/qq_20823641/article/details/51932798
 3 #include "opencv2/highgui/highgui.hpp"
 4 #include "opencv2/imgproc/imgproc.hpp"
 5 #include <iostream>
 6 using namespace cv;
 7 using namespace std;
 8 
 9 void Help()
10 {
11     printf("\n\n\t\t\t欢迎来到直方图的世界!\n");
12     printf("\n\n  ----------------------------------------------------------------------------\n");
13 }
14 
15 
16 int main()
17 {
18     Mat srcImage = imread("D:\\lena.jpg");
19     Mat grayImage;
20     if (!srcImage.data) 
21     { 
22         cout << "fail to load image" << endl;     
23         return 0; 
24     }
25     imshow("原图", srcImage);
26     cvtColor(srcImage, grayImage, CV_RGB2GRAY);
27     imshow("灰度图", grayImage);
28 
29     system("color 1F");
30     Help();
31 
32     MatND dstHist;       // 在cv中用CvHistogram *hist = cvCreateHist
33     int dims = 1;
34     float hranges[2] = { 0, 255 };
35     const float *ranges[1] = { hranges };   // 这里需要为const类型
36     int size = 256;
37     int channels = 0;
38     //计算图像的直方图
39     calcHist(&grayImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);    // cv 中是cvCalcHist
40     int scale = 1;
41     Mat dstImage(size * scale, size, CV_8U, Scalar(0));
42     //获取最大值和最小值
43     double minValue = 0;
44     double maxValue = 0;
45     minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);  //  在cv中用的是cvGetMinMaxHistValue
46                                                      //绘制出直方图
47     int hpt = saturate_cast<int>(0.9 * size);
48     for (int i = 0; i < 256; i++)
49     {
50         float binValue = dstHist.at<float>(i);           //   注意hist中是float类型    
51         int realValue = saturate_cast<int>(binValue * hpt / maxValue);
52         //rectangle(dstImage,Point(i*scale, size - 1), Point((i+1)*scale - 1, size - realValue), Scalar(255));
53         line(dstImage, Point(i*scale, size - 1), Point((i + 1)*scale - 1, size - realValue), Scalar(255));
54     }
55     imshow("一维直方图", dstImage);
56     waitKey(0);
57     return 0;
58 }
View Code

 

////Source Code:https://blog.csdn.net/qq_20823641/article/details/51932798
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <ctype.h>

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;


IplImage *src = 0;
IplImage *histimg = 0;
CvHistogram *hist = 0;

int hdims = 50;     // 划分HIST的初始个数,越高越精确

                    //滚动条函数
void HIST(int t)
{
    float hranges_arr[] = { 0,255 };
    float* hranges = hranges_arr;
    int bin_w;
    int bin_u;
    float max;
    int i;
    char string[10];
    CvFont font;
    cvInitFont(&font, CV_FONT_HERSHEY_PLAIN, 1, 1, 0, 1, 8);//字体结构初始化
    if (hdims == 0)
    {
        printf("直方图条数不能为零!\n");
    }
    else
    {
        hist = cvCreateHist(1, &hdims, CV_HIST_ARRAY, &hranges, 1);  // 创建直方图
        histimg = cvCreateImage(cvSize(800, 512), 8, 3);
        cvZero(histimg);
        cvCalcHist(&src, hist, 0, 0); // 计算直方图
        cvGetMinMaxHistValue(hist, NULL, &max, NULL, NULL);//寻找最大值及其位置
                                                           //printf("max_val:%f \n",max_val);
        cvZero(histimg);

        double bin_w = (double)histimg->width / hdims;  // hdims: 条的个数,则 bin_w 为条的宽度
        double bin_u = (double)histimg->height / max;  //// max: 最高条的像素个数,则 bin_u 为单个像素的高度

                                                       // 画直方图
        for (int i = 0; i<hdims; i++)
        {
            CvPoint p0 = cvPoint(i*bin_w, histimg->height);
            int val = cvGetReal1D(hist->bins, i);
            CvPoint p1 = cvPoint((i + 1)*bin_w, histimg->height - cvGetReal1D(hist->bins, i)*bin_u);
            cvRectangle(histimg, p0, p1, cvScalar(0, 255), 1, 8, 0);
        }
        //画纵坐标刻度(像素个数)
        int kedu = 0;
        for (int i = 1; kedu<max; i++)
        {
            kedu = i*max / 10;
            _itoa_s(kedu, string, 10);//把一个整数转换为字符串
                                   //在图像中显示文本字符串
            cvPutText(histimg, string, cvPoint(0, histimg->height - kedu*bin_u), &font, CV_RGB(0, 255, 255));
        }
        //画横坐标刻度(像素灰度值)
        kedu = 0;
        for (int i = 1; kedu<256; i++)
        {
            kedu = i * 20;
            _itoa_s(kedu, string, 10);//把一个整数转换为字符串
                                   //在图像中显示文本字符串
            cvPutText(histimg, string, cvPoint(kedu*(histimg->width / 256), histimg->height), &font, CV_RGB(255, 0, 0));
        }

        cvShowImage("Histogram", histimg);
    }
}

int main(int argc, char** argv)
{
    argc = 2;
    argv[1] = "D:\\lena.jpg";

    if (argc != 2 || (src = cvLoadImage(argv[1], 0)) == NULL)  // force to gray image
        return -1;

    cvNamedWindow("src", 1);
    cvShowImage("src", src);
    cvNamedWindow("Histogram", 1);

    cvCreateTrackbar("hdims", "src", &hdims, 256, HIST);
    HIST(0);
    cvWaitKey(0);

    cvDestroyWindow("src");
    cvDestroyWindow("Histogram");
    cvReleaseImage(&src);
    cvReleaseImage(&histimg);
    cvReleaseHist(&hist);

    return 0;
}
View Code

 参考:

https://blog.csdn.net/xiaowei_cqu/article/details/7600666

https://www.cnblogs.com/wangguchangqing/p/7098213.html 

 

3.2.2 H-S直方图

 1 ////Source Code: https://blog.csdn.net/uestc_c2_403/article/details/72814455
 2 #include "opencv2/highgui/highgui.hpp"
 3 #include "opencv2/imgproc/imgproc.hpp"
 4 #include "opencv2/opencv.hpp"
 5 #include "opencv2/core/core.hpp"
 6 #include <stdio.h>
 7 #include <string>
 8 using namespace std;
 9 using namespace cv;
10 int main()
11 {
12     cv::Mat hsvMat;
13     cv::Mat srcImage = cv::imread("D:\\lena.jpg");
14 
15     if (srcImage.empty())
16     {
17         return -1;
18     }
19     cv::imshow("原图像", srcImage);
20     //灰度转换
21     cv::Mat srcGray;
22     cv::cvtColor(srcImage, hsvMat, CV_BGR2HSV);
23     cv::imshow("hsvMat", hsvMat);
24     //初始化灰度阶参数
25     int hbins = 30;
26     int sbins = 32;
27     int histSize[] = { hbins, sbins };
28     //灰度变化范围设置
29     float hranges[] = { 0, 180 };
30     //饱和度变化范围
31     float sranges[] = { 0, 256 };
32     const float* ranges[] = { hranges, sranges };
33     cv::MatND hist;
34 
35     //选取计算直方图通道
36     int channels[] = { 0, 1 };
37     //计算当前通道直方图
38     cv::calcHist(&hsvMat, 1, channels, cv::Mat(), hist, 2, histSize, ranges, true, false);
39     double maxVal = 0;
40     //找到直方图最大值
41     cv::minMaxLoc(hist, 0, &maxVal, 0, 0);
42     int scale = 10;
43     cv::Mat histImage = cv::Mat::zeros(sbins*scale, hbins * scale, CV_8UC3);
44     //遍历H、S通道
45     for (int h = 0; h < hbins; h++)
46     {
47         for (int s = 0; s < sbins; s++)
48         {
49             float binVal = hist.at<float>(h, s);
50             //根据最大值计算变化范围
51             int intensity = cvRound(binVal * 255 / maxVal);
52             //绘图显示
53             cv::rectangle(histImage, cv::Point(h*scale, s*scale),
54                 cv::Point((h + 1)*scale - 1, (s + 1)*scale - 1), cv::Scalar::all(intensity), CV_FILLED);
55         }
56     }
57 
58     cv::imshow("H-S Histogram", histImage);
59     cv::waitKey(0);
60     return 0;
61 }
View Code

 

3.2.3B-G-R直方图 

 1 ////https://blog.csdn.net/gone_huilin/article/details/53222853
 2 #include <opencv2/opencv.hpp>
 3 #include <vector>
 4 #include <iostream>
 5 
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     cv::Mat srcImage = cv::imread("D:\\lena.jpg");
11     if (!srcImage.data)
12         return 1;
13     cv::imshow("srcImage", srcImage);
14     cv::Mat bgr_planes[3];
15     cv::split(srcImage, bgr_planes);
16 
17     // 初始化直方图计算参数
18     int histSize = 256;
19     float range[] = { 0, 256 };
20     const float* histRange = { range };
21     bool uniform = true;
22     bool accumulate = false;
23     cv::Mat b_hist, g_hist, r_hist;
24     // 计算各个通道的直方图
25     calcHist(&bgr_planes[0], 1, 0, cv::Mat(), b_hist, 1,
26         &histSize, &histRange, uniform, accumulate);
27     calcHist(&bgr_planes[1], 1, 0, cv::Mat(), g_hist, 1,
28         &histSize, &histRange, uniform, accumulate);
29     calcHist(&bgr_planes[2], 1, 0, cv::Mat(), r_hist, 1,
30         &histSize, &histRange, uniform, accumulate);
31     // 设置直方图绘图参数
32     int hist_w = 640; int hist_h = 512;
33     int bin_w = cvRound((double)hist_w / histSize);
34     cv::Mat histImage(hist_h, hist_w,
35         CV_8UC3, cv::Scalar(0, 0, 0));
36     // 分别归一化直方图到[ 0, histImage.rows ]
37     normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX,
38         -1, Mat());
39     normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX,
40         -1, Mat());
41     normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX,
42         -1, Mat());
43     // 分别对每个通道进行绘图
44     for (int i = 1; i < histSize; i++)
45     {
46         line(histImage, Point(bin_w*(i - 1),
47             hist_h - cvRound(b_hist.at<float>(i - 1))),
48             Point(bin_w*(i), hist_h -
49                 cvRound(b_hist.at<float>(i))),
50             Scalar(255, 0, 0), 2, 8, 0);
51         line(histImage, Point(bin_w*(i - 1), hist_h -
52             cvRound(g_hist.at<float>(i - 1))),
53             Point(bin_w*(i), hist_h -
54                 cvRound(g_hist.at<float>(i))),
55             Scalar(0, 255, 0), 2, 8, 0);
56         line(histImage, Point(bin_w*(i - 1), hist_h -
57             cvRound(r_hist.at<float>(i - 1))),
58             Point(bin_w*(i), hist_h -
59                 cvRound(r_hist.at<float>(i))),
60             Scalar(0, 0, 255), 2, 8, 0);
61     }
62     imshow("calcHist", histImage);
63     cv::waitKey(0);
64     return 0;
65 }
View Code

 

 1 ////https://blog.csdn.net/dainesao/article/details/79184934
 2 ////3.2.3B-G-R直方图方法2:
 3 #include <opencv2/opencv.hpp>  
 4 #include <opencv2/imgproc/imgproc.hpp>  
 5 
 6 using namespace cv;
 7 
 8 int main()
 9 {
10     Mat srcImage;
11     srcImage = imread("D:\\lena.jpg");
12     imshow("素材图", srcImage);
13     int bins = 256;
14     int hist_size[] = { bins };
15     float range[] = { 0, 256 };
16     const float* ranges[] = { range };
17     MatND redHist, grayHist, blueHist;
18 
19     //进行直方图的计算(红色分量部分)
20     int channels_r[] = { 0 };
21     calcHist(&srcImage, 1, channels_r, Mat(),
22         redHist, 1, hist_size, ranges,
23         true, false);
24 
25     //进行直方图的计算(绿色分量部分)
26     int channels_g[] = { 1 };
27     calcHist(&srcImage, 1, channels_g, Mat(), // do not use mask
28         grayHist, 1, hist_size, ranges,
29         true, // the histogram is uniform
30         false);
31 
32     //进行直方图的计算(蓝色分量部分)
33     int channels_b[] = { 2 };
34     calcHist(&srcImage, 1, channels_b, Mat(), // do not use mask
35         blueHist, 1, hist_size, ranges,
36         true, // the histogram is uniform
37         false);
38 
39     //-----------------------绘制出三色直方图------------------------
40     //参数准备
41     double maxValue_red, maxValue_green, maxValue_blue;
42     minMaxLoc(redHist, 0, &maxValue_red, 0, 0);
43     minMaxLoc(grayHist, 0, &maxValue_green, 0, 0);
44     minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0);
45     int scale = 1;
46     int histHeight = 256;
47     Mat histImage = Mat::zeros(histHeight, bins * 3, CV_8UC3);
48 
49     //正式开始绘制
50     for (int i = 0; i<bins; i++)
51     {
52         //参数准备
53         float binValue_red = redHist.at<float>(i);
54         float binValue_green = grayHist.at<float>(i);
55         float binValue_blue = blueHist.at<float>(i);
56         int intensity_red = cvRound(binValue_red*histHeight / maxValue_red);  //要绘制的高度
57         int intensity_green = cvRound(binValue_green*histHeight / maxValue_green);  //要绘制的高度
58         int intensity_blue = cvRound(binValue_blue*histHeight / maxValue_blue);  //要绘制的高度
59 
60                                                                                  //绘制红色分量的直方图
61         rectangle(histImage, Point(i*scale, histHeight - 1),
62             Point((i + 1)*scale - 1, histHeight - intensity_red),
63             Scalar(255, 0, 0));
64 
65         //绘制绿色分量的直方图
66         rectangle(histImage, Point((i + bins)*scale, histHeight - 1),
67             Point((i + bins + 1)*scale - 1, histHeight - intensity_green),
68             Scalar(0, 255, 0));
69 
70         //绘制蓝色分量的直方图
71         rectangle(histImage, Point((i + bins * 2)*scale, histHeight - 1),
72             Point((i + bins * 2 + 1)*scale - 1, histHeight - intensity_blue),
73             Scalar(0, 0, 255));
74 
75     }
76 
77     //在窗口中显示出绘制好的直方图
78     imshow("图像的RGB直方图", histImage);
79     waitKey(0);
80     return 0;
81 }
View Code

 

 

 3.2.4 自定义直方图

 1 ////https://blog.csdn.net/gone_huilin/article/details/53222859
 2 #include <opencv2/opencv.hpp>
 3 int main()
 4 {
 5     // 图像获取及判断
 6     cv::Mat srcImage = cv::imread("D:\\lena.jpg");
 7     if (!srcImage.data)
 8         return 1;
 9     cv::imshow("srcImage", srcImage);
10     // 灰度转换  
11     cv::Mat srcGray;
12     cv::cvtColor(srcImage, srcGray, CV_BGR2GRAY);
13     // 初始化直方图计算参数
14     const int channels[1] = { 0 };
15     const int histSize[1] = { 256 };
16     // 设定区间[0 60],[61 120],[121 160],[161 220],[221 255]
17     float hranges[6] = { 0, 60, 120, 160, 220, 255 };
18     const float* ranges[1] = { hranges };
19     cv::MatND hist;
20     // 计算直方图
21     cv::calcHist(&srcGray, 1,
22         channels, cv::Mat(),
23         hist, 1, histSize,
24         ranges);
25     // 求直方图中最大值
26     double maxHist = 0;
27     cv::minMaxLoc(hist, 0, &maxHist, 0, 0);
28     // 设置直方图绘图参数
29     int hist_Size = hist.rows;
30     cv::Mat histImg(hist_Size, hist_Size,
31         CV_8U, cv::Scalar(255));
32     // 直方图绘制
33     for (int h = 0; h < hist_Size; h++)
34     {
35         float binVal = hist.at<float>(h);
36         //归一化 根据最大值计算变换范围 
37         int intensity = static_cast<int>(binVal *
38             hist_Size / maxHist);
39         // 绘图直方图信息
40         cv::line(histImg, cv::Point(h, hist_Size),
41             cv::Point(h, hist_Size - intensity),
42             cv::Scalar::all(0));
43     }
44     cv::imshow("histImg", histImg);
45     cv::waitKey(0);
46     return 0;
47 }
View Code

3.2.5灰度直方图均衡

 1 //////////////////////////3.2.5灰度直方图均衡///////////////////////////
 2 ////https://blog.csdn.net/linqianbi/article/details/78603406
 3 #include<opencv2\opencv.hpp>
 4 #include<cmath>
 5 #include<iostream>
 6 using namespace cv;
 7 using namespace std;
 8 Mat MyequalizeHist(Mat &srcImage)
 9 {
10     int nRows = srcImage.rows;
11     int nCols = srcImage.cols;
12 
13     int nSumPix[256];
14     double nProDis[256];
15     double nSumProDis[256];
16     int EqualizeSumPix[256];
17 
18     for (int i = 0; i < 256; i++)
19     {
20         nSumPix[i] = 0;
21         nProDis[i] = 0.0;
22         nSumProDis[i] = 0.0;
23         EqualizeSumPix[i] = 0;
24     }
25 
26     for (int i = 0; i < nRows; i++)
27     {
28         for (int j = 0; j < nCols; j++)
29         {
30             nSumPix[(int)srcImage.at<uchar>(i, j)]++;
31         }
32     }
33 
34 
35     for (int i = 0; i < 256; i++)
36     {
37         nProDis[i] = (double)nSumPix[i] / (nRows * nCols);
38     }
39 
40 
41     nSumProDis[0] = nProDis[0];
42 
43 
44     for (int i = 1; i < 256; i++)
45     {
46         nSumProDis[i] = nSumProDis[i - 1] + nProDis[i];
47     }
48 
49 
50     for (int i = 0; i < 256; i++)
51     {
52         EqualizeSumPix[i] = cvRound((double)nSumProDis[i] * 255);
53     }
54 
55     Mat resultImage(nRows, nCols, srcImage.type());
56     for (int i = 0; i < nRows; i++)
57     {
58 
59         for (int j = 0; j < nCols; j++)
60         {
61 
62             resultImage.at<uchar>(i, j) = EqualizeSumPix[(int)srcImage.at<uchar>(i, j)];
63         }
64     }
65     return resultImage;
66 
67 }
68 int main()
69 {
70     Mat srcIamge = imread("D:\\lena.jpg");
71     if (!srcIamge.data)
72     {
73         printf("image could not load...\n");
74         return -1;
75     }
76     Mat srcGray;
77     //转化为灰度图并且显示
78     cvtColor(srcIamge, srcGray, CV_BGR2GRAY);
79     imshow("srcGray", srcGray);
80 
81     Mat resultImage = MyequalizeHist(srcGray);
82     imshow("res", resultImage);
83 
84     waitKey(0);
85     return 0;
86 }
View Code

 

参考:

https://blog.csdn.net/linqianbi/article/details/78603406

https://blog.csdn.net/xiaowei_cqu/article/details/7606607

https://www.cnblogs.com/wangguchangqing/p/7098213.html

https://blog.csdn.net/sunmc1204953974/article/details/50606395

https://blog.csdn.net/zhulf0804/article/details/52770613/ 

 

3.2.6彩色直方图均衡化

 1 ////3.2.6彩色直方图均衡化方法1:与方法2不同在于使用Mat数组
 2 ////Source code:https://blog.csdn.net/dcrmg/article/details/53677739
 3 ////对RGB三通道各自均衡化后,再组合输出结果
 4 #include <opencv2/highgui/highgui.hpp>    
 5 #include <opencv2/imgproc/imgproc.hpp>
 6 #include <iostream>
 7 
 8 using namespace cv;
 9 
10 int main(int argc, char *argv[])
11 {
12     Mat image = imread("D:\\西藏.jpg");
13     if (image.empty())
14     {
15         std::cout << "打开图片失败,请检查" << std::endl;
16         return -1;
17     }
18     imshow("原图像", image);
19     Mat imageRGB[3];
20     split(image, imageRGB);
21     for (int i = 0; i < 3; i++)
22     {
23         equalizeHist(imageRGB[i], imageRGB[i]);
24     }
25     merge(imageRGB, 3, image);
26     imshow("直方图均衡化图像增强效果", image);
27     waitKey();
28     return 0;
29 }
View Code

 

 

 1 /////https://blog.csdn.net/kuweicai/article/details/73824485
 2 #include<opencv.hpp>
 3 #include<iostream>
 4 
 5 //绘制直方图,src为输入的图像,histImage为输出的直方图,name是输出直方图的窗口名称
 6 void drawHistImg(cv::Mat &src, cv::Mat &histImage, std::string name)
 7 {
 8     const int bins = 256;
 9     int hist_size[] = { bins };
10     float range[] = { 0, 256 };
11     const float* ranges[] = { range };
12     cv::MatND hist;
13     int channels[] = { 0 };
14 
15     cv::calcHist(&src, 1, channels, cv::Mat(), hist, 1, hist_size, ranges, true, false);
16 
17     double maxValue;
18     cv::minMaxLoc(hist, 0, &maxValue, 0, 0);
19     int scale = 1;
20     int histHeight = 256;
21 
22     for (int i = 0; i < bins; i++)
23     {
24         float binValue = hist.at<float>(i);
25         int height = cvRound(binValue*histHeight / maxValue);
26         cv::rectangle(histImage, cv::Point(i*scale, histHeight), cv::Point((i + 1)*scale, histHeight - height), cv::Scalar(255));
27 
28         cv::imshow(name, histImage);
29     }
30 }
31 
32 int main(void)
33 {
34     cv::Mat src, dst;
35 
36     src = cv::imread("D:\\西藏.jpg", CV_LOAD_IMAGE_GRAYSCALE);
37     if (!src.data)
38         std::cout << "ERR";
39     cv::equalizeHist(src, dst);
40 
41     cv::imshow("src", src);
42     cv::imshow("equalizeHist", dst);
43 
44     cv::Mat srcHistImage = cv::Mat::zeros(256, 256, CV_8UC1);
45     cv::Mat dstHistImage = cv::Mat::zeros(256, 256, CV_8UC1);
46     drawHistImg(src, srcHistImage, "srcHistImage");
47     drawHistImg(dst, dstHistImage, "dstHistImage");
48 
49     cvWaitKey(0);
50     return 0;
51 }
View Code

 

由于opencv自带的函数是对灰度图像进行直方图均衡化的,所以不可直接调用函数。需要注意的是对于彩色图像(RGB),直接对三个通道单独进行直方图均衡化,然后合成是不可取的,原因是直方图均衡化并非线性操作,这样会引起彩色失真,可取的方式是将RGB转换到HSV,HSI,YUV 或者YCbCr,然后对亮度(即前面的V, I,Y通道)进度均衡化,这样不会对彩色的色调产生影响,然后转换回RGB空间即可。这里特别推荐最后一个YCbCr,因为它就是专门为数字图像所设计的。

 1 ////// RGB图像转化为YCbCr(HSI,YUV)颜色空间后,对亮度通道进行均衡化运算后再转回RGB空间
 2 //////https://blog.csdn.net/kuweicai/article/details/73824485
 3 #include<opencv.hpp>
 4 #include<iostream>
 5 
 6 //绘制直方图,src为输入的图像,histImage为输出的直方图,name是输出直方图的窗口名称
 7 void drawHistImg(cv::Mat &src, cv::Mat &histImage, std::string name)
 8 {
 9     const int bins = 256;
10     int hist_size[] = { bins };
11     float range[] = { 0, 256 };
12     const float* ranges[] = { range };
13     cv::MatND hist;
14     int channels[] = { 0 };
15 
16     cv::calcHist(&src, 1, channels, cv::Mat(), hist, 1, hist_size, ranges, true, false);
17 
18     double maxValue;
19     cv::minMaxLoc(hist, 0, &maxValue, 0, 0);
20     int scale = 1;
21     int histHeight = 256;
22 
23     for (int i = 0; i < bins; i++)
24     {
25         float binValue = hist.at<float>(i);
26         int height = cvRound(binValue*histHeight / maxValue);
27         cv::rectangle(histImage, cv::Point(i*scale, histHeight), cv::Point((i + 1)*scale, histHeight - height), cv::Scalar(255));
28 
29         cv::imshow(name, histImage);
30     }
31 }
32 
33 int main(void)
34 {
35     cv::Mat src, dst;
36     cv::Mat srcHistImage = cv::Mat::zeros(256, 256, CV_8UC1);
37     cv::Mat dstHistImage = cv::Mat::zeros(256, 256, CV_8UC1);
38 
39     src = cv::imread("D:\\西藏.jpg");
40     if (!src.data)
41         std::cout << "ERR";
42 
43     cv::Mat YCC;
44     cv::cvtColor(src, YCC, cv::COLOR_RGB2YCrCb);
45     //std::vector<cv::Mat> channels;
46     cv::Mat channels[3];
47     cv::split(YCC, channels);
48 
49     drawHistImg(channels[0], srcHistImage, "srcHistImage");
50     cv::equalizeHist(channels[0], channels[0]);//对Y通道进行均衡化
51 
52     cv::merge(channels, 3, YCC);
53     cv::cvtColor(YCC, dst, cv::COLOR_YCrCb2RGB);//重新转换到RGB颜色域
54 
55     cv::imshow("src", src);
56     cv::imshow("dst", dst);
57 
58     drawHistImg(channels[0], dstHistImage, "dstHistImage");
59 
60     cvWaitKey(0);
61     return 0;
62 
63 }
View Code

 主要参考:

https://blog.csdn.net/kuweicai/article/details/73824485

https://blog.csdn.net/dcrmg/article/details/53677739

RGB各通道直方图均衡化后图像与YCbCr 亮度通道Y直方图均衡化后图像对比参考如下:

https://blog.csdn.net/frank_xu_0818/article/details/39232157 和 https://www.cnblogs.com/yoyo-sincerely/p/6159101.html

其他:

https://blog.csdn.net/frank_xu_0818/article/details/39232157

3.2.7~3.2.10 丢了!

3.2.11 直方图的反向投影

反向投影在某一位置的值是源图像在对应位置的像素值的累计。反向投影操作可实现检测输入原图像给定图像块的最匹配区域,一般可用于基于图像内容的检索或查找特定内容。

什么是反向投影直方图呢?简单的说在灰度图像的每个点(x,y),用它对应的直方图的bin的值(就是有多少像素落在bin内)来代替它。所以·如果这个bin的值比较大,那么反向投影显示的结果会比较亮,否则就比较暗。

从统计学的角度,反输出图像象素点的值是观测数组在某个分布(直方图)下的的概率。

所以加入我们已经得到了一个物体的直方图,我们可以计算它在另一幅图像中的反向投影,来判断这幅图像中是否有该物体。

 1 //////https://blog.csdn.net/gone_huilin/article/details/53222966
 2 #include "opencv2/imgproc/imgproc.hpp"
 3 #include "opencv2/highgui/highgui.hpp"
 4 #include <iostream>
 5 
 6 using namespace cv;
 7 using namespace std;
 8 
 9 int main()
10 {
11     // 加载源图像并验证
12     cv::Mat srcImage = cv::imread("D:\\梵高星空.jpg");
13     if (!srcImage.data)
14         return 1;
15     // 转换到 HSV 空间
16     cv::Mat hsvImage;
17     cvtColor(srcImage, hsvImage, CV_BGR2HSV);
18     // Hue 通道分离 
19     cv::Mat hueImage;
20     hueImage.create(hsvImage.size(), hsvImage.depth());
21     int ch[] = { 0, 0 };
22     mixChannels(&hsvImage, 1, &hueImage, 1, ch, 1);
23     // 初始化直方图计算参数
24     int bins = 25;
25     cv::MatND hist;
26     int histSize = MAX(bins, 2);
27     float hue_range[] = { 0, 100 };
28     const float* ranges = { hue_range };
29     // 计算直方图
30     calcHist(&hueImage, 1, 0, cv::Mat(),
31         hist, 1, &histSize, &ranges, true, false);
32     // 归一化直方图
33     normalize(hist, hist, 0, 255, cv::NORM_MINMAX,
34         -1, cv::Mat());
35     // 计算反向投影
36     MatND backproj;
37     calcBackProject(&hueImage, 1, 0, hist, backproj,
38         &ranges, 1, true);
39     // 定义输出图像
40     int w = 320; int h = 360;
41     int bin_w = cvRound((double)w / histSize);
42     cv::Mat histImg = cv::Mat::zeros(w, h, CV_8UC3);
43     for (int i = 0; i < bins; i++)
44     {
45         // 绘制直方图
46         rectangle(histImg, cv::Point(i * bin_w, h),
47             cv::Point((i + 1)*bin_w,
48                 h - cvRound(hist.at<float>(i) * h / 255.0)),
49             cv::Scalar(0, 0, 255), -1);
50     }
51     // 显示源图像与反向投影图像
52     imshow("BackProj", backproj);
53     imshow("srcImage", srcImage);
54     imshow("Histogram", histImg);
55     // 直方图均衡化
56     cv::equalizeHist(backproj, backproj);
57     imshow("backproj_equa", backproj);
58     waitKey(0);
59     return 0;
60 }
View Code

 

 

参考:

https://blog.csdn.net/gone_huilin/article/details/53222966

https://blog.csdn.net/thefutureisour/article/details/7554716

https://www.cnblogs.com/liu-jun/p/3482211.html

https://blog.csdn.net/viewcode/article/details/8209067 

https://blog.csdn.net/u012372584/article/details/18308681

https://blog.csdn.net/Jake_cai/article/details/55802702

 

posted @ 2018-08-13 22:44  BreakofDawn  阅读(433)  评论(0编辑  收藏  举报