OpenCV:calcHist计算图像直方图

2025-12-29 09:57:19

1、calcHist三种函数原型:

opencv中自带了求算图像直方图的函数calhist(),

函数原型如下:

①void calcHist( const Mat* images,

                          int nimages, 

                          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* images,

                          int nimages,

                         const int* channels,

                         InputArray mask, 

                        SparseMat& hist,

                         int dims, 

                        const int* histSize,

                        const float** ranges, 

                        bool uniform=true,

                        bool accumulate=false ); 

③void calcHist( InputArrayOfArrays images, 

                         const vector<int>& channels, 

                         InputArray mask,

                        OutputArray hist, 

                        const vector<int>& histSize, 

                        const vector<float>& ranges, 

                        bool accumulate=false );  

OpenCV:calcHist计算图像直方图

2、calcHist参数详解:

以第一个函数原型为例:

①const Mat* images:为输入图像的指针;

②int nimages:要计算直方图的图像的个数。此函数可以为多图像求直方图,我们通常情况下都只作用于单一图像,所以通常nimages=1。

③const int* channels:图像的通道是一个数组,如果是灰度图像则channels[1]={0};如果是彩色图像则channels[3]={0,1,2};如果只是求彩色图像第2个通道的直方图则channels[1]={1};

④IuputArray mask:掩膜,仅对指定元素操作,默认情况设置为一个空图像,即:Mat()。

⑤OutArray hist:计算得到的直方图

⑥int dims:得到的直方图的维数,灰度图像为1维,彩色图像为3维

⑦const int* histSize:直方图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和

⑧const float** ranges:这是一个二维数组,用来指出每个区间的范围

⑨uniform参数表明直方图是否等距,

⑩accumulate与多图像下直方图的显示与存储有关;

OpenCV:calcHist计算图像直方图

3、注意的地方:

关于calHist计算直方图的结果hist,

hist的结果为统计的灰度级0,1,…,255的数量;

表示一维或三维的矩阵;

对于直方图结果矩阵,访问形式为:

cout<<hist.at<float>(i)<<endl;

OpenCV:calcHist计算图像直方图

4、灰度图的直方图绘制:

#include <opencv2\opencv.hpp>

#include <opencv2\highgui\highgui.hpp>

#include <opencv2\features2d\features2d.hpp>

#include <opencv2\core\core.hpp>

using namespace std; 

using namespace cv; 

int main() 

       Mat srcImage = imread("mask.jpg"); 

       imshow("【原图】", srcImage); 

       int channels = 0; 

       MatND dstHist; 

       //接下来是直方图的每一个维度的柱条的数目 

       int histSize[] = { 256 };

       //如果这里写成int histSize = 256;

       //那么下面调用计算直方图的函数的时候,该变量需要写 &histSize 

       //定义变量用来存储单个维度的数值的取值范围 

       float midRanges[] = { 0, 256 }; 

       const float *ranges[] = { midRanges }; 

       calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false); 

       //calcHist 函数调用结束后,

       //dstHist变量中将储存了直方图的信息;

       //用dstHist的模版函数 at<Type>(i)得到第i个柱条的值 

       //at<Type>(i, j)得到第i个并且第j个柱条的值   

       Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3); 

       double g_dHistMaxValue; 

       minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0); 

       for (int i = 0; i < 256; i++) 

       { 

              int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue); 

              line(drawImage, Point(i, drawImage.rows - 1), Point(i, drawImage.rows - 1 - value), Scalar(255, 0, 0)); 

       }

       imshow("【直方图】", drawImage); 

       waitKey(0); 

       return 0;  

}     

OpenCV:calcHist计算图像直方图

5、彩色直方图的绘制:

int main() 

       Mat srcImage = imread("mask.jpg"); 

       imshow("【原图】", srcImage); 

       int channels = 0; 

       MatND dstHist;  

       int histSize =  256 ;

       float midRanges[] = { 0, 256 }; 

       const float *ranges[] = { midRanges }; 

       calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, &histSize, ranges, true, false); 

       //绘制蓝色通道

       Mat b_drawImage = Mat::zeros(Size(256, 256), CV_8UC3);  

       double g_dHistMaxValue = 0; 

       minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0); 

       for (int i = 0; i < histSize; i++) 

       { 

              int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue); 

              rectangle(b_drawImage,

                     Point(i * 8, b_drawImage.rows - 1),

                     Point(i * 8 + 256 / histSize, b_drawImage.rows - 1 - value) 

                     ,Scalar(255, 0, 0), -1); 

       } 

       imshow("【蓝色通道的直方图】", b_drawImage); 

       //绘制绿色通道 

       channels = 1; 

       calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, &histSize, ranges, true, false); 

       Mat g_drawImage = Mat::zeros(Size(256, 256), CV_8UC3); 

       minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0); 

       for (int i = 0; i < histSize; i++) 

       { 

              int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue); 

              rectangle(g_drawImage,

                     Point(i * 8, g_drawImage.rows - 1),

                     Point(i * 8 + 256 / histSize, g_drawImage.rows - 1 - value),

                     Scalar(0, 255, 0), -1); 

       } 

       imshow("【绿色通道的直方图】", g_drawImage); 

       //绘制红色通道 

       channels = 2; 

       calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, &histSize, ranges, true, false); 

       Mat r_drawImage = Mat::zeros(Size(256, 256), CV_8UC3); 

       minMaxLoc(dstHist, 0, &g_dHistMaxValue, 0, 0); 

       for (int i = 0; i < histSize; i++) 

       { 

              int value = cvRound(dstHist.at<float>(i) * 256 * 0.9 / g_dHistMaxValue); 

              rectangle(r_drawImage,

                     Point(i * 8, r_drawImage.rows - 1),

                     Point(i * 8 + 256 / histSize, r_drawImage.rows - 1 - value),

                     Scalar(0, 0, 255), -1); 

       } 

       imshow("【红色通道的直方图】", r_drawImage); 

       waitKey(0); 

       return 0; 

}  

OpenCV:calcHist计算图像直方图

6、【注】:

calhist()函数求得的直方图返回值是一个一维或三维等的矩阵;不是二维;

通过hist.at<float>(i)格式访问;

OpenCV:calcHist计算图像直方图

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢