Matlab数字图像处理学习记录【4】——图像复原

一.图像退化/复原处理的模型

退化函数是指将退化过程模型化,它和加性噪声项一起,作用于输入图像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有两个函数otf2psfpsf2otf用于OTFPSF之间的转换。

二.噪声模型

2.1使用imnoise添加噪声

基本语法:
g = imnoise(f, type, parameters)

  • f在进行运算的时候,会被转换成一个[0,1]的double类图像,后续操作要考虑参数的取值
  • imnoise(f, 'gaussian', m, var)将均值为m方差为var的高斯噪声加载图像f上,默认均值为0.方差为0.01的噪声
  • imnoise(f, 'localvar', V)将均值为0、局部方差为V的高斯噪声添加到图像f上,其中Vf大小相同的数组,它包含了每个店的理想方差值。
  • imnoise(f, 'localvar', image_intensity, var). 将均值为0的高斯噪声添加到图像f上,其中噪声的局部方差var是图像f的亮度值的函数,参量image_intensityvar是大小相同的向量,plot(image_intensity, var)绘制出噪声方差和图像亮度的函数关系。向量image_intensity的取值范围必须是[0,1]
  • imnoise(f, 'salt & pepper', d)则是椒盐噪声污染图像f,其中d是噪声密度(即包含噪声值得图像区域的百分比)。因此,大约有d*numel(f)个像素受到了影响,默认密度为0.05
  • imnoise(f, 'speckle', var)用方程g=f+n*f将乘性噪声添加到图像f上,其中n是均值为0,方差为var的均匀分布的随机噪声,var默认0.04
  • imnoise(f, 'poisson')从数据中,产生泊松噪声。遵守泊松统计,这个听描述很复杂。

2.2使用指定的分布产生空间随机噪声

空间噪声值时随机数,以概率密度函数PDF或相应的累积分布函数CDF表征。
所以许多函数都是在区间(0,1)内具有均匀CDF的随机数生成问题为基础的。但是更有意义的是用rand生成均匀随机数及使用函数randn生成正态(高斯)随机数。
假设w是区间(0,1)内均匀分布的随机变量,则可以通过求解以下方程来得到具有指定CDF和Fz的随机变量z
z = F z − 1 ( w ) z = F^{-1}_z(w) z=Fz1(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)={ 1e(za)2/b,0,zaza
为了z可解:
1 − e − ( z − a ) 2 / b = w 1-e^{-(z-a)^2/b} = w 1e(za)2/b=w

z = a + b   l n ( 1 − w ) z = a+ \sqrt{b\ ln(1-w)} z=a+b ln(1w)
这样可以生成一个参数为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(1w) 有时可称为随机数生成器方程,因为它确定了如何生成需要的随机数。
下标列出了当前讨论中,一些随机变量,以及他们的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

效果:
在这里插入图片描述

2.3 周期噪声

图像的周期噪声一般产生于图像采集过程中的电器或电机等干扰,一般来说,是从空间域滤波处理。一般来说,它的模型是这样的:
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)δ(uu0,vv0)]
也就是说,这是一个位于(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, [ ]);

效果如下:
在这里插入图片描述

扫描二维码关注公众号,回复: 12959979 查看本文章

2.4估计噪声参数

周期噪声一般是通过分析频谱实现,只要图片的频谱不太离谱,那么离谱的那个尖峰就是噪声。所以,在噪声尖峰明显或者知道了干扰频率的情况下,是可以自动分析然后滤掉的。
假设噪声的均值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=0L1(zim)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=0L1zip(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=0L1(zim)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)
那么,选用空间滤波是最好的方法。

3.1 空间噪声滤波器

常见的几种滤波器的数学公式:
在这里插入图片描述
有函数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

效果的话,没有合适的图片,也不会有太大的差异。

3.2自适应空间滤波器

算法稍微比较复杂,这里记录算法思路:
Zmin表示Sxy最小亮度值
Zmax表示Sxy最大亮度值
Zmod表示Sxy中的亮度中值
Zxy表示坐标(x,y)处的亮度值。
这个算法工作在两个层面levelAlevelB

  • levelA
    • 若Zmin<Zmod<Zmax,则转向levelB
    • 否则增加窗口尺寸
    • 若窗口尺寸≤Smax,则重复leveA
    • 否则输出Zmod
  • levelB
    • 若Zmin<Zxy<Zmax,则输出Zxy
    • 否则输出Zmod

四.频域滤波降低周期噪声

滤除那种冲击函数的周期信号,可以通过陷波滤波。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)=[(uM/2u0)2+(vN/2v0)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)=[(uM/2+u0)2+(vN/2+v0)2]1/2
其中,(u0,v0)和(-u0,-v0)
陷波的位置。D0是它们的半径。只需要根据原理参照前面频域滤波的代码就行。

五.退化函数建模

一般来说,典型的方法是通过产生PSF以及测试各种复原算法的结果来做实验。或者是试图用数学方法把PSF模型化,这种不是讨论的主流。若没有任何关于PSF的信息时,可以用盲去卷积来推断PSF。
在图像复原问题中遇到得一个主要的退化就是图像模糊。一般来说有两种模糊:

  1. 由场景和传感器两者产生的模糊,可以用空间域或者频域的低通滤波器来建模。
  2. 在获取传感器和场景之间的均匀线性运动而产生的图像模糊。这个可以用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{ (ff^)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)1H(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=MN1uvSη(u,v)fA=MN1uvSf(u,v):R=fAηA
在matlab里通过函数deconvwnr实现。有三种语法形式:

  1. fr = deconvwnr(g, PSF) 噪信比为0
  2. fr = deconvwnr(g, PSF, NSPR)手动输入噪信比
  3. 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=0M1n=0N1f(m,n)h(xm,yn)
通过这个公式,我们可以把向量矩阵的形式来将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]
比如:
图像大小为64
64,噪声方差为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), [ ]);

在这里插入图片描述

九. 使用Lucy-Richardson算法的迭代非线性复原

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)

  • NUMIT是迭代次数
  • DAMPAR是结果图像与原图像g的偏离阈值。当像素值偏离原值的范围在DAMPAR之内时,就不用在迭代
  • WEIGHT则是与g同样大小的数组。作用一当然就是过滤部分不良像素。作用二则是可以剔除图像边界的像素点。比如PSF大小为n×n,则WEIGHT的零边界宽度则是ceil(n/2)
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)后面三个参数与前面一样

十一.集合变换与图像配准

11.1 空间几何变换

一幅定义在(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是以下类型之一: affineprojectiveboxcompositecustom
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]);

在这里插入图片描述

11.2对图像应用空间变换

一般来说,仿射计算方法可以归为两类,基于正向和反向的两种方法。
正向是顺序扫描每一个输入像素,然后又T{(w,z)}决定的位置直接将值赋值给输出图像。这里面有两个问题,一就是重复赋值,二就是有些输出的像素并没有被赋值。
IPT里的函数imtransform使用反向映射。反向映射指过程按顺序扫描每个输出图像,用T-1{(x,y)}去计算出输入图像上的对应位置,并赋值。
语法如下:
g = imtransform(f, tform. interp, 'XData', [X range], 'YData', [Y range],'FillValue', Fill_Value)
interp是一个字符串,用来指明输入像素怎样插值来或得输出图像。可以是nearestbilinearbicubic可以省略,默认为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);

在这里插入图片描述

11.3图像配准

一副图像,在各种情况下,比如镜头,移动,温度等会导致图片产生几何误差。
工具箱支持以控制点为基础的图像配准。控制点可称为联结点。
说白了,类似于pr/AE里的摄像机跟踪。选几个跟踪点,然后图像会被函数缩放至正常图片的居中。
在这里插入图片描述
在这里插入图片描述
也懒得制作图片了,就记录一下书上的样例吧:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u011017694/article/details/113380872