这是opencv中文版第七章的一个例子,主要参考了这两篇博客进行源码的理解http://blog.csdn.net/cwjcwj520/article/details/7421411和http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/histogram_calculation/histogram_calculation.html
进行归一化的原因说明:
1、归一化直方图后再显示直方图,由于bin的值归一化之后太小,可能造成显示出来基本看不见的情况.此时可以归一化直方图的颜色值(映射到(0,255))
2、不归一化直方图,可明显的显示出bin值. 但是bin超过了255,显示出来就没有意义了.所以直方图颜色值也要归一化
#include "cv.h"
#include "highgui.h"
int main()
{
//读入测试图片
IplImage *src=cvLoadImage("test.jpg");
if(!src)
return -1;
//创建一个hsv图像
IplImage *hsv=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
cvCvtColor(src,hsv,CV_BGR2HSV);//色彩空间的转换
IplImage *h_plane=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage *s_plane=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage *v_plane=cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage *planes[]={h_plane,s_plane};
//可以看作cvSplit是他的宏:分割多通道数组成几个单通道数组或者从数组中提取一个通道
cvCvtPixToPlane(hsv,h_plane,s_plane,v_plane,NULL);
//h_bins和s_bins表示H,S特征空间的子区段的数目;
//例如:h_ranges={0,180},而h_plane这个空间的子区段数目为30,
//所以每个区段为{0,6},{7,13}....{172,180}
int h_bins=30,s_bins=32;
CvHistogram *hist;
/*-----此段是为下面创建直方图做准备,设置的一些直方图参数-----*/
int hist_size[]={h_bins,s_bins};//直方图矩阵大小
float h_ranges[]={0,180};
float s_ranges[]={0,255};
float *ranges[]={h_ranges,s_ranges};//二维数组
/*-----------------------------------------------------------*/
//创建直方图,
hist=cvCreateHist(2,
hist_size,
CV_HIST_ARRAY,
ranges,
1);
//计算图像的直方图,planes是IplImage**类型
cvCalcHist(planes,hist,0,0);
//归一化得到的直方图
cvNormalizeHist(hist,1.0);
int scale=10;
IplImage *hist_img=cvCreateImage(cvSize(h_bins*scale,s_bins*scale),IPL_DEPTH_8U,3);
//将矩阵数组置0
cvZero(hist_img);
float max_value=0;
//取得归一化后直方图中的最大值
cvGetMinMaxHistValue(hist,0,&max_value,0,0);
for(int h=0;h<h_bins;h++)
{
for(int s=0;s<s_bins;s++)
{
float bin_val=cvQueryHistValue_2D(hist,h,s);
int intensity=cvRound(bin_val*255/max_value);
cvRectangle(hist_img,
cvPoint(h*scale,s*scale),
cvPoint((h+1)*scale-1,(s+1)*scale-1),
CV_RGB(intensity,intensity,intensity),
CV_FILLED);
}
}
cvNamedWindow("source",1);
cvShowImage("source",src);
cvNamedWindow("H_S Histogram",1);
cvShowImage("H_S Histogram",hist_img);
cvWaitKey(0);
return 0;
}
程序使用的源图片:
程序运行的结果如下: