在学习直方图匹配之前,最好先看一下直方图均衡的原理,这样对于直方图匹配的理解就不是问题。
参考:直方图均衡原理及MATLAB实现
对于某些应用,采用均匀直方图的直方图匹配法并不是最好的处理方法,如果希望得到具有规定形状的直方图,就需要用到一种特殊的处理方法:直方图匹配 (直方图规定化)。
令连续灰度值 r r r 和 z z z 分别表示输入图像和输出图像的灰度级,用 p r ( r ) p_r(r) pr(r) 和 p z ( z ) p_z(z) pz(z) 分别表示它们对应的连续概率密度函数。
我们现在的目标是:由给定的输入图像估计出 p r ( r ) p_r(r) pr(r),由 p r ( r ) p_r(r) pr(r) 得到 p z ( z ) p_z(z) pz(z),即得到我们希望输出的图像所具有的指定概率密度函数。
首先,我们已经知道在直方图均衡中, s s s 是 r r r 经过均衡后的图像灰度级,转换 (映射) 的表达式为:
s = T ( r ) = ( L − 1 ) ∫ 0 r p r ( w ) d w (1) s = T(r) = (L-1)\int_0^rp_r(w){\rm d}w \tag{1} s=T(r)=(L−1)∫0rpr(w)dw(1)
这里表达的是 r r r 经过变换函数 T T T,映射到了 s s s
在这个基础上,再定义一个随机变量 z z z:
G ( z ) = ( L − 1 ) ∫ 0 z p z ( t ) d t = s (2) G(z) = (L-1)\int_0^zp_z(t){\rm d}t = s \tag{2} G(z)=(L−1)∫0zpz(t)dt=s(2)
这里表达的是 z z z 经过变换函数 G G G,映射到了 s s s
那么就可以得出: G ( z ) = T ( r ) G(z) = T(r) G(z)=T(r),所以 z z z 必须满足条件:
z = G − 1 [ T ( r ) ] = G − 1 ( s ) z = G^{-1}[T(r)] = G^{-1}(s) z=G−1[T(r)]=G−1(s)
(1) 式的离散形式为:
s k = T ( r k ) = ( L − 1 ) ∑ j = 0 k p r ( r j ) = ( L − 1 ) M N ∑ j = 0 k n j , k = 0 , 1 , 2 , . . . , L − 1 (3) s_k = T(r_k) = (L-1)\sum^k_{j=0}p_r(r_j) = \frac{(L-1)}{MN}\sum^k_{j=0} n_j,\ \ k = 0,1,2,...,L-1 \tag{3} sk=T(rk)=(L−1)j=0∑kpr(rj)=MN(L−1)j=0∑knj, k=0,1,2,...,L−1(3)
(2) 式的离散形式为:
G ( z q ) = ( L − 1 ) ∑ i = 0 q p z ( z i ) = s k (4) G(z_q) = (L-1)\sum^q_{i=0}p_z(z_i) = s_k \tag{4} G(zq)=(L−1)i=0∑qpz(zi)=sk(4)
其中 p z ( z i ) p_z(z_i) pz(zi) 是规定直方图的第 i i i 个值。
最后利用反变换找到期望的 z q z_q zq:
z q = G − 1 ( s k ) z_q = G^{-1}(s_k) zq=G−1(sk)
在实际情况中,由于图像灰度值是离散的,所以并不需要计算 G G G 的反变换。
由一幅给定的图像,想要得到一幅其灰度级具有指定概率密度函数的图像,可以按照如下步骤:
为了表述方便,下面把具有 r r r 值像素的图像直接叫做图像 r r r, s s s 和 z z z 同理。
所以整个处理过程就是:
对输入图像 r r r 进行直方图均衡得到输出图像 s s s,对均衡后的图像 s s s 进行反映射 z = G − 1 ( s ) z = G^{-1}(s) z=G−1(s),对每个像素都进行处理后,输出图像的概率密度函数 PDF 就等于我们指定的 PDF。
clear all;
close all;
clc;
r=127;
x=-r:r+1;
sigma=20;
y1=exp(-((x-80).^2)/(2*sigma^2));
y2=exp(-((x+80).^2)/(2*sigma^2));
y=y1+y2; %双峰高斯函数,任意函数都可以
%im=imread('bg.bmp'); %匹配一个图像的直方图
%y=imhist(im);
y=y/sum(y); %归一化,使函数符合概率分布的sum(y)==1这样一个规律
plot(y); %待匹配的直方图
G=[]; %函数的累积直方图
for i=1:256
G=[G sum(y(1:i))];
end
img=imread('lena.jpg');
[m n]=size(img);
hist=imhist(img); %待处理图像的直方图
p=hist/(m*n);
figure;plot(p) %原图直方图
s=[]; %待处理图像的累积直方图
for i=1:256
s=[s sum(p(1:i))];
end
for i=1:256
tmp{i}=G-s(i);
tmp{i}=abs(tmp{i}); %因为要找距离最近的点,所以取绝对值
[a index(i)]=min(tmp{i}); %找到两个累积直方图距离最近的点
end
imgn=zeros(m,n);
for i=1:m
for j=1:n
imgn(i,j)=index(img(i,j)+1)-1; %由原图的灰度通过索引映射到新的灰度
end
end
imgn=uint8(imgn);
figure;imshow(imgn)
figure;plot(imhist(imgn)) %新图的直方图