退化函数是指将退化过程模型化
,它和加性噪声
项一起,作用于输入图像f(x,y)
,产生一幅退化图像g(x,y)
:
g ( x , y ) = H [ f ( x , y ) ] + η ( x , y ) g(x,y) = H[f(x,y)]+\eta(x,y) g(x,y)=H[f(x,y)]+η(x,y)
若给定g、一些关于退化函数H的知识以及一些关于加性噪声η
的知识,复原目标函数得到原图像的一个估计 f ^ ( x , y ) \hat{f}(x,y) f^(x,y)。如果我们对H和η
直到的越多,那么 f ^ ( x , y ) \hat{f}(x,y) f^(x,y)会越接近 f ( x , y ) f(x,y) f(x,y)。
若H是线性的,空间不变的的过程,那么退化函数还可以在空间域通过下式给出:
g ( x , y ) = h ( x , y ) ∗ f ( x , y ) + η ( x , y ) g(x,y) = h(x,y)*f(x,y)+\eta(x,y) g(x,y)=h(x,y)∗f(x,y)+η(x,y)
其中h(x,y)
是退化函数的空间表示,*
是卷积,则空间域的卷积核频域的乘法组成了一个傅里叶变换对,所以可以用等价的频域
表示来写出前面的模型:
G ( u , v ) = H ( u , v ) F ( u , v ) + N ( u , v ) G(u,v)=H(u,v)F(u,v)+N(u,v) G(u,v)=H(u,v)F(u,v)+N(u,v)
退化函数H(u,v)
有时称为光学传递函数OTF
,在空间域,h(x,y)
称为点扩散函数PSF
。
对于任何种类的输入,让h(x,y)
作用于光源的一个点来得到退化的特征,点扩散函数就是来源于此。
OTF和PSF是一个傅里叶变换对,IPT有两个函数otf2psf
和psf2otf
用于OTF
和PSF
之间的转换。
基本语法:
g = imnoise(f, type, parameters)
imnoise(f, 'gaussian', m, var)
将均值为m方差为var的高斯噪声加载图像f上,默认均值为0.方差为0.01的噪声imnoise(f, 'localvar', V)
将均值为0、局部方差为V的高斯噪声添加到图像f
上,其中V
与f
大小相同的数组,它包含了每个店的理想方差值。imnoise(f, 'localvar', image_intensity, var)
. 将均值为0的高斯噪声添加到图像f
上,其中噪声的局部方差var
是图像f的亮度值的函数,参量image_intensity
和var
是大小相同的向量,plot(image_intensity, var)
绘制出噪声方差和图像亮度的函数关系。向量image_intensity
的取值范围必须是[0,1]imnoise(f, 'salt & pepper', d)
则是椒盐噪声污染图像f,其中d是噪声密度(即包含噪声值得图像区域的百分比)。因此,大约有d*numel(f)
个像素受到了影响,默认密度为0.05imnoise(f, 'speckle', var)
用方程g=f+n*f
将乘性噪声添加到图像f上,其中n是均值为0,方差为var的均匀分布的随机噪声,var默认0.04imnoise(f, 'poisson')
从数据中,产生泊松噪声。遵守泊松统计,这个听描述很复杂。空间噪声值时随机数,以概率密度函数PDF
或相应的累积分布函数CDF
表征。
所以许多函数都是在区间(0,1)
内具有均匀CDF
的随机数生成问题为基础的。但是更有意义的是用rand
生成均匀随机数及使用函数randn生成正态(高斯)随机数。
假设w
是区间(0,1)
内均匀分布的随机变量,则可以通过求解以下方程来得到具有指定CDF和Fz的随机变量z
:
z = F z − 1 ( w ) z = F^{-1}_z(w) z=Fz−1(w)
就比如:
F z ( z ) = { 1 − e − ( z − a ) 2 / b , z ≥ a 0 , z < a F_z(z) = \begin{cases} 1-e^{-(z-a)^2/b}, &z≥a \\ 0, & z<a \end{cases} Fz(z)={1−e−(z−a)2/b,0,z≥az<a
为了z可解:
1 − e − ( z − a ) 2 / b = w 1-e^{-(z-a)^2/b} = w 1−e−(z−a)2/b=w
或
z = a + b l n ( 1 − w ) z = a+ \sqrt{b\ ln(1-w)} z=a+b ln(1−w)
这样可以生成一个参数为a和b的瑞利分布
的随机变量z:
R = a + sqrt(b*log(1 - rand(M, N)));
该表达式 z = a + b l n ( 1 − w ) z = a+ \sqrt{b\ ln(1-w)} z=a+b ln(1−w)有时可称为随机数生成器方程,因为它确定了如何生成需要的随机数。
下标列出了当前讨论中,一些随机变量,以及他们的PDF、CDF和随机数生成器方程
先介绍一下rand和find
函数,然后就自己实现上表:
A = rand(M, N)
生成一个大小为M×N的数组,它的元素是零均值,单位方差的正态数2.若省略N则N默认等于M。若不给参数,则值生成一个数。
I = find(A)
[r, c] = find(A)
[r, c, v] = find(A)
第一种形式将返回A中所有非0的索引。
第二种则是返回非0数的行和列索引
第三种则是在第二种的基础上,将非0值传递给列向量v
稍微高级点的操作,将数组A里的小于128的值改为0:
I = find(A < 128);
A(I) = 0;
function R=imnoise2(type,M,N,a,b)%type是函数类型,M*N是噪声数组的大小,a,b为两个参数
%设置默认值
if nargin==1%如果函数的输入参数为1,则默认a=0;b=1;M=1;N=1
a=0;b=1;
M=1;N=1;
elseif nargin==3%如果函数的输入参数为3,则默认a=0;b=1
a=0;b=1;
end
%开始运行程序
switch lower(type)
case 'gaussian'%如果是高斯类型,执行下面方程
R=a+b*randn(M,N);
case 'salt & pepper'%如果是焦盐类型,当输入参数小于等于3,a=0.05,b=0.05
if nargin<=3
a=0.05;b=0.05;
end
%检验Pa+Pb是否大于1
if(a+b)>1
error('The sum Pa+Pb must be not exceed >1')
end
R(1:M,1:N)=0.5;
X=rand(M,N);%(0,1)范围内产生一个M*N大小的均匀随机数组
c=find(X<=a);%寻找X中小于等于a的数,并赋值为0
R(c)=0;
u=a+b;
c=find(X>a & X<=u);%寻找X中大于a并小于等于u的数,并赋值为1
R(c)=1;
case 'lognormal'%对数正态类型,当输入参数小于等于3,a=1,b=0.25,执行下面方程
if nargin<=3
a=1;b=0.25;
end
R=a*exp(b*randn(M,N));
case 'rayleigh'%瑞利类型,执行下面方程
R=a+(-b*log(1-rand(M,N))).^0.5;
case 'exponential'%指数类型,执行下面方程
if nargin<=3%如果输入参数小于等于3,a=1
a=1;
end
if a<=0%如果a=0,错误类型
error('Parameter a must be positive for exponential type.')
end
k=-1/a;
R=k*log(1-rand(M,N));
case 'erlang'%厄兰类型,如果输入参数小于等于3,a=2,b=5
if nargin<=3
a=2;b=5;
end
if(b~=round(b)|b<=0)%如果b=0,错误类型
error('Param b must a positive integer for Erlang.')
end
k=-1/a;
R=zeros(M,N);
for j=1:b
R=R+k*log(1-rand(M,N));
end
otherwise%如果不是以上类型,输出未知分配类型
error('Unknown distribution type.')
end
图像的周期噪声一般产生于图像采集过程中的电器或电机等干扰,一般来说,是从空间域滤波处理。一般来说,它的模型是这样的:
r ( x , y ) = A s i n [ 2 π u 0 ( x + B x ) / M + 2 π v 0 ( y + B y ) / N ] r(x,y) = Asin[2\pi u_0(x+B_x)/M+2\pi v_0(y+By)/N] r(x,y)=Asin[2πu0(x+Bx)/M+2πv0(y+By)/N]
A是振幅,u0和v0是关于x轴和y轴确定的正弦频率,Bx和By是相移,则该方程DFT为:
R ( u , v ) = j A 2 [ ( e j 2 π u 0 B x / M ) δ ( u + u 0 , v + v 0 ) − ( e j 2 π v 0 B y / N ) δ ( u − u 0 , v − v 0 ) ] R(u,v) = j\frac{A}{2}[(e^{j2\pi u_0B_x/M})\delta(u+u_0,v+v_0)-(e^{j2\pi v_0B_y/N })\delta(u-u_0,v-v_0)] R(u,v)=j2A[(ej2πu0Bx/M)δ(u+u0,v+v0)−(ej2πv0By/N)δ(u−u0,v−v0)]
也就是说,这是一个位于(u+u0,v+v0)和(u-u0,v-v0)的复共轭冲击响应。
然后就是imnoise3的代码部分:
function [r,R,S]=imnoise3(M,N,C,A,B)
%产生一个大小为M*N的正弦噪声模型r,R为傅里叶变换,S为正弦噪声模型的傅里叶的频谱
%C为冲击位置的坐标,A是1*k维向量包含振幅的冲击对,B是由k*2矩阵组成的冲击对
%处理输入参数
[K,n]=size(C);%矩阵C的行数返回给K,矩阵C的列数返回给n
if nargin==3
A(1:K)=1.0;
B(1:K,1:2)=0;
elseif nargin==4
B(1:K,1:2)=0;
end
R=zeros(M,N);%构造R
for j=1:K%j从1到K取遍,步长为1
u1=M/2+1+C(j,1);v1=N/2+1+C(j,2);
R(u1,v1)=i*(A(j)/2)*exp(i*2*pi*C(j,1)*B(j,1)/M);
%复共轭
u2=M/2+1-C(j,1);v2=N/2+1-C(j,2);
R(u2,v2)=-i*(A(j)/2)*exp(i*2*pi*C(j,2)*B(j,2)/N);
end
S=abs(R);%计算光谱
r=real(ifft2(ifftshift(R)));%产生空间正弦图形
调用看看效果:
C1 = [0 32; 0 64; 16 16; 32 0; 64 0; -16 16];
C2 = [6 32; -2 2];
[r1, R1, S1] = imnoise3(512, 512, C1);
A = [1 5];
[r2, R2, S2] = imnoise3(512, 512, C2, A);
[r3, R3, S3] = imnoise3(512, 512, C2);
subplot(2,3,1);
imshow(S1, [ ]);
subplot(2,3,4);
imshow(r1, [ ]);
subplot(2,3,2);
imshow(S2, [ ]);
subplot(2,3,5);
imshow(r2, [ ]);
subplot(2,3,3);
imshow(S3, [ ]);
subplot(2,3,6);
imshow(r3, [ ]);
周期噪声一般是通过分析频谱实现,只要图片的频谱不太离谱,那么离谱的那个尖峰就是噪声。所以,在噪声尖峰明显或者知道了干扰频率的情况下,是可以自动分析然后滤掉的。
假设噪声的均值m和方差σ2的关系,以及用来指定本章中的噪声PDF的参数a,b。那么问题就成了用图像样本去估计均值与方差,然后来求解a和b。
假设zi是用来表示一副图像的灰度级的一个离散随机变量,令p(zi)是i=0,1,2,3,…,L-1的归一化直方图,L是可能亮度值的数目。直方图分量p(zi)则是亮度值p(zj)出现的概率估计。(用频数来代表频率)。
直方图分布形状的一种方法是通过它的中心矩
,它的定义是:
μ n = ∑ i = 0 L − 1 ( z i − m ) n p ( z i ) \mu_n = \sum_{i=0}^{L-1} (z_i-m)^np(z_i) μn=i=0∑L−1(zi−m)np(zi)
n为矩的阶、m是均值,又有:
M = ∑ i = 0 L − 1 z i p ( z i ) M = \sum_{i=0}^{L-1}z_ip(z_i) M=i=0∑L−1zip(zi)
假设所有分量和为1,则可知μ0=1,μ1=0
二阶矩是方差:
μ 2 = ∑ i = 0 L − 1 ( z i − m ) 2 p ( z i ) \mu_2 = \sum_{i=0}{L-1}(z_i-m)^2p(z_i) μ2=i=0∑L−1(zi−m)2p(zi)
ps矩代表啥?
函数:[v, unv] = statmoments(p, n)
,可以计算均值和n阶中心矩,并返回行向量v。因为0阶矩总为1,1阶矩总为0,则该函数自动忽略这两个矩。改为令v(1) = m, v(k) = μk,k=2,3,4,…,n。
上述代码中,p为直方图向量,n是计算的矩的数量。要求对于uint8类图像,p的分量数等于28,uint16则是216。double则两个均可。向量v包含了一随机变量值为基础的归一化矩,而随机变量被标注在区间[0,1]内,所以,所有的矩也在这个区间内。向量unv
包含了与v相同的矩,但用位于源氏值区间内的数值计算。例如,若length§=256,v(1)=0.5,则unv(1)则是127.5,是区间[0,255]的一半。
噪声参数通常直接由(一组)带噪声的图像来估计。通过尽可能选择一个无特色的区域,然后确保该区域亮度值的可变性主要
由噪声产生。当然这个感兴趣区域ROI
则是通过函数roipoly
来选择。
通过B = roipoly(f,col,row)
来生成一个由01构成的掩膜B。当然可以省略col、row
然后再显示的图像上用鼠标选择roi
。(col,row)可以组成多边形,B则是与f的大小相同,多边形内的点为1,多边形外的点为0
若鼠标选择,则可以将参数写为:[B, c, r] = roipoly(f)
来得到鼠标选择的多边形点。
然后又自定义函数来统计roi
区域的直方图:
function [p, npix] = histroi(f, c, r)
B = roipoly(f, c, r);
p = imhist(f(B));
if nargout > 1
npix = sum(B(:));
end
如果只是退化噪声,则遵循:
g ( x , y ) = f ( x , y ) + η ( x , y ) g(x,y) = f(x,y) + \eta(x,y) g(x,y)=f(x,y)+η(x,y)
那么,选用空间滤波是最好的方法。
常见的几种滤波器的数学公式:
有函数imlincomb
可以计算输入的线性组合:
B = imlincomb(c1,A1,c2,A2,c3,A3, ... ,cn,An)
实现了 B = c1A1+c2A2+…+cn*An
然后就是手写函数,实现上表的功能:
function f=spfilt(g,type,m,n,parameter)
%spfilt执行线性和非线性的空间滤波器,g为原图像,type为滤波器类型,M*N为滤波器模板大小
%处理输入参数
if nargin==2
m=3;n=3;Q=1.5;d=2;
elseif nargin==5
Q=parameter;d=parameter;
elseif nargin==4
Q=1.5;d=2;
else
error('Wrong number of inputs.');
end
%开始执行滤波
switch type
case 'amean'%算数平均滤波
w=fspecial('average',[m n]);
f=imfilter(g,w,'replicate');
case 'gmean'%几何平均滤波
f=gmean(g,m,n);
case 'hmean'%调和平均滤波
f=harmean(g,m,n);
case 'chmean'%反调和平均滤波,Q的默认值是1.5
f=charmean(g,m,n,Q);
case 'median'%中值滤波
f=medfilt2(g,[m n],'symmetric');
case 'max'%最大值滤波
f=ordfilt2(g,m*n,ones(m,n),'symmetric');
case 'min'%最小值滤波
f=ordfilt2(g,1,ones(m,n),'symmetric');
case 'midpoint'%中值滤波
f=ordfilt2(g,1,ones(m,n),'symmetric');
f=ordfilt2(g,m*n,ones(m,n),'symmetric');
f=imlincomb(0.5,f1,0.5,f2);
case 'atrimmed'%顺序平均值滤波,d必须是非负的数,d的默认值是2
if(d<0)|(d/2~=round(d/2))
error('d must be a nonnegative,even integer.')
end
f=alphatrim(g,m,n,d);
otherwise
error('Unkown filter type.')
end
效果的话,没有合适的图片,也不会有太大的差异。
算法稍微比较复杂,这里记录算法思路:
Zmin表示Sxy最小亮度值
Zmax表示Sxy最大亮度值
Zmod表示Sxy中的亮度中值
Zxy表示坐标(x,y)处的亮度值。
这个算法工作在两个层面levelA
和levelB
:
滤除那种冲击函数的周期信号,可以通过陷波滤波。n阶巴特沃兹陷波滤波器的传递函数:
H ( u , v ) = 1 1 + [ D 0 2 D 1 ( u , v ) D 2 ( u , v ) ] H(u,v)= \frac{1}{1+[\frac{D^2_0}{D_1(u,v)D_2(u,v)}]} H(u,v)=1+[D1(u,v)D2(u,v)D02]1
其中:
D 1 ( u , v ) = [ ( u − M / 2 − u 0 ) 2 + ( v − − N / 2 − v 0 ) 2 ] 1 / 2 D1(u,v) = [(u-M/2-u_0)^2 + (v--N/2-v_0)^2]^{1/2} D1(u,v)=[(u−M/2−u0)2+(v−−N/2−v0)2]1/2
D 2 ( u , v ) = [ ( u − M / 2 + u 0 ) 2 + ( v − − N / 2 + v 0 ) 2 ] 1 / 2 D2(u,v) = [(u-M/2+u_0)^2 + (v--N/2+v_0)^2]^{1/2} D2(u,v)=[(u−M/2+u0)2+(v−−N/2+v0)2]1/2
其中,(u0,v0)和(-u0,-v0)
是陷波
的位置。D0是它们的半径。只需要根据原理参照前面频域滤波的代码就行。
一般来说,典型的方法是通过产生PSF以及测试各种复原算法的结果来做实验。或者是试图用数学方法把PSF模型化,这种不是讨论的主流。若没有任何关于PSF的信息时,可以用盲去卷积
来推断PSF。
在图像复原问题中遇到得一个主要的退化就是图像模糊。一般来说有两种模糊:
fspecial
来建模PSF = fspecial('motion', len, theta)
它由近似于有len
个像素的摄像机的线性移动的效果。参数theta
以度为单位,以顺时针方向对正水平轴度量。len
默认为9,theta
默认是0.
可以用imfilter
创建一个已知PSF
或用刚刚描述的方法计算得到的PSF
退化图像:
g=imfilter(f,PSF, 'circular')
其中参数circular
用来减少边界效应。
然后g = g+noise;
添加适当的噪声来构造退化的图像模型。
用checkerboard
生成一个类似于国际象棋棋盘的图像,
C=checkerboard(NP, M, N)
NP是正方形一边的像素,M是行数,N是列数。
测试板左半部分的亮正方形是白色的,右半部分的亮正方形是灰色的,若要全部亮正方形为白色,可这样写:
K = im2double(checkerboard(NP, M, N) > 0.5);
函数B = pixeldup(A, m, n)
可以将A的每个像素在垂直方向上总共复制m次,水平复制n次
function B=pixeldup(A,m,n)%pixeldup用来重复像素的,在水平方向复制m倍,在垂直方向复制n倍,m,n必须为整数,n没有赋值默认为m
%检查输入参数个数
if nargin<2
error('At least two inputs are required.');
end
if nargin==2
n=m;
end
u=1:size(A,1);%产生一个向量,其向量中元素的个数为A的行数
%复制向量中每个元素m次
m=round(m);%防止m为非整数
u=u(ones(1,m),:);
u=u(:);
%在垂直方向重复操作
v=1:size(A,2);
n=round(n);
v=v(ones(1,n),:);
v=v(:);
B=A(u,v);
所以这样写出代码:
f = checkerboard(8);
imshow(pixeldup(f, 4), [ ]);
PSF = fspecial('motion', 7, 45);
gb = imfilter(f, PSF, 'circular');
noise = imnoise(zeros(size(f)), 'gaussian', 0, 0.001);
g = gb +noise;
subplot(1,3,1);
imshow(pixeldup(f, 4), [ ]);
subplot(1,3,2);
imshow(pixeldup(noise, 4), [ ]);
subplot(1,3,3);
imshow(pixeldup(g, 4), [ ]);
用于复原一幅退化函数的图像的最简单方法则是:
F ^ ( u , v ) = G ( u , v ) H ( u , v ) \hat{F}(u,v) = \frac{G(u,v)}{H(u,v)} F^(u,v)=H(u,v)G(u,v)
然后采用对其逆变换来得到图像的估计。这种方法称为逆滤波。当然也可以这样表示:
F ^ ( u , v ) = F ( u , v ) + N ( u , v ) H ( u , v ) \hat{F}(u,v) =F(u,v) + \frac{N(u,v)}{H(u,v)} F^(u,v)=F(u,v)+H(u,v)N(u,v)
所以,即使知道了H(u,v)也不能回复F
。因为噪声的分量是一个随机函数,N
是未知的。
采用逆滤波的最典型方法是 F ^ ( u , v ) = G ( u , v ) H ( u , v ) \hat{F}(u,v) = \frac{G(u,v)}{H(u,v)} F^(u,v)=H(u,v)G(u,v). 为了得到逆,则将频率的范围限制在接近原点的频率。
维纳滤波器
寻找一个是一个能让统计误差函数最小的f
:
e 2 = E { ( f − f ^ ) 2 } e^2 = E\{(f-\hat{f})^2\} e2=E{(f−f^)2}
E是期望值操作符,f是未退化的图像,则频域内可表示为:
F ^ ( u , v ) = [ 1 H ( u , v ) ⋅ ∣ H ( u , v ) ∣ 2 ∣ H ( u , v ) 2 + S η ( u , v ) / S f ( u , v ) ] G ( u , v ) \hat{F}(u,v)=[\frac{1}{H(u,v)}\cdot \frac{|H(u,v)|^2}{|H(u,v)^2+S_\eta(u,v)/S_f(u,v)}]G(u,v) F^(u,v)=[H(u,v)1⋅∣H(u,v)2+Sη(u,v)/Sf(u,v)∣H(u,v)∣2]G(u,v)
其中:
H(u,v)是退化函数
|H(u,v)|2 = H*(u,v)H(u,v) 前者是其副共轭
Sη(u,v)=|H(u,v)|2表示噪声的功率谱
Sf(u,v)=|F(u,v)|2表示退化函数的功率谱
比率Sη/Sf称为噪信功率比
。若噪声功率谱为0,则该比率就成了0.则该滤波器就变为了逆滤波器。
平均噪声功率和平均图像功率可以分别定义为:
η A = 1 M N ∑ u ∑ v S η ( u , v ) f A = 1 M N ∑ u ∑ v S f ( u , v ) 比 率 : R = η A f A \eta_A=\frac{1}{MN}\sum_u\sum_vS_\eta(u,v) \\ f_A=\frac{1}{MN}\sum_u\sum_vS_f(u,v) \\ 比率:R = \frac{\eta_A}{f_A} ηA=MN1u∑v∑Sη(u,v)fA=MN1u∑v∑Sf(u,v)比率:R=fAηA
在matlab里通过函数deconvwnr
实现。有三种语法形式:
fr = deconvwnr(g, PSF)
噪信比为0fr = deconvwnr(g, PSF, NSPR)
手动输入噪信比fr = deconvwnr(g, PSF, NACORR,FACORR)
后两者分别是噪声和为退化的自相关函数。比如要使用该函数恢复:
f = checkerboard(8);
PSF = fspecial('motion', 7, 45);
gb = imfilter(f, PSF, 'circular');
noise = imnoise(zeros(size(f)), 'gaussian', 0, 0.001);
g = gb +noise;
subplot(2,3,1);
imshow(pixeldup(f, 4), [ ]);
subplot(2,3,2);
imshow(pixeldup(noise, 4), [ ]);
subplot(2,3,3);
imshow(pixeldup(g, 4), [ ]);
subplot(2,3,4);
fr1 = deconvwnr(g, PSF);
imshow(fr1, [ ]);
Sn = abs(fft2(noise)).^2;
nA = sum(Sn(:))/prod(size(noise));
Sf = abs(fft2(f)).^2;
fA = sum(Sf(:))/prod(size(f));
R = nA/fA;
subplot(2,3,5);
fr2 = deconvwnr(g, PSF, R);
imshow(fr2, [ ]);
NCORR = fftshift(real(ifft2(Sn)));
ICORR = fftshift(real(ifft2(Sf)));
subplot(2,3,6);
fr3 = deconvwnr(g, PSF, NCORR, ICORR)
imshow(fr3, [ ]);
这是另外一个比较容易实现的线性滤波,IPT文件中也称为正则滤波。其二维离散卷积定义入选:
h ( x , y ) ∗ f ( x , y ) = 1 M N ∑ m = 0 M − 1 ∑ n = 0 N − 1 f ( m , n ) h ( x − m , y − n ) h(x,y) *f(x,y) = \frac{1}{MN}\sum_{m=0}^{M-1}\sum_{n=0}^{N-1}f(m,n)h(x-m,y-n) h(x,y)∗f(x,y)=MN1m=0∑M−1n=0∑N−1f(m,n)h(x−m,y−n)
通过这个公式,我们可以把向量矩阵的形式来将g(x,y)=h(x,y)f(x,y)+η(x,y)表示为:g=Hf+η
然后就是书上暂时还无法理解的推导:
然后使用IPT工具箱里的函数则是:
fr= deconvreg(g, PSF, NOISEPOWER, RANGE)
.
噪声功率与||η||2成比例。RANGE则是求解γ值得范围限制,默认[10-9,109]
比如:
图像大小为6464,噪声方差为0.001,均值为0,则NOISEPOWER估计为:642[0.001-0]≈4
则:
f = checkerboard(8);
PSF = fspecial('motion', 7, 45);
gb = imfilter(f, PSF, 'circular');
noise = imnoise(zeros(size(f)), 'gaussian', 0, 0.001);
g = gb +noise;
subplot(2,3,1);
imshow(pixeldup(f, 4), [ ]);
subplot(2,3,2);
imshow(pixeldup(noise, 4), [ ]);
subplot(2,3,3);
imshow(pixeldup(g, 4), [ ]);
fr1 = deconvreg(g, PSF, 4);
subplot(2,3,4);
imshow(pixeldup(fr1, 4), [ ]);
fr2 = deconvreg(g, PSF, 4, [1e-7 1e7]);
subplot(2,3,5);
imshow(pixeldup(fr2, 4), [ ]);
fr3 = deconvreg(g, PSF, 0.4);
subplot(2,3,6);
imshow(pixeldup(fr2, 4), [ ]);
L-R算法是从最大似然公式中引出来的。图像是用泊松加以模型化。当下面这个迭代收敛时,模型的最大似然函数可以得到一个满意的方程:
f ^ k + 1 ( x , y ) = f ^ k ( x , y ) [ h ( − x , − y ) ∗ g ( x , y ) h ( x , y ) ∗ f ^ k ( x , y ) ] \hat{f}_{k+1}(x,y) = \hat{f}_k(x,y)[h(-x,-y)*\frac{g(x,y)}{h(x,y)*\hat{f}_k(x,y)}] f^k+1(x,y)=f^k(x,y)[h(−x,−y)∗h(x,y)∗f^k(x,y)g(x,y)]
函数是fr = deconvlucy(g, PSF, NUMIT, DAMPAR, WEIGHT)
f = checkerboard(8);
PSF = fspecial('motion', 7, 45);
gb = imfilter(f, PSF, 'circular');
noise = imnoise(zeros(size(f)), 'gaussian', 0, 0.001);
g = gb +noise;
subplot(2,3,1);
imshow(pixeldup(f, 4), [ ]);
subplot(2,3,2);
imshow(pixeldup(noise, 4), [ ]);
subplot(2,3,3);
imshow(pixeldup(g, 4), [ ]);
LIM = ceil(size(PSF, 1)/2);
WEIGHT = zeros(size(g));
WEIGHT(LIM + 1:end - LIM, LIM + 1:end - LIM) = 1;
f3 = deconvlucy(g, PSF, 3, 0.05, WEIGHT);
f10 = deconvlucy(g, PSF, 10, 0.05, WEIGHT);
f50 = deconvlucy(g, PSF, 50, 0.05, WEIGHT);
subplot(2,3,4);
imshow(pixeldup(f3, 4), [ ]);
subplot(2,3,5);
imshow(pixeldup(f10, 4), [ ]);
subplot(2,3,6);
imshow(pixeldup(f50, 4), [ ]);
推理过程及其复杂,所以暂且不管。
语法:[fr, PSFe] = deconvblind(g, INITPSF)
其中,g是退化图像,INITPSF是点扩散函数的初始估计,PSFe是函数最终计算得到的估计值,fr是利用估计的PSF复原的图像。同理参考上一节的内容,它也可以迭代:
[fr, PSFe] = deconvblind(g, INITPSF, NUMIT, DAMPAR, WEIGHT)
后面三个参数与前面一样
一幅定义在(w,z)上的图像f经过几何变形后定义在了(x,y)上的图像g,则这个变换可以表示为(x,y) = T{(w,z)}
例如(x,y) = T{(w,z)} = (w/2,z/2)
则图片的空间大小缩小一半。
当然,用矩阵去操作可能来得快一些,也就是我们的仿射变换
[ x y 1 ] = [ w z 1 ] T = [ w z 1 ] [ t 11 t 12 0 t 21 t 22 0 t 31 t 32 1 ] [x \ y \ 1]=[w\ z\ 1]T=[w\ z\ 1]\begin{bmatrix}t_{11} \ t_{12} \ 0 \\ t_{21} \ t_{22} \ 0 \\ t_{31} \ t_{32} \ 1 \\\end{bmatrix} [x y 1]=[w z 1]T=[w z 1]⎣⎡t11 t12 0t21 t22 0t31 t32 1⎦⎤
通过修改矩阵T,达到不同的移动目的。比如:
IPT利用所谓的tform
结构来表示空间变换。通过maketform
函数创建。
语法为:
tform = maketform(transform_type, T)
type是以下类型之一: affine
、projective
、box
、composite
、custom
tform是个结构体,它作为tformfwd和tforminv
的参数使用。
XY = tformfwd(WZ, tform)
执行正变换。
WZ = tforminv(XY, tform)
执行逆变换。两者使用的是同一tform。
就比如写了一个栅格图来直观的表达仿射变换的效果。
function vistformfwd(tform, wdata, zdata, N)
% VISTFORMFWD Visualize forward geometric transform.
% VISTFORMFWD(TFORM, WDATA, ZDATA, N) shows two plots: an N-by-N grid in
% the W-Z coordinate system, and the spatially transformed grid in the
% X-Y coordinate system. WRANGE and ZRANGE are two-element vectors
% specifying the desired range for the grid. N can be omitted, in which
% case the default value is 10.
if nargin < 4
N = 10;
end
% Create the w-z grid and transform it.
[w, z] = meshgrid(linspace(wdata(1), zdata(2), N), ...
linspace(wdata(1), zdata(2), N));
wz = [w(:) z(:)];
xy = tformfwd([w(:) z(:)], tform);
% Calculate the minimum and maximum values of w and x, as well as z and
% y.These are used so that two plots can be displayed using the same
% scale.
x = reshape(xy(:, 1), size(w));
y = reshape(xy(:, 2), size(z));
wx = [w(:); x(:)];
wxlimits = [min(wx) max(wx)];
zy = [z(:); y(:)];
zylimits = [min(zy) max(zy)];
% Create the w-z plot.
figure()
subplot(1,2,1)
plot(w, z, 'b')
axis equal, axis ij
hold on
plot(w', z', 'b')
hold off
xlim(wxlimits)
ylim(zylimits)
set(gca, 'XAxisLocation', 'top')
xlabel('w'), ylabel('z')
% Create the x-y plot.
subplot(1,2,2)
plot(x, y, 'b')
axis equal, axis ij
hold on
plot(x', y', 'b')
hold off
xlim(wxlimits)
ylim(zylimits)
set(gca, 'XAxisLocation', 'top')
xlabel('x'), ylabel('y')
T1 = [3 0 0; 0 2 0; 0 0 1];
tform1 = maketform('affine', T1);
vistformfwd(tform1, [0 100], [0 100]);
T2 = [1 0 0; .2 1 0; 0 0 1];
tform2 = maketform('affine', T2);
vistformfwd(tform2, [0 100], [0 100]);
Tscale = [1.5 0 0; 0 2 0; 0 0 1];
Tritation = [ cos(pi/4) sin(pi/4) 0
-sin(pi/4) cos(pi/4) 0
0 0 1];
Tshear = [1 0 0; .2 1 0; 0 0 1];
T3 = Tscale * Tritation * Tshear;
tform3 = maketform('affine', T3);
vistformfwd(tform3, [0 100], [0 100]);
一般来说,仿射计算方法可以归为两类,基于正向和反向的两种方法。
正向是顺序扫描每一个输入像素,然后又T{(w,z)}决定的位置直接将值赋值给输出图像。这里面有两个问题,一就是重复赋值,二就是有些输出的像素并没有被赋值。
IPT里的函数imtransform
使用反向映射。反向映射指过程按顺序扫描每个输出图像,用T-1{(x,y)}去计算出输入图像上的对应位置,并赋值。
语法如下:
g = imtransform(f, tform. interp, 'XData', [X range], 'YData', [Y range],'FillValue', Fill_Value)
interp
是一个字符串,用来指明输入像素怎样插值来或得输出图像。可以是nearest
、bilinear
、bicubic
可以省略,默认为bilinear
。
'FillValue', Fill_Value
这俩可选,用于控制输入图像区域之外的像素颜色。
'XData', [X range], 'YData', [Y range]
也是可选,可以指定范围,计算输出图像,可以解决平移的效果
比如这样:
f = checkerboard(50);
s = 0.8;
theta = pi/6;
T = [s*cos(theta) s*sin(theta) 0
-s*sin(theta) s*cos(theta) 0
0 0 1];
tform = maketform('affine', T);
g1 = imtransform(f, tform);
g2 = imtransform(f, tform, 'nearest');
g3 = imtransform(f, tform, 'FillValue', 0.5);
T2 = [1 0 0; 0 1 0; 50 50 1];
tform2 = maketform('affine', T2);
g4 = imtransform(f, tform2);
g5 = imtransform(f, tform2, 'XData', [1 400], 'YData', [1 400], 'FillValue', 0.5);
subplot(2,3,1);
imshow(f);
subplot(2,3,2);
imshow(g1);
subplot(2,3,3);
imshow(g2);
subplot(2,3,4);
imshow(g3);
subplot(2,3,5);
imshow(g4);
subplot(2,3,6);
imshow(g5);
一副图像,在各种情况下,比如镜头,移动,温度等会导致图片产生几何误差。
工具箱支持以控制点为基础的图像配准。控制点可称为联结点。
说白了,类似于pr/AE里的摄像机跟踪。选几个跟踪点,然后图像会被函数缩放至正常图片的居中。
也懒得制作图片了,就记录一下书上的样例吧: