matlab数字图像处理——直方图均衡重现老照片

任务

在课堂上学习了直方图均衡化的处理手段,看到外国女子的脸部增亮,这是在空域中实现变换增强的方法之一。尝试在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'

结果展示

参考资料

Leave a comment

Your email address will not be published. Required fields are marked *