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

如何检测图像中的模糊区域?重点识别运动模糊

图像运动模糊区域检测方案优化

需求说明

需要实现图像中模糊区域的检测与选中,重点针对运动模糊场景:比如移动硬币照片的左右模糊区域、移动车辆照片的模糊区域。此前采用梯度搜索方法效果最优,但该方法在非均匀背景下失效,无法检测车辆照片中的模糊区域,原实现代码如下:

import cv2
import numpy as np
import blure as bl


def put_mask(image, mask):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return cv2.filter2D(src=gray, ddepth=-1, kernel=mask)

width, height, x, y = 550, 400, 50, 100
img = cv2.imread("car.jpg")
image = img[y:y+height, x:x+width]
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

mask_1 = np.array([ [1, 0, -1],
                    [2,  0, -2],
                    [1, 0, -1]])

mask_2 = np.array([ [1, 2, 1],
                    [0,  0, 0],
                    [-1, -2, -1]])

masked_1 = cv2.filter2D(gray, ddepth=-1, kernel=mask_1)
masked_2 = cv2.filter2D(gray, ddepth=-1, kernel=mask_2)
masked = cv2.bitwise_or(masked_1, masked_2)


cv2.imshow("edges", image)
cv2.imshow("grad", masked)

cv2.waitKey(0)
cv2.destroyAllWindows()

原方法核心问题:所用的Sobel梯度算子仅对边缘强度敏感,非均匀背景的高反差会掩盖模糊区域的低梯度特征,导致检测失效。以下是三种针对性优化方案:


方案1:局部拉普拉斯方差检测

利用拉普拉斯算子的方差反映局部清晰度——模糊区域的拉普拉斯方差远小于清晰区域。通过分块计算方差并阈值化,可得到模糊区域掩码。

实现代码

import cv2
import numpy as np

def detect_blur_laplacian(image, block_size=25, threshold=30):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    laplacian = cv2.Laplacian(gray, cv2.CV_64F)
    h, w = gray.shape
    blur_mask = np.zeros_like(gray, dtype=np.uint8)
    
    # 分块遍历计算方差
    for y in range(0, h, block_size):
        for x in range(0, w, block_size):
            block = laplacian[y:y+block_size, x:x+block_size]
            var = np.var(block)
            if var < threshold:
                blur_mask[y:y+block_size, x:x+block_size] = 255
    
    # 形态学操作优化掩码,消除噪声
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    blur_mask = cv2.morphologyEx(blur_mask, cv2.MORPH_CLOSE, kernel)
    return blur_mask

# 测试逻辑
img = cv2.imread("car.jpg")
width, height, x, y = 550, 400, 50, 100
image = img[y:y+height, x:x+width]
blur_mask = detect_blur_laplacian(image)

# 叠加掩码显示检测结果
result = cv2.bitwise_and(image, image, mask=blur_mask)
cv2.imshow("Original", image)
cv2.imshow("Blur Mask", blur_mask)
cv2.imshow("Detected Blur Areas", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

适用场景

通用模糊检测,支持运动模糊、失焦模糊等多种类型,对非均匀背景有较好适应性。


方案2:运动模糊定向梯度分析

运动模糊具有方向性(如水平运动模糊会导致垂直方向梯度幅度显著降低),通过分析不同方向梯度的均值差异,可精准定位运动模糊区域。

实现代码

import cv2
import numpy as np

def detect_motion_blur(image, threshold=15):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # 计算x、y方向Sobel梯度幅度
    sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
    sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
    mag_x = np.abs(sobel_x)
    mag_y = np.abs(sobel_y)
    
    # 局部平滑梯度幅度,减少噪声干扰
    mean_x = cv2.blur(mag_x, (15,15))
    mean_y = cv2.blur(mag_y, (15,15))
    
    # 判定运动模糊:某一方向梯度均值远低于另一方向,且整体均值低于阈值
    blur_mask = np.zeros_like(gray, dtype=np.uint8)
    mask_horizontal = (mean_y < threshold) & (mean_x > mean_y * 1.5)
    mask_vertical = (mean_x < threshold) & (mean_y > mean_x * 1.5)
    blur_mask[mask_horizontal | mask_vertical] = 255
    
    # 形态学操作优化掩码
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
    blur_mask = cv2.morphologyEx(blur_mask, cv2.MORPH_OPEN, kernel)
    return blur_mask

# 测试逻辑
img = cv2.imread("car.jpg")
width, height, x, y = 550, 400, 50, 100
image = img[y:y+height, x:x+width]
motion_blur_mask = detect_motion_blur(image)

result = cv2.bitwise_and(image, image, mask=motion_blur_mask)
cv2.imshow("Original", image)
cv2.imshow("Motion Blur Mask", motion_blur_mask)
cv2.imshow("Detected Motion Blur", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

适用场景

专门针对运动模糊检测,可区分水平/垂直等运动方向,适合车辆、移动物体的运动模糊检测。


方案3:归一化梯度改进(解决非均匀背景问题)

通过CLAHE局部对比度增强对图像做归一化处理,消除非均匀背景的干扰,再计算梯度幅度,筛选低梯度的模糊区域。

实现代码

import cv2
import numpy as np

def detect_blur_normalized_gradient(image, threshold=20):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # CLAHE增强局部对比度,弱化背景不均影响
    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
    gray_clahe = clahe.apply(gray)
    
    # 计算梯度幅度
    sobel_x = cv2.Sobel(gray_clahe, cv2.CV_64F, 1, 0, ksize=3)
    sobel_y = cv2.Sobel(gray_clahe, cv2.CV_64F, 0, 1, ksize=3)
    mag = np.sqrt(sobel_x**2 + sobel_y**2)
    
    # 局部平滑梯度幅度
    mag_blur = cv2.blur(mag, (10,10))
    # 阈值化得到模糊区域掩码
    blur_mask = np.where(mag_blur < threshold, 255, 0).astype(np.uint8)
    
    # 形态学操作优化掩码
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    blur_mask = cv2.morphologyEx(blur_mask, cv2.MORPH_CLOSE, kernel)
    return blur_mask

# 测试逻辑
img = cv2.imread("car.jpg")
width, height, x, y = 550, 400, 50, 100
image = img[y:y+height, x:x+width]
blur_mask = detect_blur_normalized_gradient(image)

result = cv2.bitwise_and(image, image, mask=blur_mask)
cv2.imshow("Original", image)
cv2.imshow("Normalized Gradient Blur Mask", blur_mask)
cv2.imshow("Detected Blur", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

适用场景

针对非均匀背景下的模糊检测,是原梯度方法的直接优化,兼容性强。


内容的提问来源于stack exchange,提问作者Лев Изъюров

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:25:39