You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用OpenCV提取图像中新增物体并裁剪指定区域?

如何用OpenCV提取照片中新增物体的裁剪图?

我看了你用OpenCV识别照片中新增物体的代码,目前的问题是直接使用MOG2背景减法得到的前景掩码噪声较多,没法精准框出你想要的红圈物品。咱们一步步调整代码,最终拿到目标区域的裁剪图:

1. 修正背景减法的使用逻辑

你当前代码里连续对im1im2调用apply,但背景减法模型需要先“学习”背景图(也就是im1),再处理新图im2才能得到准确的前景。我们可以先多次输入背景图让模型稳定,再检测新图的变化。

2. 对前景掩码做后处理

原始的前景掩码会有很多细碎的噪声点,用形态学闭操作(先腐蚀再膨胀)可以消除这些噪声,让前景区域更连贯完整。

3. 提取轮廓并裁剪目标区域

拿到干净的掩码后,通过轮廓检测找到前景区域,过滤掉过小的噪声轮廓,再根据轮廓的边界框从新图中裁剪出目标物体。

完整改进代码

import cv2 as cv
import matplotlib.pyplot as plt

def mdisp(image):
    # OpenCV读取的是BGR格式,matplotlib需要RGB格式,转换后再显示
    plt.imshow(cv.cvtColor(image, cv.COLOR_BGR2RGB))
    plt.show()

# 读取前后两张图片
im1 = cv.imread('images/litter-before.jpg')
im2 = cv.imread('images/litter-after.jpg')

# 初始化背景减法器,关闭阴影检测避免干扰
backsub = cv.createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=False)

# 让模型多次学习背景图,确保背景建模稳定
for _ in range(5):
    backsub.apply(im1)

# 处理新图,得到前景掩码
fgmask = backsub.apply(im2)

# 用形态学闭操作去除噪声,调整核大小适配你的图片
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
fgmask = cv.morphologyEx(fgmask, cv.MORPH_CLOSE, kernel)

# 显示处理后的前景掩码
mdisp(fgmask)

# 寻找前景轮廓,只保留最外层轮廓
contours, _ = cv.findContours(fgmask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# 遍历轮廓,裁剪并保存目标区域
for idx, cnt in enumerate(contours):
    # 过滤过小的噪声轮廓,阈值根据你的图片大小调整
    if cv.contourArea(cnt) < 1000:
        continue
    # 获取轮廓的边界框坐标
    x, y, w, h = cv.boundingRect(cnt)
    # 从新图中裁剪目标区域
    cropped_obj = im2[y:y+h, x:x+w]
    # 显示裁剪结果
    mdisp(cropped_obj)
    # 保存裁剪后的图片
    cv.imwrite(f'cropped_item_{idx}.jpg', cropped_obj)

关键细节说明

  • 颜色空间转换:OpenCV默认以BGR格式读取图片,而matplotlib用RGB显示,所以mdisp函数里必须做格式转换,否则图片颜色会失真。
  • 关闭阴影检测:设置detectShadows=False可以避免把阴影误判为新增物体,减少不必要的干扰。
  • 形态学操作:闭操作能填充前景区域的小空洞,同时消除周围的细碎噪声,让轮廓更清晰。
  • 轮廓过滤:通过contourArea过滤小轮廓,可以排除残留的噪声点,只保留真正的新增物体。

如果红圈中的物品是特定类型(比如垃圾、瓶子),后续还可以结合YOLO等目标检测模型进一步精准定位,但如果只是识别任意新增物体,上面的方法就足够满足需求了。

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

火山引擎 最新活动