原文请参考以下博文,代码是直接借鉴的,指出了一些问题。
https://blog.csdn.net/weixin_37139761/article/details/83386790
以下是原博文贴出的代码,并做了一些修改。
function [img2, func_T] = myHistogramEqualization(img)
img1 = double(img);
[r,c,l] = size(img1)%获取图像的高r和宽c
%统计图像中每个灰度级出现的次数
count = zeros(1,256);
for i=1:r
for j=1:c
count(1,img(i,j)+1) = count(1,img(i,j)+1)+1;
end
end
%统计图像中每个灰度级出现的概率
p = zeros(1,256);
for i=1:256
p(1,i) = count(1,i)/(r*c);
end
img2 = im2uint8(ones(r,c));%创建一个r X c大小的1矩阵
func_T = zeros(1,256);%变换函数
p_sum = 0;
%求直方图均衡化的变换函数
for k = 1:256
p_sum = p_sum + p(k);%求每个灰度级的概率之和
func_T(k) = (256-1)*p_sum;%根据变换函数的公式求和
end
func_T_z = round(func_T);%对变换函数进行取整
%完成每个像素点的映射
for i = 1:256 % 此时的i是概率和
findi = find(func_T_z==i);%找到灰度概率和是i时对应的灰度值
len = length(findi);
for j=1:len
findj = find(img==(findi(j)-1));%进行对应每个像素点的映射
img2(findj) = i;
end
end
end
直方图均衡化的原理很多博文都有,这里不再涉及。对于上述代码,在运行后会发现有些奇怪的噪点。代码先统计各个像素的灰度值出现的次数,然后计算灰度值0-255的概率密度函数p,然后求概率分布函数(也就是概率累计)func_T,对概率分布函数线性映射到0-255并取整。直方图变换函数其实就是概率分布函数,落在分布函数每个点上的灰度可能不止一个。实验用的lena.bmp,最小灰度是24,最大灰度是245,但是概率分布在1上的灰度是33 34 35 36,也就是说,图像中所有灰度为33到36的像素点的个数占总像素的1%。这么理解也没问题,但是矛盾出来了,明明图像中有小于灰度是33的像素,为什么概率分布为1对应的像素是33-36呢?仔细看代码后发现,源代码中 findi = find(func_T_z==i); 的i是从1开始的,但是func_T_z给四舍五入到0-255,因此代码更改一点即可:findi = find(func_T_z==(i-1));下图(左)是原代码效果,可见帽檐左侧有一些白点,改完以后的效果如右图所示。左下为原始图像。可见,相比于原图像, 经过直方图均衡化后的图像对比度更强。