这个问题在这里已有答案:
根据this Python教程,OpenCV cv2.findContours 函数有两种Contour Approximation方法: cv2.CHAIN_APPROX_NONE 和 cv2.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 回答
如果你看一下教程,特别是它的文本底部是:
Mehul Jain是正确的,如果你使用
cv2.drawContours
它只是在绘制轮廓时将点连接在一起 . 您不会明显看到两种近似方法之间的差异 . 你需要做的是 draw circles 而不是 .因此,一旦运行
cv2.findContours
,就可以使用contours
输出,该输出是图像中找到的所有轮廓的列表 . 因为只有一个可能的轮廓,因为它是一个正方形,所以列表应该是一个元素长 . 另请注意,输出将是(N, 1, 2)
3D NumPy数组,因此最好在继续之前将其重新整形为2列数组 .接下来,您可以使用
cv2.circle
实际获取每个点并绘制单个圆而不是实际轮廓 . 只有这样你才能真正看到差异 .上面的代码并修改它以便我们执行这两种方法,我们应该这样做:
让我们慢慢地浏览代码 . 代码的第一部分就是您提供的内容 . 现在我们进入新的领域 .
步骤#1 - 使用两种方法检测轮廓
使用阈值图像,我们使用完整和简单近似检测轮廓 . 它存储在两个列表中,
contours1
和contours2
.步骤#2 - 重塑为2D矩阵
轮廓本身存储为NumPy数组列表 . 对于提供的简单图像,应该只检测到一个轮廓,因此提取出列表的第一个元素,然后使用
numpy.reshape
将3D矩阵重新整形为2D形式,其中每一行都是(x, y)
点 .步骤#3 - 将点绘制为图像中的各个圆圈
下一步是从每组轮廓中取出每个
(x, y)
点并在图像上绘制它们 . 我们以彩色形式制作原始图像的两个副本,然后我们使用cv2.circle
并遍历每对(x, y)
点以获得两组轮廓并填充两个不同的图像 - 每组轮廓一个 .步骤#4 - 将两个图像并排堆叠并显示出来
我们最终使用
numpy.hstack
水平堆叠图像,然后显示结果 . 您将看到左图像是完整轮廓近似的两个图像,而右图像是简化版本 .我想这是因为你使用的是drawContours()函数,它会从字面上绘制轮廓 . 如果你想看到差异,即只是点,我认为你应该尝试绘制返回的点,而不是使用drawContours()函数 .