4.3 Python图像处理之图像恢复-无约束滤波器(逆滤波)、有约束滤波器(维纳滤波器)
1 算法原理
逆滤波与维纳滤波算法。
图像复原是一种客观的操作,通过使用退化现象的先验知识重建或恢复一副退化的图像;图像在形成、传输和记录的过程中,由于受多种原因的影响,图像的质量会有下降,典型表现为图像模糊、失真、有噪声等,这一降质的过程称为图像的退化。而图像复原试图利用退化现象的某种先验知识(即退化模型),把已经退化了的图像加以重建和复原。其目的就是尽可能地减少或去除在获取图像过程中发的图像质量的下降(退化),恢复被退化图像的本来面目。
图像复原基本思路:弄清退化原因,建立退化模型,反向推演,恢复图像。
逆滤波复原过程:对退化的图像进行二位傅里叶变换;计算系统点扩散函数的二位傅里叶变换;引入 H(fx,fy)计算并且对结果进行逆傅里叶变换。
维纳滤波:在一定的约束条件下,其输出与一给定函数(通常称为期望输出)的差的平方达到最小,通过数学运算最终可变为一个托布利兹方程的求解问题。维纳滤波器又被称为最小二乘滤波器或最小平方滤波器,目前是基本的滤波方法之一。维纳滤波是利用平稳随机过程的相关特性和频谱特性对混有噪声的信号进行滤波的方法。
逆滤波:简单的就是将退化函数去除,直接的逆滤波没有什么意义,只处理了靠近直流分量的部分,其他不做处理。如果加入巴特沃斯低通滤波器,效果会好点,可是在运动模糊的图片中就不好使了。
2 代码
运行代码说明
1.要改变代码中的图片地址(地址不能有中文)
更改
put(path)
函数中的路径put(r'../image/image1.jpg')
2.注意最后的
plt.savefig('1.new.jpg')
是保存plt图像,如果不使用可以注释掉
import math
import os
import numpy as np
from numpy import fft
import cv2
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 仿真运动模糊
def motion_process(image_size, motion_angle):
PSF = np.zeros(image_size)
center_position = (image_size[0] - 1) / 2
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
# 维纳滤波,K=0.01
def wiener(input, PSF, eps, 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
def put(path):
img = cv2.imread(path, 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_h = img.shape[0]
img_w = img.shape[1]
# 进行运动模糊处理
PSF = motion_process((img_h, img_w), 60)
blurred = np.abs(make_blurred(img, PSF, 1e-3))
# 逆滤波
res1 = inverse(blurred, PSF, 1e-3)
# 维纳滤波
res2 = wiener(blurred, PSF, 1e-3)
# 添加噪声,standard_normal产生随机的函数
blurred_noisy = blurred + 0.1 * blurred.std() * np.random.standard_normal(blurred.shape)
# 对添加噪声的图像进行逆滤波
res3 = inverse(blurred_noisy, PSF, 0.2 + 1e-3)
# 对添加噪声的图像进行维纳滤波
res4 = wiener(blurred_noisy, PSF, 0.2 + 1e-3)
plt.subplot(2, 3, 1), plt.axis('off'), plt.imshow(blurred, plt.cm.gray), plt.title('运动模糊')
plt.subplot(2, 3, 2), plt.axis('off'), plt.imshow(res1, plt.cm.gray), plt.title(' 逆滤波')
plt.subplot(2, 3, 3), plt.axis('off'), plt.imshow(res2, plt.cm.gray), plt.title(' 维纳滤波(k=0.01)')
plt.subplot(2, 3, 4), plt.axis('off'), plt.imshow(blurred_noisy, plt.cm.gray), plt.title('有噪声且运动模糊')
plt.subplot(2, 3, 5), plt.axis('off'), plt.imshow(res3, plt.cm.gray), plt.title(' 逆滤波')
plt.subplot(2, 3, 6), plt.axis('off'), plt.imshow(res4, plt.cm.gray), plt.title(' 维纳滤波(k=0.01)')
# plt.savefig('3.new.jpg')
plt.show()
# 图像处理函数,要传入路径
put(r'../image/image3.jpg')