在直方图计算一节中,介绍了相关图像直方图计算。本节进行回顾一下相关知识,同时加深一步了解图像直方图相关步骤,以及实践一维和二维直方图计算。
typedef struct CvHistogram { int type; CvArr* bins; //存放每个灰度级数目的数组指针 实际上是 mat->data的数据 float thresh[CV_MAX_DIM][2]; //均匀直方图 中每个bin的边界 float** thresh2; //非均匀直方图 CvMatND mat; //直方图数组的内部数据结构 } CvHistogram;其中注意:thresh是一个二维数据,里面存储每个bin的上下边界,对于非均匀直方图,存储在thresh2中,直方图的数据主要存储在CvMatND结构中,bins中其实就是指向CvMatND中的data数据指针,对于密集矩阵,可以通过CvMatND mat直接访问直方图数据 。
CVAPI(CvHistogram*) cvCreateHist( int dims, //直方图维数 int* sizes, //直翻图维数尺寸 int type, //直方图的表示格式 float** ranges CV_DEFAULT(NULL), //图中方块范围的数组 int uniform CV_DEFAULT(1)//归一化标识 );说明:
当uniform=0时直方图是非均匀的,需要用数组对来表示,如果某维数里面有N个bin,需要N+1个数表示,例如,uniform=0,dim =4 , sizes = 1 ,
rangs = [0,2,4,9,10] ,对应的每个bin的统计区级为[0 2] [2 4] [4 9] [9 10] .
void cvReleaseHist( CvHistogram** hist ); //函数 cvReleaseHist释放直方图 (头和数据). //指向直方图的指针被函数所清空。如果 *hist指针 //已经为 NULL, 则函数不做任何事情。 void cvClearHist( CvHistogram* hist ); //函数 cvClearHist 当直方图是稠密数组时将所有 //直方块设置为 0,当直方图是稀疏数组时,除去所 //有的直方块。
一种是采用函数访问:
double cvquerhistValue_nD(CvHistogram* hist,int*idex)
void cvCalcHist( IplImage** image, CvHistogram* hist, int accumulate=0, const CvArr* mask=NULL );直方图计算cvCalcHist( )在在直方图计算一节,详细介绍过,在此略过。
void cvGetMinMaxHistValue(const CvHistogram* hist,
float* min_value, float* max_value,
int* min_idx=NULL, int* max_idx=NULL );
其中函数中参数:
#include "stdafx.h" #include <cv.h> #include <highgui.h> int _tmain(int argc, _TCHAR* argv[]) { IplImage * src= cvLoadImage("pollen.tif"); IplImage* gray_plane = cvCreateImage(cvGetSize(src),8,1); cvCvtColor(src,gray_plane,CV_BGR2GRAY); int hist_size = 256; //直方图尺寸 int hist_height = 256; float range[] = {0,255}; //灰度级的范围 float* ranges[]={range}; //创建一维直方图,统计图像在[0 255]像素的均匀分布 CvHistogram* gray_hist; gray_hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1); //计算灰度图像的一维直方图 printf("dim:%d\n",gray_hist->mat.dims); //访问直方图 printf("num of bin:%d\n",gray_hist->mat.dim[0].size); printf("low of dim:%f\n",gray_hist->thresh[0][0]); printf("up of dim:%f\n",gray_hist->thresh[0][1]); cvCalcHist(&gray_plane,gray_hist,0,0); for (UINT i = 0 ; i < gray_hist->mat.dim->size ; i ++){ //访问直方图 printf("%d_bin:%f--",i+1,cvQueryHistValue_1D(gray_hist,i)); printf("%d_bin:%f\n",i + 1 ,*(gray_hist->mat.data.fl + i)); } cvNormalizeHist(gray_hist,1.0); //归一化直方图 int scale = 2; //创建一张一维直方图的“图”,横坐标为灰度级,纵坐标为像素个数(*scale) IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale,hist_height),8,3); cvZero(hist_image); float max_value = 0; cvGetMinMaxHistValue(gray_hist, 0,&max_value,0,0); //统计直方图中的最大直方块 for(int i=0;i<hist_size;i++){ float bin_val = cvQueryHistValue_1D(gray_hist,i); //像素i的概率 int intensity = cvRound(bin_val*hist_height/max_value); //要绘制的高度 cvRectangle(hist_image, cvPoint(i*scale,hist_height-1), cvPoint((i+1)*scale - 1, hist_height - intensity), CV_RGB(255,255,255)); } cvNamedWindow("GraySource", 1 ); cvShowImage("GraySource",gray_plane); cvNamedWindow("H-S Histogram", 1 ); cvShowImage("H-S Histogram", hist_image ); cvWaitKey(0); return 0; }
#include "stdafx.h" #include <cv.h> #include <highgui.h> int _tmain(int argc, _TCHAR* argv[]) { IplImage * src= cvLoadImage("iris.tif"); IplImage* r_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* g_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* b_plane = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* planes[] = { r_plane, g_plane }; cvCvtPixToPlane( src, b_plane, g_plane, r_plane, 0 ); //将HSV图像分离到不同的通道中 int r_bins =256, b_bins = 256; // 生成二维直方图数据结构 CvHistogram* hist; int hist_size[] = { r_bins, b_bins }; float r_ranges[] = { 0, 255 }; float b_ranges[] = { 0, 255 }; float* ranges[] = { r_ranges,b_ranges }; hist = cvCreateHist( 2, hist_size, CV_HIST_ARRAY, ranges, 1); cvCalcHist( planes, hist, 0, 0 ); //计算一张或多张单通道图像image(s) 的直方图 int scale = 2; //创建一张一维直方图的“图”,横坐标为灰度级,纵坐标为像素个数(*scale) IplImage* hist_image = cvCreateImage(cvSize(r_bins * scale, b_bins * scale),8,3); cvZero(hist_image); float max_value = 0; cvNormalizeHist(hist,1.0); cvGetMinMaxHistValue(hist, 0,&max_value,0,0); for( int h = 0; h < r_bins; h++ ){ for( int s = 0; s < b_bins; s++ ){ float bin_val = cvQueryHistValue_2D( hist, h, s ); //查询直方块的值 int intensity = cvRound( bin_val * 255 / max_value ); cvRectangle( hist_image, cvPoint( h*scale, s*scale ), cvPoint( (h+1)*scale - 1, (s+1)*scale - 1), CV_RGB(intensity,intensity,intensity),CV_FILLED); } } cvNamedWindow("Source"); cvShowImage("Source",src); cvNamedWindow("H-S Histogram", 1 ); cvShowImage("H-S Histogram", hist_image); cvWaitKey(0); return 0; }
处理的显示形式不是opencv例子那里的形式,这里采用R分量为X轴,B分量为Y轴,r,b中存储的量为X Y分别为响应值的统量。
如有错误,请多多指正。谢谢!