和之前的一篇blog【http://blog.csdn.net/lu597203933/article/details/14104505】一样,这篇是opencv2的Mat格式。
一:一维直方图
Code:
int main()
{
Mat image = imread("F:\\huangrong.jpg", 0);
if(!image.data)
{
cout << "fail to load image" << endl;
return 0;
}
MatND hist; // 在cv中用CvHistogram *hist = cvCreateHist
int dims = 1;
float hranges[] = {0, 255};
const float *ranges[] = {hranges}; // 这里需要为const类型
int size = 256;
int channels = 0;
// 计算图像的直方图
calcHist(&image, 1, &channels, Mat(), hist, dims, &size, ranges); // cv 中是cvCalcHist
int scale = 1;
Mat imageShow(size * scale, size, CV_8U, Scalar(0));
// 获取最大值和最小值
double minVal = 0;
double maxVal = 0;
minMaxLoc(hist,&minVal, &maxVal, 0, 0); // cv中用的是cvGetMinMaxHistValue
//显示直方图的图像
int hpt = saturate_cast<int>(0.9 * size);
for(int i = 0; i < 256; i++)
{
float value = hist.at<float>(i); // 注意hist中是float类型 cv中用cvQueryHistValue_1D
int realValue = saturate_cast<int>(value * hpt/maxVal);
//line(imageShow, Point(i, size - 1), Point(i, size - realValue), Scalar(0));
rectangle(imageShow,Point(i*scale, size - 1), Point((i+1)*scale - 1, size - realValue), Scalar(255));
}
namedWindow("showImage");
imshow("showImage", imageShow);
waitKey(0);
return 0;
}
Explaination:
<1>代码中有注释将mat格式与cv格式进行了比对,大家注意
<2> float value = hist.at<float>(i);
要注意直方图数据为浮点类型
<3>画出直方图其实有多种方式,可以使用line或rectangle都可以
Result:
二:二维直方图
Code:
int main()
{
Mat image = imread("F:\\baboon.jpg", 1);
if(!image.data)
{
cout << "fail to load image" << endl;
return 0;
}
MatND hist; // 在cv中用CvHistogram *hist = cvCreateHist
int dims = 2;
float r_hranges[] = {0, 255};
float g_hranges[] = {0, 255};
const float *ranges[] = {r_hranges, g_hranges}; // 这里需要为const类型
int size[2] = {256, 256};
int channels[] ={0,1}; //代表 r g通道 2代表b通道
// 计算图像的直方图
calcHist(&image, 1, channels, Mat(), hist, dims, size, ranges); // cv 中是cvCalcHist
int scale = 1;
Mat imageShow(size[0] * scale, size[1]*scale, CV_8UC3, Scalar(255));
// 获取最大值和最小值
double minVal = 0;
double maxVal = 0;
minMaxLoc(hist,&minVal, &maxVal, 0, 0); // cv中用的是cvGetMinMaxHistValue
//显示直方图的图像
//int hpt = saturate_cast<int>(0.9 * size[]);
for(int i = 0; i < 256; i++)
{
for(int j = 0; j < 256; j++)
{
float value = hist.at<float>(i,j); // 注意直方图的值是float类型 cv中用cvQueryHistValue_1D
int realValue = saturate_cast<int>(value * size[0]/maxVal);
//line(imageShow, Point(i, size - 1), Point(i, size - realValue), Scalar(0));
rectangle(imageShow,Point(i*scale, j*scale), Point( ((i+1)*scale - 1), (j+1)*scale - 1), Scalar(realValue,realValue, realValue));
}
}
namedWindow("baboon");
namedWindow("showImage");
imshow("showImage", imageShow);
imshow("baboon", image);
waitKey(0);
return 0;
}
Explaination:
需要注意的是取二维的通道数是通过变量channels来取得的,不需要将图片再进行split
Result:
另外推荐小魏的blog,关于直方图的描述写的也非常好:
链接:http://blog.csdn.net/xiaowei_cqu/article/details/8833799【Mat格式】
http://blog.csdn.net/xiaowei_cqu/article/details/7600666【cv】
作者:小村长 出处:http://blog.csdn.net/lu597203933 欢迎转载或分享,但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流!)