运动模糊是指由于相机和物体之间的相对运动造成的模糊,又称为动态模糊。
一、已知模糊核的运动模糊
在已知模糊运动核的前提下,可通过核线性卷积的形式对图像添加运动模糊。
#-*- coding:utf-8 -*-
import cv2 as cv
import numpy as np
import math
from PIL import Image
import matplotlib.pyplot as plt
def motion_PSF(image_size, motion_angle, motion_dis):
'''
建立退化模型,仿真运动模糊
INPUT -> 图像尺寸, 运动角度, 模糊尺度
OUTPUT -> PSF(点扩散函数)
'''
PSF = np.zeros(image_size)
x_center = (image_size[0] - 1) / 2
y_center = (image_size[1] - 1) / 2
sin_val = math.sin(motion_angle * math.pi / 180)
cos_val = math.cos(motion_angle * math.pi / 180)
# 将对应角度上motion_dis个点置成1
for i in range(motion_dis):
x_offset = round(sin_val * i)
y_offset = round(cos_val * i)
PSF[int(x_center-x_offset),int(y_center+y_offset)] = 1
return PSF / PSF.sum() #对点扩散函数进行归一化亮度
def make_blurred(img_arr, PSF, eps):
'''
对图片进行运动模糊
INPUT -> 图像数组, PSF(点扩散函数), 噪声
OUTPUT -> 模糊后的图像
'''
# 将空间域转化为频率域
img_f = np.fft.fft2(img_arr)
PSF_f = np.fft.fft2(PSF)
blurred = np.fft.ifft2(img_f * PSF_f)
blurred = np.abs(np.fft.fftshift(blurred))
return blurred
def array_to_image(image_arr):
'''
数组还原为图片
INPUT -> 数组
OUTPUT -> 单张图文件
'''
if len(image_arr.shape) == 3: # 格式为(height(rows), weight(colums), 3)
r = Image.fromarray(np.uint8(image_arr[:,:,0]))
g = Image.fromarray(np.uint8(image_arr[:,:,1]))
b = Image.fromarray(np.uint8(image_arr[:,:,2]))
image = Image.merge("RGB", (r, g, b))
return image
elif len(image_arr.shape) == 2: # 格式为(height(rows), weight(colums))
return Image.fromarray(np.uint8(image_arr))
img_arr = np.array(Image.open('tools/33.jpg').convert('L'))
PSF = motion_PSF((img_arr.shape[0], img_arr.shape[1]), 30, 15)
blurred = make_blurred(img_arr, PSF, 1e-4)
# 可视化
plt.imshow(array_to_image(blurred))
plt.show()
反之也可利用该核精确的去除该运动模糊。
使用逆滤波可以精确还原图像,但是它对噪声非常敏感。
最小均方差(维纳)滤波用来还原含有噪声的模糊图像,但是需要估计图像的信噪比(SNR)或者噪信比(NSR)。若无噪声,此时维纳滤波相当于逆滤波,恢复运动模糊效果是极好的。
def inverse(blurred, PSF, eps):
'''
逆滤波图像还原
INPUT -> 模糊图像, 点扩散函数, 噪声
'''
blurred_f = np.fft.fft2(blurred)
PSF_f = np.fft.fft2(PSF) + eps # 噪声功率
result = np.fft.ifft2(blurred_f / PSF_f) # 计算F(u,v)的傅里叶反变换
result = np.abs(np.fft.fftshift(result))
return result
def wiener(blurred, PSF, eps, SNR=0.001):
'''
维纳滤波图像还原
INPUT -> 模糊图像, 点扩散函数, 噪声功率, 信噪比0.01
'''
blurred_f = np.fft.fft2(blurred)
PSF_f = np.fft.fft2(PSF) + eps
PSF_f_1 = np.conj(PSF_f) /(np.abs(PSF_f)**2 + SNR)
result = np.fft.ifft2(blurred_f * PSF_f_1)
result = np.abs(np.fft.fftshift(result))
return result
img2 = inverse(blurred, PSF, 0)
img2 = wiener(blurred, PSF, 0)
二、未知模糊核的运动模糊
在实际应用场景是不知道的运动模糊的卷积核的。
1、Richardson-Lucy算法
Richardson–Lucy算法是一个在泊松噪声背景下用于图像恢复的迭代技术。迭代公式:
对于没有噪声干扰的理想模糊图像,迭代次数越多恢复的效果越好。每次迭代时,都会提高解的似然性,随着迭代次数的增加,最终将会收敛在最大似然性的解,但随着迭代次数的增加也会增加计算量。
对于含有噪声干扰的模糊图像,随着迭代次数的增加噪声被放大,而且迭代时间随之增长。当迭代超过50次后,恢复结果并没有明显改观。
2、基于GAN的去运动模糊
DeblurGAN是Orest Kupyn等人于17年11月提出的一种模型。他们结合GAN和多元内容损失来构建DeblurGAN,以实现对运动图像的去模糊化。
DeblurGAN