You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV的未知PSF运动模糊去除技术方案问询

针对横向平移运动模糊的Python去模糊方案(基于OpenCV)

核心思路

由于是横向平移拍摄,运动模糊的PSF(点扩散函数)为水平方向线性核,无需手动定义——可通过图像频域分析或帧间运动估计自动生成,再结合维纳滤波/Lucy-Richardson去卷积算法修复模糊,提升画作提取质量。

实现步骤与代码

1. 从视频帧中定位并提取画作区域

先截取视频帧,通过边缘检测定位画面中的画作(避免背景干扰):

import cv2
import numpy as np

# 读取视频指定帧(示例:读取第100帧)
cap = cv2.VideoCapture("museum_video.mp4")
cap.set(cv2.CAP_PROP_POS_FRAMES, 100)
ret, frame = cap.read()
cap.release()

# 转为灰度图(去模糊对灰度图处理更稳定,后续可转回彩色)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 边缘检测+轮廓筛选定位画作
edges = cv2.Canny(gray, 50, 150)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
max_contour = max(contours, key=cv2.contourArea)  # 假设画作是最大轮廓
x, y, w, h = cv2.boundingRect(max_contour)
painting_gray = gray[y:y+h, x:x+w]

2. 自动生成横向平移PSF

通过频域分析估计模糊长度,再生成对应水平线性核:

def create_horizontal_psf(blur_length, kernel_size=31):
    # 生成水平方向运动模糊核
    psf = np.zeros((kernel_size, kernel_size))
    center = kernel_size // 2
    psf[center, center - blur_length//2 : center + blur_length//2 + 1] = 1.0
    psf /= psf.sum()  # 归一化
    return psf

def estimate_blur_length(gray_img):
    # 频域分析自动估计模糊长度
    fft = np.fft.fft2(gray_img)
    fft_shift = np.fft.fftshift(fft)
    magnitude = 20 * np.log(np.abs(fft_shift))
    
    # 提取水平中线频谱,计算峰值间隔推导模糊长度
    mid_row = magnitude.shape[0] // 2
    horizontal_spectrum = magnitude[mid_row, :]
    peaks = np.where(np.diff(np.sign(np.diff(horizontal_spectrum))) < 0)[0] + 1
    
    if len(peaks) >= 2:
        blur_length = int(np.round(gray_img.shape[1] / (peaks[1] - peaks[0])))
        return max(5, min(blur_length, 50))  # 限制合理范围
    return 15  # 默认值

# 生成适配当前帧的PSF
blur_len = estimate_blur_length(painting_gray)
psf = create_horizontal_psf(blur_len)

3. 维纳滤波去模糊(OpenCV实现)

利用频域维纳滤波修复模糊,兼顾去模糊与噪声抑制:

def wiener_deblur(img, psf, noise_var=0.001):
    img_float = img.astype(np.float32) / 255.0
    psf_float = psf.astype(np.float32)
    
    # 频域转换与滤波计算
    img_fft = np.fft.fft2(img_float)
    psf_fft = np.fft.fft2(psf_float, s=img_float.shape)
    signal_var = np.var(img_float)
    wiener_filter = np.conj(psf_fft) / (np.abs(psf_fft)**2 + noise_var / signal_var)
    deblurred_fft = img_fft * wiener_filter
    
    # 逆变换回空域并归一化
    deblurred = np.abs(np.fft.ifft2(deblurred_fft))
    deblurred = (deblurred * 255).astype(np.uint8)
    return deblurred

# 执行去模糊
deblurred_painting = wiener_deblur(painting_gray, psf)

# 对比显示
cv2.imshow("Original", painting_gray)
cv2.imshow("Deblurred", deblurred_painting)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 可选:Lucy-Richardson迭代去模糊

若维纳滤波效果不足,可使用迭代式Lucy-Richardson算法(需安装opencv-contrib-python):

from cv2.ximgproc import lucyRichardsonDeconvolution

img_float = painting_gray.astype(np.float32) / 255.0
psf_float = psf.astype(np.float32)

# 迭代10次(次数可根据模糊程度调整)
deblurred_lucy = lucyRichardsonDeconvolution(img_float, psf_float, 10)
deblurred_lucy = (deblurred_lucy * 255).astype(np.uint8)

cv2.imshow("Lucy-Richardson Deblurred", deblurred_lucy)
cv2.waitKey(0)

优化建议

  • 帧间运动校准:通过cv2.calcOpticalFlowFarneback计算相邻帧光流,精准获取平移距离,进一步提升PSF准确性。
  • 预处理降噪:去模糊前用cv2.fastNlMeansDenoising抑制噪声,避免去卷积过程放大干扰。
  • 彩色图适配:对BGR通道分别执行去模糊,再合并为彩色图像,保留画作色彩信息。

内容的提问来源于stack exchange,提问作者FlorNeufkens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 01:07:34