图像的直方图
图像的直方图处理是从概率统计的角度出发,对图像灰度级的概率分布进行变换,从而达到使图像细节丰富、动态范围较大、便于观测和理解的目的。
直方图处理是多种空间域处理技术的基础,可以直接用于图像的增强以及图像的压缩和分割。在灰度级范围为[0,L-1]的数字图像的直方图可以表示为:
其中rk是第k级灰度值,nk是图像中灰度为rk的像素的个数,M和N分别是图像的行和列数。
我们首先对下列图像进行观测。我们可以看到,在亮图像中,直方图的分量集中在灰度级的高端,而在暗图像中,中直方图的分量倾向于灰度级的低端。低对比度的图像具有较窄的直方图,且集中于灰度级的中部。对于单色图像,这就意味着暗淡,好像灰度被冲淡了一样。而高对比度的图像的直方图的分量覆盖了很宽的灰度级范围,而且像素的分布比较均匀。因此,若一幅图像的像素倾向于占据整个可能的灰度级并且分布均匀,那么该图像会有高对比度的外观并展示灰色调的较大变化。最终效果将是一幅灰度细节丰富且动态范围较大的图像。
下面是图像直方图绘制的Matlab程序,其中numel(image)是求取图像的M×N的值,imhist是求取图像的直方图,这里进行了归一化处理,使每个值处于[0,1]范围内。bar()用于显示直方图。
clear clc %%读取图像数据 Cells_bright=imread('细胞亮.jpg'); Cells_dark=imread('细胞暗.jpg'); Cells_low_contrast=imread('细胞低对比度.jpg'); Cells_hight_contrast=imread('细胞高对比度.jpg'); %%灰度化 Cells_bright_gray=rgb2gray(Cells_bright); Cells_dark_gray=rgb2gray(Cells_dark); Cells_low_contrast_gray=rgb2gray(Cells_low_contrast); Cells_hight_contrast_gray=rgb2gray(Cells_hight_contrast); %%求直方图 h_bright =imhist(Cells_bright_gray)/numel(Cells_bright_gray); h_dark =imhist(Cells_dark_gray)/numel(Cells_dark_gray); h_low_contrast =imhist(Cells_low_contrast_gray)/numel(Cells_low_contrast_gray); h_hight_contrast =imhist(Cells_hight_contrast_gray)/numel(Cells_hight_contrast_gray); %%绘制直方图 h=0:255; figure(1) subplot(1,2,1) imshow(Cells_bright) title('细胞亮') subplot(1,2,2) bar(h,h_bright); title('直方图') axis([0,255,0,0.1]) figure(2) subplot(1,2,1) imshow(Cells_dark_gray) title('细胞暗') subplot(1,2,2) bar(h,h_dark); title('直方图') axis([0,255,0,0.1]) figure(3) subplot(1,2,1) imshow(Cells_low_contrast_gray) title('细胞低对比度') subplot(1,2,2) bar(h,h_low_contrast); title('直方图') axis([0,255,0,0.1]) figure(4) subplot(1,2,1) imshow(Cells_hight_contrast_gray) title('细胞高对比度') subplot(1,2,2) bar(h,h_hight_contrast); title('直方图') axis([0,255,0,0.1])
图像的直方图均衡
注意,我们的目的是为了使图像的直方图分量覆盖整个灰度级且分布均匀,因此其等价于使得Ps(s)的直方图分布律为:
因此利用上述两个公式可以得到:
可以看到,变换后的图像的直方图概率分布为均匀分布。
对于离散的数字图像可以通过下式进行变换。
下面是原书中给的一个例子:
下面我们以图像“细胞亮”为实例,通过Matlab实现图像的均衡。这里的histeq可以实现对原图像的直方图均衡。我们可以看到,直方图均衡后的图像显示了更多细节,且直方图分量分布更加均匀。
%%直方图均衡 hist_equilibrium=histeq(Cells_bright_gray); %%直方图 Image_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium); %%绘制直方图均衡后图像 figure(5) subplot(1,2,1) imshow(g) title('细胞亮直方图均衡后的图片') subplot(1,2,2) bar(h,Image_equilibrium_hist); title('直方图') axis([0,255,0,0.1])
直方图规定化
上述我们实现了对某张图像进行直方图均衡,使图像的直方图分量分布均匀。但是有时对图像进行直方图均衡效果不佳。例如:
clear clc %%读取图像数据 Mars=imread('火星.jpg'); %%灰度化 Mars_gray=rgb2gray(Mars); %%直方图 h=0:255; h_Mars=imhist(Mars_gray)/numel(Mars_gray); figure(1) subplot(1,2,1) imshow(Mars_gray) title('火星灰度图') subplot(1,2,2) bar(h,h_Mars); title('直方图') axis([0,255,0,1]) %%直方图均衡 hist_equilibrium=histeq(Mars_gray); Mars_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium); figure(2) subplot(1,2,1) imshow(hist_equilibrium) title('火星直方图均衡') subplot(1,2,2) bar(h,Mars_equilibrium_hist); title('直方图') axis([0,255,0,1])
直方图的规定化可以理解为指定一种直方图分布律(自己可以根据实际需要设计),将原图像的直方图分布变换为我们规定的分布律。其实现方式也是显而易见的,由于直方图均衡是一一对应的结果,因此原图像可以通过直方图均衡由P(r)→P(s)(再次强调是一一对应的),同理,我们设计的直方图分布律也可以进行直方图均衡P(z)→P(s),而由于直方图均衡的一一对应的特性,我们可以找到这样的映射:P(s)→P(z)。因此我们可以通过这样的路线实现直方图规定化。
(1)P(r)→P(s)
(2)P(z)→P(s),P(s)→P(z)
(3)P(r)→P(s)→P(z)
下面是原书中的示例:
下面我们对上述火星卫星图像进行直方图规定化操作:
%%指定直方图分布律 p(1:100)=-16/50/50*(h(1:100)-50).^2+18; p(101:256)=2; p=p/sum(p); figure(3) plot(h,p); title('指定的直方图') %%直方图匹配 hist_matching=histeq(Mars_gray,p); Mars_matching_hist=imhist(hist_matching)/numel(hist_matching); figure(4) subplot(1,2,1) imshow(hist_matching) title('火星直方图匹配') subplot(1,2,2) bar(h,Mars_matching_hist); title('直方图') axis([0,255,0,1])
我们可以看到直方图规定化具有较好的效果。
局部直方图均衡
局部直方图均衡是为了解决在全局处理情况下使得图像大面积引入噪声的问题。例如下图所示。这里可以通过在某个局部邻域内进行均衡操作。具体代码可以参考后面讲解的直方图统计进行局部修改。
直方图统计
直方图统计的方式增强图像是借助图像中的数据的统计量进行分析计算。例如图像的平均值和二阶矩(方差)等统计量。
图像的取样均值可以表示为:
方差可以表示为:
其中均值表示了图像整体的明暗程度,方差可以理解为图像中的对比度。
例如下面是一幅放大了约130倍钨丝的SME图像,可以看到图像中央的钨丝及其支架可以很清楚并容易的分析,然而图像的右侧存在的另一根钨丝的结构由于过暗而不宜观测。倘若我们希望图像中央钨丝结构不变,仅仅对暗区纹理部分进行增强,而图像的全局均衡化虽然对暗区进行了增强,却影响了中央钨丝的区域。这时我们可以通过图像的直方图统计的方式实现。
clear clc %%读取图像数据 Tungsten=imread('放大约130倍钨丝的SME图像.jpg'); %%灰度化 Tungsten_gray=rgb2gray(Tungsten); %%直方图 h=0:255; h_Tungsten=imhist(Tungsten_gray)/numel(Tungsten_gray); %%绘制直方图 figure(1) subplot(1,2,1) imshow(Tungsten_gray) title('放大约130倍钨丝的SME图像') subplot(1,2,2) bar(h,h_Tungsten); title('直方图') axis([0,255,0,0.1]) %%全局直方图均衡 hist_equilibrium=histeq(Tungsten_gray); Tungsten_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium); figure(2) subplot(1,2,1) imshow(hist_equilibrium) title('全局直方图均衡') subplot(1,2,2) bar(h,Tungsten_equilibrium_hist); title('直方图') axis([0,255,0,1])
对于满足上述所有条件的区域,可以通过将该像素值乘以指定常数E来处理,以便增强或减小该区域灰度值。
因此,综上所述,我们可以表示为:
下面对上述钨丝图进行操作:
首先求取全局均值和标准差,其次设置k0、k1、k2和E,设置邻域范围为n=3。然后根据上述公式进行计算。可以看到通过直方图统计的方式增强了图像右侧的暗区域。
%%直方图统计 Tungsten_gray=double(Tungsten_gray); %格式转化,便于后期计算 Tungsten_mean_G =mean(Tungsten_gray(:)); %全局平均值 k0=0.25; Tungsten_std_G=std(Tungsten_gray(:)); %全局标准差 k2=0.4; k1=0.02; E=4.0; if k1>=k2 disp(['输入错误,k1>k2']) end n=3; %局部均衡邻域范围 Tungsten_result=Tungsten_gray; %用于得到结果 [row,col]=size(Tungsten_gray); for i=1:row-n for j=1:col-n img_temp=Tungsten_gray(i:i+(n-1),j:j+(n-1)); %获取局部图像 img_temp_mean=mean(img_temp(:)); %求局部均值 img_temp_std=std(img_temp(:)); %求局部标准差 if img_temp_mean<=k0*Tungsten_mean_G && img_temp_std<=k2*Tungsten_std_G &&img_temp_std>=k1*Tungsten_std_G; Tungsten_result(i:i+(n-1),j:j+(n-1))=img_temp*E; %增强灰度值 end end end Tungsten_result=uint8(Tungsten_result); Tungsten_result_hist=imhist(Tungsten_result)/numel(Tungsten_result); figure(3) subplot(1,2,1) imshow(Tungsten_result) title('局部直方图统计增强后的图像') subplot(1,2,2) bar(h,Tungsten_result_hist); title('直方图') axis([0,255,0,1])