代码演示:
#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)取得结果