import cv2
import numpy as np
from scipy import signal
from scipy.fft import fft2, ifft2
def motion_kernel(length, angle):
"""生成运动模糊核(PSF)"""
angle = np.deg2rad(angle)
kernel = np.zeros((length, length))
center = length // 2
x = np.linspace(-center, center, length)
y = np.round(x * np.tan(angle)).astype(int)
for i in range(length):
if center + y[i] >= 0 and center + y[i] < length:
kernel[center + y[i], i] = 1
kernel = kernel / kernel.sum()
return kernel
def wiener_deblur(img, kernel, K=0.01):
"""维纳滤波去模糊"""
img_fft = fft2(img)
kernel_fft = fft2(kernel, s=img.shape)
kernel_fft_conj = np.conj(kernel_fft)
wiener = kernel_fft_conj / (np.abs(kernel_fft)**2 + K)
img_deblur_fft = img_fft * wiener
img_deblur = np.abs(ifft2(img_deblur_fft))
img_deblur = np.uint8(np.clip(img_deblur, 0, 255))
return img_deblur
def rl_blind_deconvolution(img, iterations=30):
"""Richardson-Lucy 盲去卷积"""
img = img.astype(np.float32)
img_est = np.copy(img)
kernel = np.ones((5, 5)) / 25
for i in range(iterations):
img_blur_est = signal.convolve2d(img_est, kernel, mode='same', boundary='symm')
ratio = img / (img_blur_est + 1e-6)
img_est *= signal.convolve2d(ratio, np.flip(kernel), mode='same', boundary='symm')
img_est = np.uint8(np.clip(img_est, 0, 255))
return img_est
if __name__ == "__main__":
img = cv2.imread("motion_blur.jpg", 0)
kernel = motion_kernel(15, 0)
img_wiener = wiener_deblur(img, kernel)
img_rl = rl_blind_deconvolution(img, iterations=30)
result = np.hstack((img, img_wiener, img_rl))
cv2.imwrite("deblur_result.jpg", result)
cv2.imshow("Original | Wiener | RL Blind Deconvolution", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
dev_close_window()
dev_open_window(0, 0, 1200, 400, 'black', WindowHandle)
*1. 读取图像与参数设置
read_image(ImgBlur, 'motion_blur.jpg') // 运动模糊图像
get_image_size(ImgBlur, Width, Height)
convert_image_type(ImgBlur, ImgBlurFloat, 'real')
*2. 生成运动模糊核(长度 15 像素,水平方向)
gen_kernel_motion(Kernel, 15, 0, 'constant', 'normalized')
*3. 维纳滤波去模糊
wiener_filter(ImgBlurFloat, ImgWiener, Kernel, 0.01, 'none')
convert_image_type(ImgWiener, ImgWienerByte, 'byte')
*4. 盲去卷积(Richardson-Lucy)
deconvolve_blind(ImgBlurFloat, ImgRL, Kernel, 30, 1, 'rl')
convert_image_type(ImgRL, ImgRLByte, 'byte')
*5. 显示结果
dev_display(ImgBlur)
disp_message(WindowHandle, 'Original Motion Blur', 'window', 10, 10, 'black', 'true')
dev_set_window_pos(WindowHandle, 0, Width + 20)
dev_display(ImgWienerByte)
disp_message(WindowHandle, 'Wiener Filter', 'window', 10, 10, 'black', 'true')
dev_set_window_pos(WindowHandle, 0, 2*Width + 40)
dev_display(ImgRLByte)
disp_message(WindowHandle, 'RL Blind Deconvolution', 'window', 10, 10, 'black', 'true')
* 输出统计信息
get_image_grayval(ImgBlur, Width/2, Height/2, GrayValBlur)
get_image_grayval(ImgWienerByte, Width/2, Height/2, GrayValWiener)
disp_message(WindowHandle, 'Blur Gray Value: ' + GrayValBlur, 'window', 30, 10, 'black', 'true')
disp_message(WindowHandle, 'Wiener Gray Value: ' + GrayValWiener, 'window', 30, 10, 'black', 'true')