OpenCV 中提供了 calcHist 函数来计算图像直方图,其函数原型是:
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 )
各个参数的含义如下:
uniform: 如果为 true 的话,则说明所需计算的直方图的每一维按照它的范围和尺寸大小均匀取值;如果为 false 的话,说明直方图的每一维不是均匀分布取值的,参考参数 ranges 的解释。
accumulate: 表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加。
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat srcImage = imread("E://IM_VIDEO//kobe.jpg");
imshow("ScrImage", 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);
//绘制直方图,首先先创建一个黑底的图像,为了可以显示彩色,所以该绘制图像是一个8位的3通道图像
Mat drawImage = Mat::zeros(Size(256, 256), CV_8UC3);
//任何一个图像的某个像素的总个数有可能会很多,甚至超出所定义的图像的尺寸,
//所以需要先对个数进行范围的限制,用minMaxLoc函数来得到计算直方图后的像素的最大个数
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(0, 0, 255));
}
imshow("hist", drawImage);
waitKey(0);
return 0;
}
运行结果如下:
实例二:将计算和绘制直方图写成函数
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
using namespace std;
using namespace cv;
// 得到图像的直方图
MatND getHistogram(Mat &image)
{
MatND hist;
int channels[] = {0};
int dims = 1;
int histSize[] = {256};
float granges[] = {0, 255};
const float *ranges[] = {granges};
calcHist(&image, 1, channels, Mat(), hist, dims, histSize, ranges);
return hist;
}
// 将图像直方图展示出来
Mat getHistogramImage(Mat &image)
{
MatND hist = getHistogram(image);
Mat showImage(256,256, CV_8U,Scalar(0));
int i;
double maxValue = 0;
minMaxLoc(hist, 0, &maxValue, 0, 0);
for(i = 0; i < 256; i++)
{
float value = hist.at(i);
int intensity = saturate_cast(256 - 256* (value/maxValue));
rectangle(showImage, Point(i,256 - 1), Point((i+1)-1, intensity), Scalar(255));
}
return showImage;
}
//主函数
int main()
{
Mat image = imread("E://IM_VIDEO//kobe.jpg");
if(!image.data)
{
cout << "fail to load the image" << endl;
return 0;
}
Mat showImage = getHistogramImage(image);
namedWindow("image");
imshow("image", image);
namedWindow("showImage");
imshow("showImage", showImage);
waitKey(0);
return 0;
}
运行结果:
实例三:计算和绘制多通道图像的直方图
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
Mat src, dst;
src = imread("E://IM_VIDEO//kobe.jpg");
if( !src.data )
{ return -1; }
vector rgb_planes;
split( src, rgb_planes );
int histSize = 255;
float range[] = { 0, 255 } ;
const float* histRange = { range };
bool uniform = true;
bool accumulate = false;
Mat r_hist, g_hist, b_hist;
// 计算直方图:
calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
// 创建直方图画布
int hist_w = 400;
int hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );
// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
// 在直方图画布上画出直方图
for( int i = 1; i < histSize; i++ )
{
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
}
/// 显示直方图
namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
imshow("calcHist Demo", histImage );
waitKey(0);
return 0;
}
运行结果如下:
参考:
http://blog.csdn.net/liyuanbhu/article/details/50708912
http://blog.csdn.net/qq_23880193/article/details/49669297
http://blog.csdn.net/zhouzhouzf/article/details/9272299
http://blog.csdn.net/lu597203933/article/details/17061173