opencv2 直方图之calchist函数使用(转)

OpenCV提供了calcHist函数来计算图像直方图。

         其中C++的函数原型如下:void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray
hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=
false );

          void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, SparseMat&
hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=
false );

         参数解释:

        arrays。输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度(CV_8U or CV_32F)。同时一副图像可以有多个channes。

        narrays。输入的图像的个数。

        channels。用来计算直方图的channes的数组。比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,

那么输入就一共有4个channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计

算直方图。

        mask。掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算

直方图。

        hist。计算出来的直方图

        dims。计算出来的直方图的维数。

        histSize。在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数。

        ranges。用来进行统计的范围。比如

         float rang1[] = {0, 20};

        float rang2[] = {30, 40};

        const float *rangs[] = {rang1, rang2};那么就是对0,20和30,40范围的值进行统计。

       uniform。每一个竖条的宽度是否相等。

       accumulate。Accumulation flag. If it is set, the histogram is not cleared in the beginning
when it is allocated. This feature enables you to compute a single histogram from several
sets of arrays, or to update the histogram in time.  是否累加。如果为true,在下次计算的时候不会首先清空hist。这个地方我是这样理解的,不知道有没有错,

请高手指点。

 1 Histogram1D::Histogram1D(){  
 2     histSize[0] = 256;   
 3     hranges[0] = 0.0;  
 4     hranges[1] = 255.0;  
 5     ranges[0] = hranges;  
 6     channels[0] = 0;  
 7 }  
 8   
 9 cv::MatND Histogram1D::getHistogram(const cv::Mat &image){  
10     cv::MatND hist;  
11     cv::calcHist(&image,   //source image  
12              1,        //histogram from 1 image only  
13              channels, //the channel used  
14              cv::Mat(),//no mask is uesd  
15              hist,     //the resulting histogram  
16              1,        //it is a 1D histogram  
17              histSize, //number of bins  
18              ranges    //pixel value range  
19                 );//直方图函数  
20     return hist;  
21 }  

下面是计算1维图像的直方图:

cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image){  
    //compute histogram first  
    cv::MatND hist = getHistogram(image);  
    //get min and max bin values  
    double maxVal = 0;  
    double minVal = 0;  
    cv::minMaxLoc(hist,&minVal,&maxVal,0,0);  
    //Image on which to display histogram  
    cv::Mat histImg(histSize[0],histSize[0],CV_8U,cv::Scalar(255));  
    //set highest point at 90% of nbins   
    int hpt = static_cast<int>(0.9*histSize[0]);  
    //Draw a vertical line for each bin   
    for (int h =0;h<histSize[0];h++)  
{  
        float binVal = hist.at<float>(h);  
        int intensity = static_cast<int>(binVal*hpt/maxVal);  
        cv::line(histImg,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0));  
    }  
    return histImg;  
}  

计算H-S直方图分布:

/********************************************* 
             内容:计算H-S 直方图分布       
             时间:2013 5.27 
         作者:恋上蛋炒面       
*********************************************/  
#include <opencv2/core/core.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
using namespace cv;  
  
void main()  
{  
    Mat source = imread("baboon.jpg");  
    namedWindow("Source");  
    imshow("Source",source);  
    Mat hsv;  
    cvtColor(source,hsv,CV_BGR2HSV);  
    //Quantize the hue to 60 levels  
    //and the saturation to 64 levels  
    int hbins = 60,sbins = 64;  
    int histSize[] = {hbins,sbins};  
   int histSize[] = {hbins,sbins};  
    //hue varies from 0 to 179  
    float hranges[] = {0,180};  
    //saturation varies from 0 to 255  
    float sranges[] = {0,255};  
    const float *ranges[] = {hranges,sranges};  
    //two channels 0th,1th  
    int channels[] = {0,1};  
    MatND hist;  
    //compute h-s histogram  
    calcHist(&hsv,1,channels,Mat(),hist,2,histSize,ranges);  
    //get the max value  
    double maxVal = .0;  
    minMaxLoc(hist,0,&maxVal,0,0);  
    int scale = 8;  
    //show the histogram on the image  
    Mat histImg = Mat::zeros(sbins*scale,hbins*scale,CV_8UC3);  
    for (int h = 0;h < hbins;h++)  
{  
        for (int s = 0;s<sbins;s++)  
        {  
            float binVal = hist.at<float>(h,s);  
            int intensity = cvRound(binVal*0.9*255/maxVal);  
            rectangle(histImg,Point(h*scale,s*scale),Point((h+1)*scale-1,(s+1)*scale-1),Scalar::all(intensity),CV_FILLED);  
        }  
    }  
  
    namedWindow("H-S Histogram");  
    imshow("H-S Histogram",histImg);  
    imwrite("hshistogram.jpg",histImg);  
    waitKey(0);  
}  

  RGB直方图:

 1 #include <opencv2/core/core.hpp>  
 2 #include <opencv2/highgui/highgui.hpp>  
 3 #include <opencv2/imgproc/imgproc.hpp>  
 4   
 5 #include <fstream>  
 6   
 7 using namespace cv;  
 8 using namespace std;  
 9   
10 void main()  
11 {  
12     //Mat source = imread("red.jpg");  
13     Mat source = imread("baboon.jpg"); //读取图片  
14     //Mat source(300,300,CV_8UC3,Scalar(1,1,244));  
15     //imwrite("red.jpg",source);  
16     namedWindow("Source");//窗口显示图片  
17     imshow("Source",source);  
18     //初始化calcHist函数的参数  
19     int channels_r[1],channels_g[1],channels_b[1],histSize[1],range;  
20     float hranges[2];  
21     const float *ranges[1];  
22     histSize[0] = 256;  
23     hranges[0] = 0.0;  
24     hranges[1] = 255.0;  
25     ranges[0] = hranges;  
26     channels_b[0] = 0;  
27     channels_g[0] = 1;  
28     channels_r[0] = 2;  
29     MatND hist_r,hist_g,hist_b;  
30   
31     double max_val_r,max_val_g,max_val_b;  
32     Mat histImage(histSize[0],3*histSize[0],CV_8UC3); //定义一个显示直方图的图片,长256*3 高256  
33     //R  
34     calcHist(&source,1,channels_r,Mat(),hist_r,1,histSize,ranges);//分别计算R,G,B的直方图分布  
35     minMaxLoc(hist_r,0,&max_val_r,0,0);//计算直方图中统计最大值  
36     //G  
37     calcHist(&source,1,channels_g,Mat(),hist_g,1,histSize,ranges);  
38     minMaxLoc(hist_g,0,&max_val_g,0,0);  
39     //B  
40     calcHist(&source,1,channels_b,Mat(),hist_b,1,histSize,ranges);  
41     minMaxLoc(hist_b,0,&max_val_b,0,0);  
42   
43     //将r,g,b的最大统计值,以及像素点从0-255的统计值写入txt中  
44     ofstream outfile1("d:\r.txt");  
45     ofstream outfile2("d:\g.txt");  
46     ofstream outfile3("d:\b.txt");  
47   
48     //在txt中写入最大统计值  
49     outfile1<<"max_val_r = "<<max_val_r<<endl;  
50     outfile2<<"max_val_g = "<<max_val_g<<endl;  
51     outfile3<<"max_val_b = "<<max_val_b<<endl;  
52   
53     for (int i =0;i<histSize[0];i++)  
54     {         
55         //R,G,B= i的统计值  
56         float binVal_r = hist_r.at<float>(i);  
57         float binVal_g = hist_g.at<float>(i);  
58         float binVal_b = hist_b.at<float>(i);  
59         //统一R,G,B统计值的大小,以高度的90%封顶  
60         int intensity_r = static_cast<int>(0.9*histSize[0]*binVal_r/max_val_r);  
61         outfile1<<i<<" "<<binVal_r<<" "<<intensity_r<<endl;  
62         int intensity_g = static_cast<int>(0.9*histSize[0]*binVal_g/max_val_g);  
63         outfile2<<i<<" "<<binVal_g<<" "<<intensity_g<<endl;  
64         int intensity_b = static_cast<int>(0.9*histSize[0]*binVal_b/max_val_b);  
65         outfile3<<i<<" "<<binVal_b<<" "<<intensity_b<<endl;  
66         //画出R,G,B的直方图直线  
67         line(histImage,Point(i,histImage.rows),Point(i,histImage.rows-intensity_r),Scalar(0,0,255));  
68         line(histImage,Point(i+histSize[0],histImage.rows),Point(i+histSize[0],histImage.rows-intensity_g),Scalar(0,255,0));  
69         line(histImage,Point(i+histSize[0]*2,histImage.rows),Point(i+histSize[0]*2,histImage.rows-intensity_b),Scalar(255,0,0));  
70     }  
71     namedWindow("RGB Histogram");  
72     imshow("RGB Histogram",histImage);  
73  imwrite("RGB_Histogram.jpg",histImage);  
74     waitKey(0);  
75 }  
原文地址:https://www.cnblogs.com/wyuzl/p/6702785.html