【精品博文】建立灰度直方图
(1)基本概念
如果将图像中像素的灰度级别看作是一个随记变量(概率论中学到的随记变量,对后续直方图均匀化的推到至关重要),则其分布的情况就可以用概率密度函数(PDF)来刻画和描述,即表现为灰度直方图(histogram),它表示图像中具有某种灰度级像素的个数,反映了每种灰度出现的频率。灰度直方图的横坐标是灰度级,纵坐标是该灰度级像素的个数(出现的频度),是图像基本的统计特性。
从基本概念中可知,直方图是一幅图像中各像素灰度值出现次数的统计结果,它只反映该图像中不同灰度值出现的次数(或频数),而未反映这一灰度值像素所在的位置,也就是说,直方图只包含了该图像中某一灰度值像素出现的概率,而丢失了其所在的位置信息。
(2)编码实现
MATLAB的图像工具箱提供了imhist函数来显示图像的灰度直方图,其语法形式如下:
imhist(I);
imhist(I,n);
[counts,x]=imhist(…);
其中,I是待计算灰度直方图的图像。参数n是指定的灰度级数目,对于灰度图像而言,默认情况下n为256,即0~255。对于二值图像而言,n为2,即0~1两个灰度级。若指定参数n,则会将所有灰度级均匀分布在n个小区间内,而非全部展开。返回值counts和x为直方图的数据向量和对应的灰度区间向量,我就理解为直方图的纵坐标向量和横坐标向量。
现成的函数可以调用固然方便,但会屏蔽内部实现机理和算法,也不便于以后移植,因此我决定以后的学习都尽量自己编写函数。虽然不太会matlab编程,但我相信也不难掌握。下面就开始自己编程建立灰度直方图。
I=rgb2gray(imread('2.jpg')); %获取并转换成灰度图像 [m,n]=size(I); %获得图像大小,m为行数,n为列数 k=m*n; %总像素个数 y=zeros(1,256); %用来存放灰度级统计结果数据的向量 for i=1:m for j=1:n y(I(i,j)+1) = y(I(i,j)+1) + 1; %灰度级从0~255,而向量y的下标从1~256 end end subplot(1,2,1),imhist(I),title('Original Histogram'); subplot(1,2,2),bar(y),title('My Histogram'); clear
可以看到,从像素灰度级的分布来讲,两幅图几乎是一样的,但还有些小缺陷:
1.两个直方图的纵坐标刻度不一样,差了一个级别,因此乍看起来不太一样.
2.bar(y)函数的这一用法,默认横坐标的刻度范围为1~length(y),本程序中即1~256,这与灰度级的范围0~255有一个偏差,虽然对观察亮度分布及对比度之类的影响不大,但还是不够精确。
针对以上两个缺陷,改进的代码如下:
I=rgb2gray(imread('2.jpg')); %获取并转换成灰度图像 [m,n]=size(I); %获得图像大小,m为行数,n为列数 k=m*n; %总像素个数 y=zeros(1,256); %用来存放灰度级统计结果数据的向量 for i=1:m for j=1:n y(I(i,j)+1) = y(I(i,j)+1) + 1; %灰度级从0~255,而向量y的下标从1~256 end end subplot(1,2,1),imhist(I),title('Original Histogram'); x=0:255; subplot(1,2,2),bar(x,y),axis([0,255,0,140000]),title('My Histogram'); clear