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

仅对图像中抛射体添加运动模糊而非整图的高效实现问询

问题:仅对抛射体区域添加水平运动模糊,保留背景清晰

我是图像分析新手,现有一张含静止抛射体的图像,已获取其轮廓数组,格式如下:

contour = [[x1 x2 x3,..., xn]
[y1 y2 y3,..., yn]]

其中(x1,y1),(x2,y2),...,(xn,yn)是抛射体轮廓的像素坐标。

我想给抛射体添加水平运动模糊,模拟它相对背景运动的效果。最初直接对整图应用水平模糊核:

# 创建水平模糊核
kernel_h = np.zeros((kernel_size, kernel_size))
# 填充中间行为1
kernel_h[int((kernel_size - 1)/2), :] = np.ones(kernel_size)
# 归一化
kernel_h /= kernel_size

然后用卷积实现:

horizonal_blurred_image = cv2.filter2D(src=img, ddepth=-1, kernel=kernel_h)

结果虽然有运动模糊,但背景也被模糊了——这是因为整图都做了水平均值计算,相当于模拟相机运动,而非抛射体相对背景运动。

之后我尝试用cv2.pointPolygonTest判断像素是否在轮廓内或边缘,想给轮廓外像素用单位核(不模糊),轮廓内/边缘用水平核,写了个函数:

def Motion_Blur_Kernel(img, kernel_size,x,y, contour):
    # img:原始未模糊图像
    # kernel_size:核大小,越大模糊效果越强
    # contour:轮廓点数组,格式[[x1...xn],[y1...yn]]
    
    # 判断像素位置
    result = cv2.pointPolygonTest(np.column_stack(contour_x_values, contour_y_values), (x,y), False)
    if result == 1 or result == 0:
        # 创建水平核
        kernel_h = np.zeros((kernel_size, kernel_size))
        kernel_h[int((kernel_size - 1)/2), :] = np.ones(kernel_size)
        kernel_h /= kernel_size
    else:
        # 单位核,不改变像素
        kernel_h = [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
    return kernel_h

但不知道怎么高效把这个核和原图卷积,因为要处理100张图,效率很重要。


高效实现方案

核心思路

不用逐像素判断并应用不同核,而是先分别生成模糊后的抛射体区域和原始背景区域,再通过掩码合并两者,所有操作基于OpenCV/numpy的底层优化实现,速度远快于Python循环。

步骤代码

  1. 生成抛射体掩码
    用cv2.drawContours快速生成二值掩码,轮廓内/边缘为白色(255),背景为黑色(0):

    import cv2
    import numpy as np
    
    # 转换轮廓为OpenCV要求的格式:(N,1,2)的int32数组
    contour_opencv = np.column_stack((contour[0], contour[1])).reshape(-1, 1, 2).astype(np.int32)
    # 创建与原图尺寸一致的单通道掩码
    mask = np.zeros_like(img[:, :, 0])
    # 填充轮廓内部
    cv2.drawContours(mask, [contour_opencv], 0, 255, thickness=cv2.FILLED)
    
  2. 对整图应用水平模糊
    生成水平核并模糊整张图:

    kernel_size = 15  # 可根据需求调整,建议用奇数
    kernel_h = np.zeros((kernel_size, kernel_size))
    kernel_h[int((kernel_size - 1)/2), :] = np.ones(kernel_size)
    kernel_h /= kernel_size
    blurred_img = cv2.filter2D(img, ddepth=-1, kernel=kernel_h)
    
  3. 合并模糊目标与原始背景
    通过掩码拼接两个区域,两种方法任选:

    # 方法1:numpy索引(简洁高效)
    result_img = img.copy()
    result_img[mask == 255] = blurred_img[mask == 255]
    
    # 方法2:位运算(适合复杂掩码场景)
    blurred_object = cv2.bitwise_and(blurred_img, blurred_img, mask=mask)
    original_background = cv2.bitwise_and(img, img, mask=cv2.bitwise_not(mask))
    result_img = cv2.add(blurred_object, original_background)
    

效率说明

  • 所有操作都是OpenCV/numpy的C++底层实现,避免了Python级别的逐像素循环,单张图处理时间与整图卷积相当。
  • 处理100张图的总耗时仅为逐像素方法的几十分之一,完全满足效率需求。

注意事项

  • 确保轮廓格式转换正确,OpenCV的drawContours要求输入轮廓为(N,1,2)的int32类型数组。
  • 彩色图像无需生成多通道掩码,单通道掩码即可作用于所有颜色通道。
  • kernel_size选奇数时,中间行的索引计算更直观(如size=15时,中间行索引为7)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 19:23:15