使用OpenCV进行矩形检测/跟踪

时间:2017-06-13 12:47:43

标签: c++ opencv image-processing object-detection

我需要什么

我目前正致力于增强现实游戏。游戏使用的控制器(我在这里谈论的是物理输入设备)是单色的,长方形的纸片。我必须在摄像机的捕获流中检测该矩形的位置,旋转和大小。检测应该在比例上不变,并且在沿X轴和Y轴旋转时不变。

如果用户将纸张移开或朝向相机移动,则需要缩放不变性。我不需要知道矩形的距离,因此尺度不变性转换为尺寸不变性。

如果用户沿其局部X和/或Y轴倾斜矩形,则需要旋转不变性。这种旋转将纸张的形状从矩形变为梯形。在这种情况下,面向对象的边界框可用于测量纸张的大小。

我做了什么

开始时有一个校准步骤。窗口显示摄像机源,用户必须单击矩形。单击时,鼠标指向的像素颜色将作为参考颜色。帧被转换为HSV颜色空间以改善颜色区分。我有6个滑块可以调整每个通道的上限和下限。这些阈值用于对图像进行二值化(使用opencv的inRange函数) 在那之后,我正在侵蚀和扩展二进制图像以消除噪音并联合nerby块(使用opencv的erodedilate函数)。
下一步是在二进制图像中查找轮廓(使用opencv的findContours函数)。这些轮廓用于检测最小的方向矩形(使用opencv的minAreaRect函数)。作为最终结果,我正在使用面积最大的矩形。

程序的简短结论:

  1. 抓住一个框架
  2. 将该框架转换为HSV
  3. 将其二值化(使用用户选择的颜色和滑块的阈值)
  4. 应用变形操作(侵蚀和扩张)
  5. 查找轮廓
  6. 获取每个轮廓的最小方向的装订盒
  7. 取结果中最大的边界框
  8. 正如您可能已经注意到的那样,我没有利用有关纸张实际形状的知识,只是因为我不知道如何正确使用这些信息。

    我还考虑过使用opencv的跟踪算法。但有三个原因使我无法使用它们:

    1. 比例不变性:据我读到的一些算法,有些不支持对象的不同比例。
    2. 运动预测:一些算法使用运动预测来获得更好的性能,但我跟踪的对象完全随机移动,因此无法预测。
    3. 简单:我只是在图像中寻找单色矩形,没有像汽车或人物跟踪那样花哨。
    4. 这是一个 - 相对 - 好的捕获(侵蚀和扩张后的二进制图像) ok

      这是一个糟糕的 bad

      问题

      如何改善检测效果,特别是更能抵抗光线变化?

      更新

      Here是一些用于测试的原始图像。

      你能不能只使用更厚的材料?
      是的,我可以而且我已经做过了(不幸的是我现在无法访问这些内容)。但问题仍然存在。即使我使用像cartboard这样的材料。它不像纸一样容易弯曲,但仍然可以弯曲它。

      如何获得矩形的大小,旋转和位置?
      opencv的minAreaRect函数返回RotatedRect个对象。该对象包含我需要的所有数据。

      注意
      因为矩形是单色的,所以不可能区分顶部和底部或左右。这意味着旋转始终在[0, 180]范围内,这对我来说完全没问题。 rect的两边的比率总是w:h > 2:1。如果矩形是方形,则旋转范围将变为[0, 90],但这可以认为是无关紧要的。

      正如评论中所建议的,我将尝试使用直方图均衡来减少亮度问题并查看ORB,SURF和SIFT。

      我会更新进度。

2 个答案:

答案 0 :(得分:3)

我知道自从我提出这个问题以来已经有一段时间了。我最近继续讨论这个主题并解决了我的问题(虽然没有通过矩形检测)。

更改

  • 使用木材强化我的控制器(“矩形”),如下所示。
  • 在每个控制器上放置2个ArUco标记。

Controller

工作原理

  • 将帧转换为灰度,
  • 下采样(以提高检测期间的性能),
  • 使用cv::equalizeHist
  • 均衡直方图
  • 使用cv::aruco::detectMarkers
  • 查找标记
  • 关联标记(如果有多个控制器),
  • 分析标记(位置和旋转),
  • 计算结果并应用一些纠错。

事实证明,标记检测对于光照变化和不同的视角非常稳健,这使我可以跳过任何校准步骤。

我在每个控制器上放置了2个标记,以进一步提高检测稳健性。两个标记只需要检测一次(以测量它们的相关性)。之后,每个控制器只能找到一个标记就足够了,因为另一个可以从先前计算的相关性中推断出来。

这是在明亮环境中的检测结果:

Detection in a bright environment

在更黑暗的环境中:

Detection in a dark environment

当隐藏其中一个标记时(蓝点表示外推标记后):

Detection of missing markers

故障

我实施的初始形状检测效果不佳。照明变化非常脆弱。此外,它需要一个初始校准步骤。

在形状检测方法之后,我尝试将SIFT和ORB与蛮力和knn匹配器结合使用来提取和定位框架中的特征。事实证明,单色物体并没有提供太多关键点(令人惊讶的是)。无论如何,SIFT的表现都很糟糕(大约10 fps @ 540p)。 我在控制器上绘制了一些线条和其他形状,从而产生了更多的关键点。然而,这并没有带来巨大的改善。

答案 1 :(得分:2)

HSV空间中的H通道是Hue,它对光线变化不敏感。红色范围约为[150,180]。

根据提到的信息,我做了以下工作。

  1. 切换到HSV空间,拆分H通道,阈值并将其标准化。
  2. 应用变形操作(打开)
  3. 查找轮廓,按某些属性(宽度,高度,面积,比率等)进行过滤。
  4. PS。由于NETWORK,我无法获取您在Dropbox上传的图像。所以,我只使用裁剪the right side of your second image作为输入。

    enter image description here

    imgname = "src.png"
    img = cv2.imread(imgname)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    ## Split the H channel in HSV, and get the red range
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h,s,v = cv2.split(hsv)
    h[h<150]=0
    h[h>180]=0
    
    ## normalize, do the open-morp-op
    normed = cv2.normalize(h, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)
    kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(3,3))
    opened = cv2.morphologyEx(normed, cv2.MORPH_OPEN, kernel)
    res = np.hstack((h, normed, opened))
    cv2.imwrite("tmp1.png", res)
    

    现在,我们得到结果(h,normed,open):

    enter image description here

    然后找到轮廓并过滤它们。

    contours = cv2.findContours(opened, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    print(len(contours))[-2]
    
    bboxes = []
    rboxes = []
    cnts = []
    dst = img.copy()
    for cnt in contours:
        ## Get the stright bounding rect
        bbox = cv2.boundingRect(cnt)
        x,y,w,h = bbox
        if w<30 or h < 30 or w*h < 2000 or w > 500:
            continue
    
        ## Draw rect
        cv2.rectangle(dst, (x,y), (x+w,y+h), (255,0,0), 1, 16)
    
        ## Get the rotated rect
        rbox = cv2.minAreaRect(cnt)
        (cx,cy), (w,h), rot_angle = rbox
        print("rot_angle:", rot_angle)  
    
        ## backup 
        bboxes.append(bbox)
        rboxes.append(rbox)
        cnts.append(cnt)
    

    结果如下:

    rot_angle: -2.4540319442749023
    rot_angle: -1.8476102352142334
    

    enter image description here

    由于源图像中的蓝色矩形标签,卡片被分成两侧。但是干净的图像没有问题。