【问题标题】:OpenCV Background Subtraction to Improve DetectionOpenCV 背景减法以改善检测
【发布时间】:2018-07-20 19:48:45
【问题描述】:

我能够检测到传送带上的鸡蛋,但问题是,如果传送带上没有鸡蛋,算法仍然会找到对象。

在传送带上检测到鸡蛋:

如果皮带上没有鸡蛋:

为了减少错误检测,我正在检查半径和面积:

if (radius < 100 and radius > 20):
    ....
if area > 2200 and area < 8800:
    ....

但这些检查点不足以防止错误检测。

我试过createBackgroundSubtractorMOG的方法,但是减法后检测不到鸡蛋。

传送带类型可能会有所不同。

从图像中去除静态背景(带)的最佳方法是什么?

代码:

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    th, bw = cv2.threshold(hsv[:, :, 2], 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
    kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
    morph = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
    dist = cv2.distanceTransform(morph, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)

    borderSize = 75
    distborder = cv2.copyMakeBorder(dist, borderSize, borderSize, borderSize, borderSize,
                                    cv2.BORDER_CONSTANT | cv2.BORDER_ISOLATED, 0)
    gap = 10
    kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2*(borderSize-gap)+1, 2*(borderSize-gap)+1))
    kernel2 = cv2.copyMakeBorder(kernel2, gap, gap, gap, gap,
                                    cv2.BORDER_CONSTANT | cv2.BORDER_ISOLATED, 0)

    distTempl = cv2.distanceTransform(kernel2, cv2.DIST_L2, cv2.DIST_MASK_PRECISE)

    nxcor = cv2.matchTemplate(distborder, distTempl, cv2.TM_CCOEFF_NORMED)

    mn, mx, _, _ = cv2.minMaxLoc(nxcor)
    th, peaks = cv2.threshold(nxcor, mx*0.5, 255, cv2.THRESH_BINARY)
    peaks8u = cv2.convertScaleAbs(peaks)

    #fgmask = self.fgbg.apply(peaks8u)

    _,contours, hierarchy = cv2.findContours(peaks8u, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
    peaks8u = cv2.convertScaleAbs(peaks)    # to use as mask

    for cnt in contours:
        try:
            if len(cnt) >= 5:
                (x, y), radius = cv2.minEnclosingCircle(cnt)
                radius = int(radius)
                #print("radius: ", radius)
                if (radius < 100 and radius > 20):
                    ellipse = cv2.fitEllipse(cnt)
                    (center , axis, angle) = ellipse
                    cx,cy = int(center[0]),int(center[1])
                    ax1,ax2 = int(axis[0])-2,int(axis[1])-2
                    orientation = int(angle)
                    area = cv2.contourArea(cnt)
                    if area > 2200 and area < 8800:
                        cv2.ellipse(frame, (cx,cy), (ax1,ax2), orientation, 0, 360, (255,0,0), 2)
                        #cv2.circle(frame, (cx,cy), 1, (0, 255, 0), 15)
                        cv2.putText(frame,str(int(area)),(cx,cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, 0, 1, cv2.LINE_AA)

【问题讨论】:

  • 你也可以上传背景图片吗?你要减去哪个?我猜是光照的问题,背景图像可能不均匀,所以当光照稍微变化导致阴影等时,它会将它们检测为鸡蛋
  • 背景是腰带本身。您的猜测似乎正确,但如果我可以从图像中移除皮带,我只能检测到我想的鸡蛋。
  • 提供你的代码,没有它我们不知道你做错了什么。
  • 我已经添加了检测码。
  • 您正在使用 Otsu 阈值选择。这意味着无论是否有鸡蛋,您总能找到前景。改用固定阈值可能会更好。鸡蛋总是白色的吗?还是您也需要处理棕色鸡蛋?这些可能与传送带的对比度较小,从而使固定阈值不太可靠。

标签: python opencv computer-vision


【解决方案1】:

获取背景图片有两个基本选项:

  1. 在某些设置/校准过程中提前获取特定传送带的背景图像。
  2. 使用数据本身推导出背景,为此您必须移除对象(鸡蛋)。

第二个选项可以通过随时间取每个像素的平均值或中值来实现。鉴于大多数情况下每个像素都显示背景,您将在没有对象的情况下对场景进行相当好的估计。

【讨论】:

    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2014-04-03
    • 2016-06-19
    • 2011-12-07
    • 1970-01-01
    相关资源
    最近更新 更多