zoukankan      html  css  js  c++  java
  • 3.2直方图处理

    3.2.1灰度直方图

     1 //////3.2.1灰度直方图方法2:
     2 ////Source Code:https://blog.csdn.net/gone_huilin/article/details/53222806
     3 #include <opencv2opencv.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("
    
    			欢迎来到直方图的世界!
    ");
    12     printf("
    
      ----------------------------------------------------------------------------
    ");
    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("直方图条数不能为零!
    ");
        }
        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 
    ",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<opencv2opencv.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...
    ");
    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

  • 相关阅读:
    DOM
    JavaScript 数组的方法总结
    vuex 状态持久化插件 —— vuex-persistedstate
    移动端1px细线
    CSS多行文本并显示省略号
    Java面试题
    Git提交分支
    Redis的安装配置
    Spring IoC
    单例模式
  • 原文地址:https://www.cnblogs.com/thebreakofdawn/p/9471537.html
Copyright © 2011-2022 走看看