python实现逆滤波与维纳滤波

 构建运动模糊模型

        现假定相机不动,图像f(x,y)在图像面上移动并且图像f(x,y)除移动外不随时间变化。令x0(t)和y0(t)分别代表位移的x分量和y分量,那么在快门开启的时间T内,胶片上某点的总曝光量是图像在移动过程中一系列相应像素的亮度对该点作用之总和。也就是说,运动模糊图像是由同一图像在产生距离延迟后与原图像想叠加而成。如果快门开启与关闭的时间忽略不计,则有:

                                                                  g(x,y)=\int_{0}^{T}f[x-x_{0}(t)), y-y_{0}(t))]dt

        由于各种运动都是匀速直线运动的叠加,因而我们只需考虑匀速直线运动即可。但由于我们自身水平有限,且旨在探讨找到实现运动模糊复原方法的思想与方向,因而我们未能自行构建模型,而是借鉴了参考文献[1]中建立的运动模糊模型。关于本模型的理论依据参见参考文献[1].

        下面我们描述一下该模型函数motion_process(image_size,motion_angle),它包含两个参数:图像的尺寸大小image_size以及运动的角度motion_angle。

例如,当运动位移为9、运动角度为45度时,则该模型函数的构建过程如下:

  1. 首先是创建与图像同等大小的全0矩阵,然后找到全0矩阵的中心行数center_position,再计算出运动角度的tan值与cot值,算出运动的偏移量offset。
  2. 再令α≤45°时,PSF[int(center_position+offset),int(center_position-offset)]=1
  3. α≥45°时,PSF[int(center_position-offset),int(center_position+offset)]=1

则该模型对应的图像如下图所示:

python实现逆滤波与维纳滤波_第1张图片python实现逆滤波与维纳滤波_第2张图片python实现逆滤波与维纳滤波_第3张图片

运动位移为9,运动角度分别为45°、30°、60°时,运动模糊模型对应的图像

import matplotlib.pyplot as graph
import numpy as np
from numpy import fft
import math
import cv2

# 仿真运动模糊
def motion_process(image_size,motion_angle):
    PSF = np.zeros(image_size)
    print(image_size)
    center_position=(image_size[0]-1)/2
    print(center_position)

    slope_tan=math.tan(motion_angle*math.pi/180)
    slope_cot=1/slope_tan
    if slope_tan<=1:
        for i in range(15):
            offset=round(i*slope_tan)    #((center_position-i)*slope_tan)
            PSF[int(center_position+offset),int(center_position-offset)]=1
        return PSF / PSF.sum()  #对点扩散函数进行归一化亮度
    else:
        for i in range(15):
            offset=round(i*slope_cot)
            PSF[int(center_position-offset),int(center_position+offset)]=1
        return PSF / PSF.sum()

#对图片进行运动模糊
def make_blurred(input, PSF, eps):
    input_fft = fft.fft2(input)# 进行二维数组的傅里叶变换
    PSF_fft = fft.fft2(PSF)+ eps
    blurred = fft.ifft2(input_fft * PSF_fft)
    blurred = np.abs(fft.fftshift(blurred))
    return blurred

def inverse(input, PSF, eps):       # 逆滤波
    input_fft = fft.fft2(input)
    PSF_fft = fft.fft2(PSF) + eps #噪声功率,这是已知的,考虑epsilon
    result = fft.ifft2(input_fft / PSF_fft) #计算F(u,v)的傅里叶反变换
    result = np.abs(fft.fftshift(result))
    return result

def wiener(input,PSF,eps,K=0.01):        #维纳滤波,K=0.01
    input_fft=fft.fft2(input)
    PSF_fft=fft.fft2(PSF) +eps
    PSF_fft_1=np.conj(PSF_fft) /(np.abs(PSF_fft)**2 + K)
    result=fft.ifft2(input_fft * PSF_fft_1)
    result=np.abs(fft.fftshift(result))
    return result

image = cv2.imread('you.jpg')
image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
img_h=image.shape[0]
img_w=image.shape[1]
graph.figure(1)
graph.xlabel("Original Image")
graph.gray()
graph.imshow(image)     #显示原图像

graph.figure(2)
graph.gray()
#进行运动模糊处理
PSF = motion_process((img_h,img_w), 60)
blurred = np.abs(make_blurred(image, PSF, 1e-3))

graph.subplot(231)
graph.xlabel("Motion blurred")
graph.imshow(blurred)

result = inverse(blurred, PSF, 1e-3)   #逆滤波
graph.subplot(232)
graph.xlabel("inverse deblurred")
graph.imshow(result)

result=wiener(blurred,PSF,1e-3)     #维纳滤波
graph.subplot(233)
graph.xlabel("wiener deblurred(k=0.01)")
graph.imshow(result)

blurred_noisy=blurred + 0.1 * blurred.std() * \
           np.random.standard_normal(blurred.shape)   #添加噪声,standard_normal产生随机的函数

graph.subplot(234)
graph.xlabel("motion & noisy blurred")
graph.imshow(blurred_noisy)      #显示添加噪声且运动模糊的图像

result = inverse(blurred_noisy, PSF, 0.1+1e-3)    #对添加噪声的图像进行逆滤波
graph.subplot(235)
graph.xlabel("inverse deblurred")
graph.imshow(result)

result=wiener(blurred_noisy,PSF,0.1+1e-3)          #对添加噪声的图像进行维纳滤波
graph.subplot(236)
graph.xlabel("wiener deblurred(k=0.01)")
graph.imshow(result)

graph.show()

参考文献

[1] 何红英. 运动模糊图像恢复算法的研究与实现[D]. 西安科技大学硕士学位论文. 2011.

[2] Rafael C.Gonzalez,Richard E.Woods,Steven L.Eddins. 数字图像处理的MATLAB实现(第2版)[M]. 阮秋琦,译. 北京:清华大学出版社,2013.

[3] 陈建功. 运动模糊图像复原算法研究[D]. 南昌航空大学硕士学位论文. 2012.

你可能感兴趣的:(python实现逆滤波与维纳滤波)