0%

Image Deblur

1. 图片模糊

有多种原因会造成图片的模糊,主要有以下两种

  • 运动模糊,因为在曝光时间内相机或者被摄对象运动造成
  • 失焦模糊,因为对焦失败,被摄物体不在景深范围内造成

2. 运动模糊

首先考虑运动模糊

2022-01-19-16-31-01

本质就是一个运动模糊核(Box filter)和清晰图像的卷积,频域上是一个sinc函数

难点

  • 卷积核难以获取,和远近、运动速度和方向都有关
  • 背景分割
  • 卷积核丢失了高频信息,恢复之后信噪比低

做一些假设,降低问题的难度

  • 只有相机运动,这样卷积核基本固定

假设已知卷积核,那么就可以通过逆变换得到原图像

这里又有不同的方法

  • 直接逆变换,求模糊核的频域逆变换再和模糊图像卷积
  • 维纳滤波,基于均方差最小的原则重新设计的滤波器

2.1. 实验

取一张清晰图片,人为加上一个方向的运动模糊,尝试去噪

  • 在运动较小时,两者都能恢复结果,直接逆变换的效果更好

origin_img_v2_ea7bc059-eb13-469a-856b-c003498b231g

  • 在运动较大时,直接逆变换没法恢复结果,维纳滤波可以复原

origin_img_v2_9a3899e4-8d90-4511-928d-1aaa1e2fdbdg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import cv2
from cv2 import norm
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import balanced_accuracy_score
from numpy import fft

## Read Image and info
image = cv2.imread('test.jpg')
img_h, img_w = image.shape[:2]

## Make sure the image is between 0-255
def normal(array):
array = np.where(array < 0, 0, array)
array = np.where(array > 255, 255, array)
array = array.astype(np.int16)
return array

## Motion Kernerl Defined by user
def MotionKernel(img_h, img_w,size):
blur_kernel=np.zeros((img_h, img_w ))
blur_kernel[int((img_h - 1)/2):int((img_h - 1)/2)+size, int((img_w - 1)/2)] = np.ones(size)
return blur_kernel/size

## Direct Inverse filter
def InvFilter(img,kernel):
input_fft = fft.fft2(img)
PSF_fft = fft.fft2(kernel)
result = fft.ifft2(input_fft / PSF_fft)
result = np.abs(fft.fftshift(result))
return result

## Use Wiener Filter to adaptive deblur
def WienerFilter(img,kernel,K=0.01):
input_fft = fft.fft2(img)
PSF_fft = fft.fft2(kernel)
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

## Blur the image
blur_kernel=MotionKernel(img_h,img_w,11)
blurred = cv2.filter2D(image, -1, blur_kernel)

## Deblur in every channel
b_gray, g_gray, r_gray = cv2.split(blurred.copy())
Result=[]
Result2=[]
for gray in [b_gray, g_gray, r_gray]:
channel =InvFilter(gray,blur_kernel)
channel2 =WienerFilter(gray,blur_kernel)
Result.append(normal(channel))
Result2.append(normal(channel2))
deblur_inv=cv2.merge([Result[2],Result[1],Result[0]])
deblur_wie=cv2.merge([Result2[2],Result2[1],Result2[0]])