任务
在课堂上学习了直方图均衡化的处理手段,看到外国女子的脸部增亮,这是在空域中实现变换增强的方法之一。尝试在matlab中实现相关方法,并用网上的老照片进行实验,效果不错。
过程
得到灰度图的直方图
灰度图的获取可以参考博文matlab数字图像处理——RGB转灰度图,当然也可以直接调用系统函数rgb2gray()
直方图其实是统计不同灰度等级的像素点数目大小,并通过除以图像像素点总数目,得到归一化结果/概率。
%% 统计每种灰度值的像素个数
% Function:将灰度图grayImg的不同灰度等级(0,255)的概率进行统计
% Date:2020/9/24
% Author:leezeeyee
function record=getHistogram(grayImg)
[M,N]=size(grayImg);
record=zeros(256,1);
for row=1:M
for col=1:N
record(grayImg(row,col)+1)=record(grayImg(row,col)+1)+1;
end
end
record=record/(M*N);
end

得到累积直方图
因为需要对灰度等级进行映射——把某个阶段的灰度值对应到均衡的结果,那么我们需要取得中间变量:累积直方图。
%% 统计累积直方图
% Function:对直方图record进行遍历,得到灰度级的累计直方图
% Date:2020/9/24
% Author:leezeeyee
function cRecord=getCumulative(record)
cRecord=record;
[r,~]=size(record)
for i=2:r
% 遍历record,得到灰度级的累计直方图
cRecord(i)=cRecord(i-1)+cRecord(i);
end
end
得到映射关系
映射关系可以利用matlab的矩阵运算实现,直接将表达式中的变量用矩阵替换即可。分别表述这行代码中变量的含义:
- cRecord:上一部分得到的累积直方图
- 256:总共的灰度等级
- -1是因为在matlab中,uint8的范围在0~255
- mapValue:
- 索引值继承等号右边唯一的矩阵——cRecord的含义,是每个灰度等级
- 内部的值表示通过运算映射得到新的灰度等级
mapValue=uint8(cRecord*256-1);
根据新的映射关系修改原图的灰度值
这一步的目的比较清晰,已经通过上一步得到了映射关系,只要将原图中的灰度等级修改为映射后对应的灰度等级即可。
%% 根据新的映射关系修改原图的灰度值
% Function:将灰度图grayImg利用直方图均衡得到的映射灰度级得到均衡后图像newImg
% Date:2020/9/24
% Author:leezeeyee
function newImg=map2newImg(grayImg,mapValue)
[M,N]=size(grayImg);
newImg=uint8(size(grayImg));
for row=1:M
for col=1:N
newImg(row,col)=mapValue(grayImg(row,col)+1);
end
end

问题与解决方法
残影
整个过程比较顺利,只是第一次显示直方图时有些奇怪:

结果图P5只能隐约看到lena的轮廓,通过显示该图像的变量类型找到答案,变量并非图像的uint8
类型,而是double
类型。问题出在初始化变量上,我利用zeros()函数,当我把赋值改为强制类型转换后,问题解决。
class(newImg)
ans =
'double'
结果展示


参考资料
- 如何提取特定位置以后的字符串(出处: MATLAB中文论坛)
- MATLAB中画柱状图