目录
直方图处理技术概述
直方图均衡化
公式推导
Matlab代码实现
图像的规定化
数学推导
单映射
Matlab代码
效果展示编辑
组映射
Matlab代码
直方图处理技术概述
灰度级范围[0,L-1]的数字图像,在实际使用中,用哥灰度级的像素总数除以MN的整幅图像的像素数量,归一化到规律中进行计算,这样可以解除面积对哥灰度级在所有橡树中分布的影响,仅仅靠概率进行分析个灰度级的分布。
在较暗的图像中,直方图的分量集中在灰度级的低段。
低对比度图像具有较窄的直方图,且都集中于[0,L-1]的灰度级的某一部分,较为集中。
高对比度图像的直方图的分量覆盖了很宽的灰度范围,且像素数量的分布也没有太不均匀,只有少数灰度级的像素数量要高出许多。
可以直观的得出结论:若以一幅图像的像素占据整个可能的灰度级并且均与分布,则该图像会有高对比度的图像外观并展示灰色调的较大变化,最终效果会得到一幅灰度细节丰富且动态范围较大的图像。
直方图均衡化
直方图均衡化,其目的是为了将图像中的一些动态范围较小、较集中的的灰度级改变,让图像的灰度级分布的更为均与一些。可以依据输入的图像就能得到一个变换函数来自动的实现直方图分布均匀的效果。
我对于直方图的推到论文并没有看过,所有最底层的细节不太了解。全基于我对于均衡化的计算理解。
从实际情况分析
观察这张图的直方图,在整个[0,255]的灰度级中,大部分的灰度级都是集中在较高的灰度部分。整个图片都是偏亮。我们希望提高图像的对比度,让图像的更多细节变的突出,同时希望图像不要太亮,让灰度级像素分布均匀一些。
所以,我们的目的是希望挪动直方图的灰度级,而不是修改直方图的灰度级的数量,大规模修改灰度级的像素的数量会改变整幅图像。且会影响灰度级的分布,有需要重新取计算,所有我们的目的是,不修改各自灰度级的像素数量,而是仅仅移动灰度级。
r是指原始图像的灰度级,s是目的变换后的灰度级。
可以列出某种函数关系
变换前与变换后都是要满足同样的灰度级范围。
在输入一个灰度级的像素,经过变换后就是输出后的一个新的灰度级。
关于变换函数,可以得到其反变换,也就是反函数
而函数存在反函数的情况是,函数是一个严格单调递增函数,这样才不会出现一对多的二义性矛盾。
但是在于实际的图片的变换情况下是,任然存在多个灰度级变换后变成一个灰度级的情况,也就是多对一情况。这是因为,作用于图像的整数,是任然存在多对一的情况。
对于图像的不同的灰度级,对于不同的灰度级的灰度数量,在整幅图像的分布,可以用概率来替代表示,这是属于归一化的思想。
公式推导
得到r的s映射关系后,可以通过相应的映射可以进行灰度级变换。
Matlab代码实现
mat1=imread("Image\gray.jpg");mat2=mat1;L=256;%统计一副图像的不同灰度级的在图像中的概率密度(该灰度级的像素数量/整个图像的像素总数量)[M,N]=size(mat1); probaDensity=zeros(1,L);%从1开始到256-[0,255]for a=1:M for b=1:N probaDensity(mat1(a,b)+1)=probaDensity(mat1(a,b)+1) + 1; endendfor a=1:L probaDensity(a)=probaDensity(a)/(M*N);end%bar(1:L,probaDensity)%计算累计概率密度-s=T(r)=积分p(r)*(L-1)*drcumprobaDensity=zeros(1,L);cumprobaDensity(1)=probaDensity(1);for a=2:L cumprobaDensity(a)=cumprobaDensity(a-1)+probaDensity(a);end%完成变换,乘以(L-1)取整,完成s的映射,可以构建s的映射表S=zeros(1,L);for a=1:L S(a)=uint8(cumprobaDensity(a)*(L-1)+0.5);end%bar(1:L,S)%完成了r-s的映射表,然后遍历图像,将图像的灰度级(r)对应到变换后的sfor a=1:M for b=1:N mat2(a,b)=S(mat2(a,b)+1); endendfigure,subplot(221),imhist(mat1),title("原直方图")subplot(222),imhist(mat2),title("均衡化直方图")subplot(223),imshow(mat1),title("原图")subplot(224),imshow(mat2),title("均衡化");clf;
效果展示
这样一来,灰度级分布的较为均匀,基本上在[0,L-1]的灰度级都覆盖到了。均衡化后的图像对比度提升,细节增加。
图像的规定化
规定化,其本身与均衡化一样,不过均衡化的变换函数/增强函数是由图像自动决定的,让图像的灰度级变的更为均匀。而规定化可以让我们自己指定希望变换的图像的增强函数。让我们可以达到自己想要的效果。可以选择让灰度级集中到低灰度级区域,让阴影的细节更为丰富。
我们提供一个图像,以其的直方图作为变换的模板。
我们提供了两张图,两张图都进行变换,然后得到两个的映射函数表,再进行一次映射,可以得到新的映射表。
数学推导
关键是在于怎么完成Sr到z的反映射。
有两种方法-单映射与组映射,也就是SML与GML算法。
单映射
根据SML的思想,以为基准,让
去查找,差值的绝对值最小的哪个灰度级就是新映射的灰度级。
Matlab代码
mat1=imread("Image\原图.jpg");tmat1=mat1;mat0=imread("Image\规定图.jpg");tmat0=mat0;L=256;[M1,N1]=size(tmat1);[M0,N0]=size(tmat0);%%统计r与z的概率密度density0=zeros(1,L);density1=zeros(1,L);for a=1:M0 for b=1:N0 density0(tmat0(a,b)+1)=density0(tmat0(a,b)+1)+1; endendfor a=1:M1 for b=1:N1 density1(tmat1(a,b)+1)=density1(tmat1(a,b)+1)+1; endendfor a=1:L density1(a)=density1(a)/(M1*N1); density0(a)=density0(a)/(M0*N0);end%%分别得到关于r的T(r)-累计概率密度*(L-1)%%关于z的G(z)-累计概率密度*(l-1)cumdensity0=zeros(1,L);cumdensity1=zeros(1,L);cumdensity0(1)=density0(1);cumdensity1(1)=density1(1);for a=2:L cumdensity0(a)=cumdensity0(a-1)+density0(a); cumdensity1(a)=cumdensity1(a-1)+density1(a);end% bar(1:L,cumdensity0)% bar(1:L,cumdensity1)%%完成了量组对于S的映射,还需要关于Sr的反映射到z%找Sr与Sk中差值最小的Rz1=zeros(1,L);%为避免取整误差,直接用累计概率密度进行计算%%单映射以z为基准,进行r中的查找最小的开始映射temp=0.0;for a=1:L temp=cumdensity1(a); MinDen=1.0; minIndex=1; for b=1:L if abs(temp-cumdensity0(b)) <= MinDen minIndex=b; MinDen=abs(temp-cumdensity0(b)); end end %可以找出最小的差值和下标 Rz1(a)=minIndex;endfor a=1:M1 for b=1:N1 tmat1(a,b)=Rz1(tmat1(a,b)); endendfigure,subplot(231),imhist(mat1),title("原直方图")subplot(232),imhist(mat0),title("规定直方图")subplot(233),imhist(tmat1),title("单映射直方图")subplot(234),imshow(mat1),title("原图");subplot(235),imshow(mat0),title("规定图");subplot(236),imshow(tmat1),title("单映射后图");clf;%%组映射以r为基准,查找r中的累计概率密度的最小差值
效果展示![](http://zhangshiyu.com/zb_users/upload/2023/05/20230506150518168335671862807.png)
组映射
都说单映射的查找方法是存在误差的,所以提供了组映射。
组映射与单映射反过来,以原图图的为基准,让规定图的
去查找原图中累计概率密度的差值的绝对值最小的哪个灰度级,依次为一个分别,让从0到这个灰度级之间的所有灰度级都映射到当前的规定图的灰度级,然后更新边界,直到下一次找到最小的边界。
具体组映射和单映射的理解可以参考直方图规定化:单映射规则、组映射规则的手动求解过程_Nefu_lyh的博客-CSDN博客_直方图规定化例题
这个博主讲解的还是很清晰的。
Matlab代码
mat1=imread("Image\原图.jpg");tmat1=mat1;mat0=imread("Image\规定图.jpg");tmat0=mat0;L=256;[M1,N1]=size(tmat1);[M0,N0]=size(tmat0);%%统计r与z的概率密度density0=zeros(1,L);density1=zeros(1,L);for a=1:M0 for b=1:N0 density0(tmat0(a,b)+1)=density0(tmat0(a,b)+1)+1; endendfor a=1:M1 for b=1:N1 density1(tmat1(a,b)+1)=density1(tmat1(a,b)+1)+1; endendfor a=1:L density1(a)=density1(a)/(M1*N1); density0(a)=density0(a)/(M0*N0);end%%分别得到关于r的T(r)-累计概率密度*(L-1)%%关于z的G(z)-累计概率密度*(l-1)cumdensity0=zeros(1,L);cumdensity1=zeros(1,L);cumdensity0(1)=density0(1);cumdensity1(1)=density1(1);for a=2:L cumdensity0(a)=cumdensity0(a-1)+density0(a); cumdensity1(a)=cumdensity1(a-1)+density1(a);end%%完成了量组对于S的映射,还需要关于Sr的反映射到z%找Sr与Sk中差值最小的Rz2=zeros(1,L);%为避免取整误差,直接用累计概率密度进行计算%%组映射以r为基准,查找r中的累计概率密度的最小差值,以组为单位进行映射%设置一个边界,在查找完一轮后,映射区域内的r,然后更新边界bound=1;temp=0.0;for a=1:L temp=cumdensity0(a); MinDen=1.0; minIndex=1; for b=1:L if abs(temp-cumdensity1(b))<=MinDen minIndex=b; MinDen=abs(temp-cumdensity1(b)); end end %查找完,开始映射[bound,minIndex] for cd=bound:minIndex Rz2(cd)=a; end %更新边界 bound=minIndex+1;endfor a=1:M1 for b=1:N1 tmat1(a,b)=Rz2(tmat1(a,b)); endendfigure,subplot(231),imhist(mat1),title("原直方图")subplot(232),imhist(mat0),title("规定直方图")subplot(233),imhist(tmat1),title("组映射直方图")subplot(234),imshow(mat1),title("原图");subplot(235),imshow(mat0),title("规定图");subplot(236),imshow(tmat1),title("组映射后图");clf;
效果展示