代码演示:
#include <iostream> #include <cv.h> #include <highgui.h> #include <cxcore.h> using namespace std; int main() { IplImage *src = cvLoadImage("f:\\images\\lena.jpg"); cout<<"total_pixel : "<<src->width*src->height<<endl; assert(src); IplImage *hsv = cvCreateImage(cvGetSize(src),8,3); cvCvtColor(src,hsv,CV_BGR2HSV); IplImage *h_plane = cvCreateImage(cvGetSize(src),8,1); IplImage *s_plane = cvCreateImage(cvGetSize(src),8,1); IplImage *v_plane = cvCreateImage(cvGetSize(src),8,1); IplImage *planes[] = {h_plane,s_plane}; cvCvtPixToPlane(hsv,h_plane,s_plane,v_plane,0); //build the histogram and compute its contents int h_bins = 30 ,s_bins = 36; int hist_size[] = {h_bins,s_bins}; float h_ranges [ ] = {0,256}; //saturation varies frome 0 to 255( pure spectrum color float s_ranges[] = {0,256}; float *ranges[] = {h_ranges,s_ranges}; int scale = 10; IplImage *hist_img = cvCreateImage(cvSize(h_bins*scale,s_bins*scale),8,3); CvHistogram *hist; float max_value = 0; int h,s; hist = cvCreateHist(2,hist_size,CV_HIST_ARRAY,ranges,1); cvCalcHist(planes,hist,0,0); cvGetMinMaxHistValue(hist,0,&max_value,0,0); cvZero(hist_img); float cnt = 0; for(h = 0;h<h_bins;h++){ for(s = 0;s<s_bins;s++){ float bin_val = cvQueryHistValue_2D(hist,h,s); cnt += bin_val; 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,0,0), CV_FILLED); } } cout<<"cnt = "<<cnt<<endl; cvShowImage("h_s histogram " ,hist_img); cvShowImage("src",src); cvWaitKey(); cvReleaseHist(&hist); cvReleaseImage(&src); cvReleaseImage(&hist_img); cvDestroyAllWindows(); }
total_pixel = cnt ;
先来看看:
CVAPI(CvHistogram*) cvCreateHist( int dims, int* sizes, int type,
float** ranges CV_DEFAULT(NULL),
int uniform CV_DEFAULT(1));
//这里ranges表示的是直方图的范围 , 某一维度d , ranges 在uniform下为[0,256] , 且size[d] 为10 ,即将此维分成4份
则[0,64) , [64,128) , [128,192) , [192,256) 包含左边,不包含右边
CV_INLINE void cvCalcHist( IplImage** image, CvHistogram* hist,
int accumulate CV_DEFAULT(0),
const CvArr* mask CV_DEFAULT(NULL) );
image 传入的图像指针,若用cvCreateHist 生成的hist有 dims 个维度, 则传入的图像就得有dims个 ,图像数组 IplImage *image = {h_plane , s_plane} (包含两张图像)
!且图像的大小一样(width ,height)
hist 即一般用cvCreateHist 生成的
accumulate 若为0 ,则在计算此图像的直方图前,将hist先清零 .. 若非0, 则在原来的基础上累加
mask 掩码 , , mask的必须为8位无符号整型 ,单通道图像IplImage 或者CvMat结构 ,将mask看成二值图,非零的地方即为使用(统计)的地方 , 为0时对应的地方不参与运算操作
cvCalcHist 即为统计图像的像素点 ,,
拿上面的程序来说,就是比第一幅图在 第i个bin 内 且第二幅图在第j 个bin内 ,同时满足时即为hist在 (i,j)处的值(像素个数)
如对于RGB图像,我们可心通过求RGB三个通道的图像,求其在 50<=R<100 且0<=G<30且20<=B<80的像素个数 ,
此时只要选取3个维度,每个维度的size 都为1 , int size[] = { 1 , 1 ,1 },将uniform设置为0 , 设置float *ranges[3] = {50 100;
0 30;
20 80}
再调用cvCalcHist 即可
然后用
cvQueryHistValue_2D(hist,0,0)取得结果