多语言展示
当前在线:805今日阅读:176今日分享:34

OpenCV:calcHist计算图像直方图

绪:直方图可展示图像中的像素分布,是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布。本文主要介绍opencv中绘制直方图的函数calHist的格式和用法;
工具/原料

OpenCV 2410

方法/步骤
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& channels,                          InputArray mask,                        OutputArray hist,                         const vector& histSize,                         const vector& ranges,                         bool accumulate=false );

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与多图像下直方图的显示与存储有关;

3

注意的地方:关于calHist计算直方图的结果hist,hist的结果为统计的灰度级0,1,…,255的数量;表示一维或三维的矩阵;对于直方图结果矩阵,访问形式为:cout<(i)<

4

灰度图的直方图绘制:#include #include #include #include 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(i)得到第i个柱条的值        //at(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(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;  }

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(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(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(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; }

6

【注】:calhist()函数求得的直方图返回值是一个一维或三维等的矩阵;不是二维;通过hist.at(i)格式访问;

注意事项
1

hist.at(i):访问的格式

2

彩色直方图的生成;

推荐信息