用OpenCV/Python轮廓化二进制掩码
使用Python和OpenCV,我正在检测二进制掩码的轮廓:
With Python and OpenCV I am detecting contours of a binary mask:
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()
但是,我似乎无法理解完全激活的遮罩的结果:
However, I cannot seem to understand the result of a full activated mask :
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?
Why is opencv findcontours behaving like that, with an offset of 1?
直到OpenCV 3.1 findContours
具有文档:
Until OpenCV 3.1 findContours
has this wierd behaviour on borders, also stated in the documentation:
此功能修改了源图像.此外,该功能未考虑到图像的1像素边界(它用0填充并在算法中用于邻居分析),因此将剪切与图像边界接触的轮廓.
Source image is modified by this function. Also, the function does not take into account 1-pixel border of the image (it's filled with 0's and used for neighbor analysis in the algorithm), therefore the contours touching the image border will be clipped.
由于opencv 3.2源映像未被此功能修改.
Since opencv 3.2 source image is not modified by this function.
作为以前版本的一种解决方法,可以使用copyMakeBorder
创建1像素的黑色(0)边框,并使用偏移量为(-1,-1)
的findContours
:
As a workaround for previous releases, you can use copyMakeBorder
to create a black (0) border of 1 pixel, and use findContours
with an offset of (-1,-1)
:
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))