我找到了一个阈值图像的轮廓并像这样画出来:
self.disc_contour = cv2.findContours(self.thresh.copy(), cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE)[1]
cv2.drawContours(self.original_image, self.disc_contour, -1, (0,255,0), 2)
我按照需要得到轮廓:
(忽略内圈。外部是上下文中的轮廓)
但如果我将drawContour函数中的self.disc_contour
更改为self.disc_contour[0]
,我会得到以下结果:
可能是什么原因?
答案 0 :(得分:2)
注意:特定于OpenCV 3.x
cv2.findContours
的第二个结果是轮廓列表。
cv.drawContours
的第二个参数应为轮廓列表。
轮廓表示为点的列表(或数组)。每个点都是一个坐标列表。
如何仅绘制单个轮廓有多种方法:
import cv2
src_img = cv2.imread("blob.png")
gray_img = cv2.cvtColor(src_img, cv2.COLOR_BGR2GRAY)
contours = cv2.findContours(gray_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)[1]
print(contours)
# Choose one:
# Draw only first contour from the list
cv2.drawContours(src_img, contours, 0, (0,255,0), 2)
# Pass only the first contour (v1)
cv2.drawContours(src_img, [contours[0]], -1, (0,255,0), 2)
# Pass only the first contour (v2)
cv2.drawContours(src_img, contours[0:1], -1, (0,255,0), 2)
cv2.imshow("Contour", src_img)
cv2.waitKey()
示例输入图像:
当我们检查cv2.findContours
的结果时,您看到点的原因变得明显 - 有4个级别的嵌套。
[
array([
[[ 95, 61]], # Point 0
[[ 94, 62]], # Point 1
[[ 93, 62]],
... <snip> ...
[[ 98, 61]],
[[ 97, 61]],
[[ 96, 61]]
]) # Contour 0
]
根据本回答开头的定义,我们可以看到这种情况下的要点包含在附加列表中,例如: [[ 98, 61]]
。 OpenCV显然正确地解决了这个问题 - 我想这是一个特色。
如果我们仅使用contours
的第一个元素删除外部列表,我们会有效地将每个点转换为包含单个点的单独轮廓。
array([
[
[ 95, 61] # Point 0
], # Contour 0
[
[ 94, 62] # Point 0
], # Contour 1
... and so on
])