如何识别与我的对象相关的轮廓并找到它们的几何质心

How to identify contours associated with my objects and find their geometric centroid

问题陈述和背景信息:

编辑:约束:法兰上的红色随时间变化,所以我现在不尝试使用颜色识别来识别我的对象,除非它可以强壮的。此外,外部照明也是一个因素,因为这将在未来的室外区域进行。

我有 RGB-Depth 相机,有了它,我能够捕捉到这个场景。其中每个像素 (x,y) 都有一个深度值。

对与我的图像关联的深度图应用梯度幅度过滤器,我能够得到以下边缘图。

如果梯度幅度不为零,则梯度幅度的值为 0。黑色 (255) 表示与 0(均匀深度或平面)相关联的幅度值。

从这张边缘图中,我对边缘进行了拨号,这样拾取轮廓会更容易。

然后我找到了图像中的等高线,并尝试只绘制 5 个最大的等高线。

问题

有没有办法可靠地找到与我的对象(红色盒子和金属夹具)关联的轮廓,然后找到它们的几何质心?我一直在 运行 解决我可以在图像中找到轮廓的问题,但是我无法选择性地筛选属于我的对象而不是噪声的轮廓。

我提供了我用于图像处理的图像,但由于某些原因,OpenCV 将图像保存为黑色图像,当您在使用.. .

gray = cv2.imread('GRAYTEST.jpeg', cv2.IMREAD_GRAYSCALE)

它看起来是蓝色的,而不是我展示的二进制 white/black 图像。很抱歉。

图片如下:

抱歉,我不知道为什么它只保存为黑色图像,但如果您在 OpenCV 中阅读它,它应该显示与 "magnitude of gradients" 图相同的线条。

我的代码

    gray = cv2.imread('GRAYTEST.jpeg', cv2.IMREAD_GRAYSCALE)
    plt.imshow(gray)
    plt.title('gray start image')
    plt.show()

    blurred = cv2.bilateralFilter(gray, 8, 25, 25)  # blurr image while preserving edges
    kernel = np.ones((3, 3), np.uint8)  # define a kernel (block) to apply filters to

    dialated = cv2.dilate(blurred, kernel, iterations=1)
    plt.title('dialated')
    plt.imshow(dialated)
    plt.show()

    #Just performs a canny edge dectection on an image
    edges_empty = self.Commons.CannyE_Auto(dialated)  # Canny edge image for some sigma
    #makes an empty image using the same diemensions of the given image
    empty2 = self.Commons.make_empty(gray)

    _, contours, _ = cv2.findContours(edges_empty, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = sorted(contours, key=cv2.contourArea, reverse=True)[:5]  # get largest five contour area
    cv2.drawContours(empty2, cnts, -1, (255, 0, 0), thickness=1)

    plt.title('contours')
    plt.imshow(empty2)
    plt.show()
  1. 我没有对已经阈值化的图像执行模糊操作、拨号、canny 边缘检测,而是对原始图像执行了轮廓检测。

  2. 然后通过修改 findContour 命令,我能够为我的图像轮廓找到一个像样的轮廓。

    _, 轮廓, _ = cv2.findContours(灰色, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

用 cv2.RETR_EXTERNAL 替换 cv2.RETR_TREE 我只能得到与对象轮廓相关联的轮廓,而不是试图在内部得到轮廓物体。切换到 cv2.CHAIN_APPROX_NONE 并没有显示出任何明显的改进,但它可能会为更复杂的几何图形提供更好的轮廓。

        for c in cnts:
        # compute the center of the contour
        M = cv2.moments(c)
        cX = int(M["m10"] / M["m00"])
        cY = int(M["m01"] / M["m00"])

        # draw the contour and center of the shape on the image
        cv2.drawContours(empty2, [c], -1, (255, 0, 0), thickness=1)
        perimeter = np.around(cv2.arcLength(c, True), decimals=3)
        area = np.around(cv2.contourArea(c), decimals=3)

        cv2.circle(empty2, (cX, cY), 7, (255, 255, 255), -1)
        cv2.putText(empty2, "center", (cX - 20, cY - 20),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

        cv2.putText(empty2, "P:{}".format(perimeter), (cX - 50, cY - 50),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

        cv2.putText(empty2, "A:{}".format(area), (cX - 100, cY - 100),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

使用上面的代码,我能够标记每个轮廓的质心以及每个轮廓周长和面积的信息。

但是,我无法执行 select 哪个轮廓是我想要的轮廓的测试。我有一个想法,可以在更理想的环境中捕捉我的物体,并找到它的质心、周长和相关区域。这样,当我找到一个新的轮廓时,我可以将它与它与我的已知值的接近程度进行比较。

我认为这种方法可以去除太大或太小的轮廓。

如果有人知道更好的解决方案,那就太棒了!