OpenCV--数字图像灰度直方图

图像灰度直方图的定义:

灰度直方图是灰度级的函数,它表示图像中具有某种灰度级的像素的个数,反映了图像中某种灰度出现的频率。


如果将图像总像素亮度(灰度级别)看成是一个随机变量,则其分布情况就反映了图像的统计特性,这可用probability density function (PDF)来刻画和描述,表现为灰度直方图。


一维直方图的结构表示为


色彩直方图是高维直方图的特例,它统计色彩的出现频率,即色彩的概率分布信息。通常这需要一定的量化过程,将色彩分成若干互不重叠的种类。一般不直接在RGB色彩空间中统计,而是在将亮度分离出来后,对代表色彩部分的信息进行统计,如在HSI空间的HS子空间、YUV空间的UV子空间,以及其它反映人类视觉特点的彩色空间表示中进行。

OpenCV中的直方图CvHistogram

OpenCV中用CvHistogram表示多维直方图
typedef struct CvHistogram
{
    int     type;
    CvArr*  bins;      //存放每个灰度级数目的数组指针 
    float   thresh[CV_MAX_DIM][2]; /* for uniform histograms 均匀直方图*/
    float** thresh2; /* for non-uniform histograms 非均匀直方图*/
    CvMatND mat; /* embedded matrix header for array histograms 直方图数组的内部数据结构*/
}
CvHistogram;

OpenCV中用CvHistogram表示多维直方图
第一个成员type用来指定第二个成员bins的类型。OpenCv中常见到CvArr*的接口,可以用以指定诸如CvMat、CvMatND、IplImage的类型,其实CvArr*的是一个指向void的指针。在函数内部有时需要得到确切的指向类型,这就需要type来指定。
thresh用来指定统计直方图分布的上下界。比如[0 255]表示用来统计图像中像素分别在灰度级[0 255]区间的分布情况,CV_MAX_DIM对应直方图的维数,假如设定二维红-蓝直方图的thresh为[0 255;100 200],就是分别统计红色图像灰度级在[0 255]以及蓝色图像在灰度级[100 200]的分布情况。
thresh用以指定均匀直方图的分布,我们按每个像素理解自然是“均匀分布”,其实也可以统计像素在几个区间的分布。如果统计像素在2个区间的分布,则对应[0 255]的上下界,均匀分布统计的区间即[0 127] [127 255]分布的概率,这也是为什么thresh第二个维数默认为2——会自动均分上下界;而thresh2指定非均匀的分布,这就需要指定每个区间的上下界,如果要统计直方图在区间(0,10,100,255)的分布,那需要指定thresh2的一个维度为[0 10 100 255],所以用float**形式表示。
mat简单说就是存储了直方图的信息,即我们统计的直方图分布概率。

创建直方图 cvCreateHist()

CvHistogram* cvCreateHist(   
						  int dims, //直方图维数   
						  int* sizes,//直方图维数尺寸  
						  int type, //直方图的表示格式  
						  float** ranges=NULL, //图中方块范围的数组  
						  int uniform=1 //归一化标识  
    );  
size数组的长度为dims,每个数表示分配给对应维数的bin的个数。如dims=3,则size中用[s1,s2,s3]分别指定每维bin的个数。
type有两种:CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat。
ranges就是那个复杂的不好理解的thresh的范围,他的内容取决于uniform的值。uniform为0是均匀的,非0时不均匀。

计算图像直方图的函数为CalcHist()

void cvCalcHist(   
				IplImage** image, //输入图像(也可用CvMat**)  
				CvHistogram* hist, //直方图指针  
				int accumulate=0, //累计标识。如果设置,则直方图在开始时不被清零。  
				const CvArr* mask=NULL //操作 mask, 确定输入图像的哪个象素被计数  
    ); 

一维直方图的实现:

#include <cxcore.h>
#include <cv.h>
#include <highgui.h>

void main()
{
	IplImage* src=cvLoadImage("./LENA.bmp")	;
	IplImage* gray_plane=cvCreateImage(cvGetSize(src),8,1);
	cvCvtColor(src,gray_plane,CV_RGB2GRAY);

	int hist_size=256;//直方图尺寸
	int hist_height=256;
	float range[]={0,255};//灰度级范围
	float* ranges[]={range};
	//创建一维直方图,统计图像在[0 255]像素的均匀分布 
	CvHistogram* gray_hist=cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
	//计算灰度图像的一维直方图
	cvCalcHist(&gray_plane,gray_hist,0,0);
	//归一化直方图
	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)//线条颜色 (RGB) 
			);
	}

	//创建窗口
	cvNamedWindow("GraySource",CV_WINDOW_AUTOSIZE);
	//显示图像
	cvShowImage("GraySource",gray_plane);

	cvNamedWindow("H-S Histogram",1);
	cvShowImage( "H-S Histogram", hist_image );  

	cvWaitKey(0);
	
	//释放头和图像数据 
	cvReleaseImage(&gray_plane);
	cvReleaseImage(&hist_image);
}

结果:








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值