微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于直方图的图像增强算法(HE、CLAHE、Retinex)之(一)

基于直方图的图像增强算法(HE、CLAHE、Retinex)之(一)

时间:02-23 来源:互联网 点击:

直方图是图像色彩统计特征的抽象表述。基于直方图可以实现很多有趣的算法。例如,图像增强中利用直方图来调整图像的对比度、有人利用直方图来进行大规模无损数据隐藏、还有人利用梯度直方图HOG来构建图像特征进而实现目标检测。本节我们就来讨论重要的直方图均衡化算法,说它重要是因为以此为基础后续又衍生出了许多实用而有趣的算法。

Histogram equalization

如果一幅图像的像素灰度值在一个过于有限的范围内聚集,那么图像的程序效果即会很糟糕,直接观感就是对比度很弱。下图来自维基百科,第一幅图的直方图分布非常不均衡。如果把直方图均匀地延展到整个分布域内,则图像的效果显得好了很多。

  

Matlab中提供了现成的函数“histeq()”来实现图像的直方图均衡。但为了演示说明算法的原理,下面我将在Matlab中自行编码实现图像的直方图均衡。通过代码来演示这个算法显然更加直观,更加易懂。当然,其实我还不得不感叹,如果仅仅是作为图像算法研究之用,Matlab确实非常好用。

首先读入图像,并将其转化为灰度图。然后提取图像的长和宽。

image = imread('Unequalized_Hawkes_Bay_NZ.jpg');

Img = rgb2gray(image);

[height,width]=size(image);

然后绘制一下原始图像的直方图。

[plain] view plain copy

[counts1, x] = imhist(Img,256);

counts2 = counts1/height/width;

stem(x, counts2);

  

统计每个灰度的像素值累计数目。

NumPixel = zeros(1,256);%统计各灰度数目,共256个灰度级

for i = 1:height

for j = 1: width

%对应灰度值像素点数量增加一

%因为NumPixel的下标是从1开始,但是图像像素的取值范围是0~255,所以用NumPixel(Img(i,j) + 1)

NumPixel(Img(i,j) + 1) = NumPixel(Img(i,j) + 1) + 1;

end

end

然后将频数值算为频率

ProbPixel = zeros(1,256);

for i = 1:256

ProbPixel(i) = NumPixel(i) / (height * width * 1.0);

end

再用函数cumsum来计算cdf,并将频率(取值范围是0.0~1.0)映射到0~255的无符号整数。

CumuPixel = cumsum(ProbPixel);

CumuPixel = uint8(255 .* CumuPixel + 0.5);

直方图均衡。赋值语句右端,Img(i,j)被用来作为CumuPixel的索引。比如Img(i,j) = 120,则从CumuPixel中取出第120个值作为Img(i,j) 的新像素值。

for i = 1:height

for j = 1: width

Img(i,j) = CumuPixel(Img(i,j));

end

end

最后显示新图像的直方图。

imshow(Img);

[counts1, x] = imhist(Img,256);

counts2 = counts1/height/width;

stem(x, counts2);

  

当然,上述讨论的是灰度图像的直方图均衡。对于彩色图像而言,你可能会想到分别对R、G、B三个分量来做处理,这也确实是一种方法。但有些时候,这样做很有可能导致结果图像色彩失真。因此有人建议将RGB空间转换为HSV之后,对V分量进行直方图均衡处理以保存图像色彩不失真。下面我们来做一些对比实验。待处理图像是标准的图像处理测试用图couple图,如下所示。

  

首先,我们分别处理R、G、B三个分量,为了简便我们直接使用matlab中的函数histeq()。

a = imread('couple.tiff');

R = a(:,:,1);

G = a(:,:,2);

B = a(:,:,3);

R = histeq(R, 256);

G = histeq(G, 256);

B = histeq(B, 256);

a(:,:,1) = R;

a(:,:,2) = G;

a(:,:,3) = B;

imshow(a)

下面的代码使用了另外一种方式,即将色彩空间转换到HSV后,对V通道进行处理。由于代码基本与前面介绍的一致,这里我们不再做过多解释了。

Img = imread('couple.tiff');

hsvImg = rgb2hsv(Img);

V=hsvImg(:,:,3);

[height,width]=size(V);

V = uint8(V*255);

NumPixel = zeros(1,256);

for i = 1:height

for j = 1: width

NumPixel(V(i,j) + 1) = NumPixel(V(i,j) + 1) + 1;

end

end

ProbPixel = zeros(1,256);

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top