首页 文章

OpenCV Python - 不同的Contour近似方法具有相同的输出[重复]

提问于
浏览
2

这个问题在这里已有答案:

根据this Python教程,OpenCV cv2.findContours 函数有两种Contour Approximation方法: cv2.CHAIN_APPROX_NONEcv2.CHAIN_APPROX_SIMPLE . 第一个存储所有边界点,第二个方法删除所有冗余点 .

import cv2

im = cv2.imread('simple.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, 
cv2.CHAIN_APPROX_SIMPLE)

img = cv2.drawContours(im, contours, -1, (0, 255, 0), 3)


cv2.imshow('Output', img)
wk = cv2.waitKey(0) & 0xFF
if wk == 27:
    cv2.destroyAllWindows()

但是这个代码输出相同的图像,无论它使用什么方法 .

这是代码执行后的图像:Output

绿线是轮廓 . 如您所见,矩形由绿线包围,但应仅由4个点定义,每个角一个 .

2 回答

  • 1

    如果你看一下教程,特别是它的文本底部是:

    只需在轮廓阵列中的所有坐标上绘制一个圆圈(以蓝色绘制) .

    Mehul Jain是正确的,如果你使用 cv2.drawContours 它只是在绘制轮廓时将点连接在一起 . 您不会明显看到两种近似方法之间的差异 . 你需要做的是 draw circles 而不是 .

    因此,一旦运行 cv2.findContours ,就可以使用 contours 输出,该输出是图像中找到的所有轮廓的列表 . 因为只有一个可能的轮廓,因为它是一个正方形,所以列表应该是一个元素长 . 另请注意,输出将是 (N, 1, 2) 3D NumPy数组,因此最好在继续之前将其重新整形为2列数组 .

    接下来,您可以使用 cv2.circle 实际获取每个点并绘制单个圆而不是实际轮廓 . 只有这样你才能真正看到差异 .

    上面的代码并修改它以便我们执行这两种方法,我们应该这样做:

    ### Your code
    import numpy as np
    import cv2
    
    im = cv2.imread('simple.jpg')
    imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
    ret,thresh = cv2.threshold(imgray,127,255,0)
    
    ### Step #1
    # Detect contours using both methods on the same image
    _, contours1, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    _, contours2, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    
    ### Step #2 - Reshape to 2D matrices
    contours1 = contours1[0].reshape(-1,2)
    contours2 = contours2[0].reshape(-1,2)
    
    ### Step #3 - Draw the points as individual circles in the image
    img1 = im.copy()
    img2 = im.copy()
    
    for (x, y) in contours1:
        cv2.circle(img1, (x, y), 1, (255, 0, 0), 3)
    
    for (x, y) in contours2:
        cv2.circle(img2, (x, y), 1, (255, 0, 0), 3)
    
    ### Step #4 - Stack the two images side by side and show it
    out = np.hstack([img1, img2])
    cv2.imshow('Output', out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    让我们慢慢地浏览代码 . 代码的第一部分就是您提供的内容 . 现在我们进入新的领域 .

    步骤#1 - 使用两种方法检测轮廓

    使用阈值图像,我们使用完整和简单近似检测轮廓 . 它存储在两个列表中, contours1contours2 .

    步骤#2 - 重塑为2D矩阵

    轮廓本身存储为NumPy数组列表 . 对于提供的简单图像,应该只检测到一个轮廓,因此提取出列表的第一个元素,然后使用 numpy.reshape 将3D矩阵重新整形为2D形式,其中每一行都是 (x, y) 点 .

    步骤#3 - 将点绘制为图像中的各个圆圈

    下一步是从每组轮廓中取出每个 (x, y) 点并在图像上绘制它们 . 我们以彩色形式制作原始图像的两个副本,然后我们使用 cv2.circle 并遍历每对 (x, y) 点以获得两组轮廓并填充两个不同的图像 - 每组轮廓一个 .

    步骤#4 - 将两个图像并排堆叠并显示出来

    我们最终使用 numpy.hstack 水平堆叠图像,然后显示结果 . 您将看到左图像是完整轮廓近似的两个图像,而右图像是简化版本 .

  • 2

    我想这是因为你使用的是drawContours()函数,它会从字面上绘制轮廓 . 如果你想看到差异,即只是点,我认为你应该尝试绘制返回的点,而不是使用drawContours()函数 .

相关问题