一.什么是图像直方图
学习知识必须循序渐进,工欲善其事必先利其器,要想熟悉图像均衡化,就需要先了解什么是图像直方图。
这里用视觉处理中常用的灰度图来讲述,什么是灰度直方图呢?要知道,灰度直方图有256个灰度级,分别为0-255,数值越大,图像就越亮,也就是越白,而数值越小,图像越暗。图像是有大小的,比如一幅图像的大小为300×300,表示其有300×300=90000个像素点,而每个像素点都有一个灰度级,这样我们将灰度级0-255作为横坐标,一幅图像上面该灰度级的数量表示纵坐标,这样就构成了这幅图像的灰度直方图。
二.均衡化原理
直方图均衡化是通过灰度变换将一幅图象转换为另一幅均衡直方图,即在每个灰度级上都具有相同的象素点数的过程。图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。直方图均衡的缺点是:
1、变换后图像的灰度级减少,某些细节消失;
2、某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。
三.实战与分析
1.直方图显示
读入图像‘rice.png’,在一个窗口中显示灰度级n=64,128和256的图像直方图。
a=imread('rice.png'); figure(1) subplot(3,3,1); imshow(a);title('rice.png') subplot(3,3,2) imhist(a);title('原始图片直方图') subplot(3,3,3) imhist(a,64);title('灰度值64直方图') subplot(3,3,4) imhist(a,128);title('灰度值128直方图') subplot(3,3,5) imhist(a,256);title('灰度值256直方图')
分析:
首先用imread函数读取图片然后用imshow函数将图片展示出来,matlab中统计图像直方图的函数为imhist,imhist(i)表示直接显示图像i的灰度直方图,imhist(i,n)可以将图像以指定灰度值显示直方图。需要注意的是,如果读取的图片是RGB图像或者彩色图像,需要将其转化为灰度图像,可以利用的函数为rgb2gray。
对一幅灰度图像,其直方图反映了该图像中不同灰度级出现的统计情况,当灰度级分布在较窄的区间时,就会造成图像不清晰,过曝光的图像灰度级集中在高亮度范围,而曝光不足的图像灰度级则集中在低亮度范围内。
2.直方图灰度调节
利用函数imadjust调解图像灰度范围,观察变换后的图像及其直方图的变化。
adjustImg=imadjust(a,[0.25,0.6],[0,1]); subplot(336);imshow(adjustImg);title('调整后的图像') subplot(337);imhist(adjustImg);title('调整灰度后的直方图')
adjustImg2=imadjust(a,[0.25,0.6],[0,1],0.5); subplot(338),imshow(adjustImg2);title('gamma<1'); adjustImg3=imadjust(a,[0.25,0.6],[0,1],4); subplot(339),imshow(adjustImg3);title('gamma>1');
分析:
imadjust函数可以实现对图像直方图的灰度调节,常见的语法有J = imadjust(I)和J = imadjust(I, [low_in; high_in], [low_out; high_out], gamma)。上述代码实现的功能为将原始图像中小于2550.25=63.75的灰度值设置为0(可以看到原始图像不含有灰度值为0的区域,经过调整后出现了灰度值为0的区域),将大于2550.6=153的灰度值设置为255(可以看到原始图像不含有灰度值为255的区域,经过调整后出现了灰度值为255的区域),而在63.75和153之间的值则线性化映射成0和255之间的值。由于函数没有设置gamma的值,所以默认为1,为线性映射;当gamma<1时会增强亮色值的输出,见图1.5.2-3左;而当gamma>1时会增强暗色值的输出,见图1.5.2-3右。函数imadjust不仅能够对灰度图像进行增强操作,还可以对彩色图像进行增强,利用函数imadjust进行彩色图像增强时,是对彩色图像的RGB值分别进行操作。
3.直方图均衡化
分别对图像‘pout.tif’和‘tire.tif’进行直方图均衡化处理,比较处理前后图像及直方图分布的变化。
b=imread('pout.tif'); c=imread('tire.tif'); figure(2) subplot(331);imshow(b);title('pout.tif') subplot(332);imhist(b);title('pout原始直方图') subplot(333);imshow(c);title('tire.tif') subplot(334);imhist(c);title('pout原始直方图') beq=histeq(b); ceq=histeq(c); subplot(335);imshow(beq);title('pout均衡化') subplot(336);imhist(beq);title('pout均衡化后的直方图') subplot(337);imshow(ceq);title('tire均衡化') subplot(338);imhist(ceq);title('tire均衡化后的直方图')
分析:
前面提到当图像灰度值集中在较窄的一段区时候就会造成图像不清晰,在未对pout图像进行处理时,可以见到该图像的直方图灰度级集中在中部,而tire图像的灰度级集中在低亮度范围。此时直方图均衡化就是一种简单的图像增强技术,其通过改变直方图来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。histeq()函数就可以实现图像均衡化的功能,简单来说就是将每个灰度值用一个公式替换成新的灰度值。可以看到,经过均衡化后的图像对比度得到了增强,而且直方图的灰度级分布也较为均匀,这就是均衡化处理。
4.自己设计程序实现图像的直方图均衡
image = imread('pout.tif'); imshow(image) [height, width] = size(image); % 统计每个灰度的像素值的累计数目 NumPixel = zeros(1,256); % 建立一个256列的行向量,以统计各灰度级的像素个数 for i = 1 : height for j = 1 : width k = image(i,j); % k是像素点(i,j)的灰度值 NumPixel(k+1) = NumPixel(k+1) + 1; % 对应灰度值像素点数量加1 end end figure; bar(NumPixel); % 灰度图像的直方图
% 接下来,将频数值算为频率 ProbPixel = zeros(1,256); % 统计各灰度级出现的频率 for i = 1 : 256 ProbPixel(i) = NumPixel(i) / (height * width); end figure; bar(ProbPixel); % 灰度图像的归一化直方图
% 计算累积分布函数,并将频率(取值范围是0~1)映射到0~255的无符号整数 CumPixel = cumsum(ProbPixel); % 这里的数组CumPixel大小也是1×256 CumPixel = uint8((256-1) .* CumPixel + 0.5); % 四舍五入 figure; bar(CumPixel);
% 在下列用作直方图均衡化实现的赋值语句右端,image(i,j)被用来作为CumPixel的索引 outImage = uint8(zeros(height, width)); % 预分配数组 for i = 1 : height for j = 1 : width outImage(i,j) = CumPixel(image(i,j)); end end % 显示直方图均衡化前后的图像 peq = histeq(image); figure subplot(121),imhist(peq);title('函数处理直方图均衡化'); subplot(122),imhist(outImage);title('编程实现直方图均衡化');
imshowpair(image, outImage, 'montage');
分析:
要对直方图进行均衡化处理,其实是根据直方图像素点的灰度值进行 变换的过程,属于点操作。首先要计算每个灰度值出现的频率,也即进行归一化处理,见图1.5.4-2,然后计算其灰度累积分布频率,见图1.5.4-3,最后再将归一化的矩阵乘以255并且进行四舍五入得到新的灰度值,至此完成直方图的均衡化处理,见图1.5.4-4、1.5.4-5,可以看到其效果和histeq函数效果基本一致。