使用OpenCV/Python对二值掩模进行轮廓处理。

3

使用Python和OpenCV,我正在检测二进制掩模的轮廓:

import numpy as np
import cv2
import matplotlib.pyplot as plt

mask = np.zeros(20000, dtype=np.uint8).reshape(100, 200)
mask[5:-5,5:-5] = 255
mask[10:70,40:80] = 0
plt.subplot(121)
plt.imshow(mask, cmap='Greys_r', interpolation='none')

_, contours, hierarchy = cv2.findContours(mask.copy(), 
                                          cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE,
                                          offset=(0, 0))

导致预期行为:
plt.subplot(122)
cv2.drawContours(mask, contours, -1, (127, 127, 127), 2)
plt.imshow(mask, cmap='Greys_r',  interpolation='none')
plt.show()

简单的OpenCV轮廓

然而,我似乎无法理解完全激活掩模的结果:

mask = np.ones(20000, dtype=np.uint8).reshape(100, 200)
mask *=255
_, contours, hierarchy = cv2.findContours(mask.copy(),
                                            cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE,
                                            offset=(0, 0))

print contours[0]

这会产生:

(1   1), (1  98), (198 98), (198 1)

而不是 (0 0), (0 99), (199, 99), (199, 0)

为什么opencv的findcontours函数表现得像这样,带有偏移量1?


通过精确执行您的最后一段代码,我得到了(0 0),(0 99),(199, 99),(199, 0)。 - Soltius
1个回答

5

在OpenCV 3.1之前,findContours函数在边缘上有奇怪的行为,也在文档中说明:

该函数会修改源图像。此外,该函数不考虑图像的1像素边界(由0填充并用于算法中的邻域分析),因此与图像边界相接触的轮廓将被裁剪。

这个问题已在OpenCV 3.2中得到修正,同时也不会修改源图像

自OpenCV 3.2以来,该函数不会修改源图像。


作为以前版本的解决方法,您可以使用copyMakeBorder创建一个1像素的黑色(0)边框,并使用带有偏移量(-1,-1)findContours
border = cv2.copyMakeBorder(mask, 1, 1, 1, 1, cv2.BORDER_CONSTANT, value=0 )
_, contours, hierarchy = cv2.findContours(border, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE, offset=(-1, -1))

谢谢您提供的两种方法。我期待在Python上使用OpenCV3.2,并在此期间继续使用您的第一种方法。 - mxdbld

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接