我在python中使用OpenCV轮廓函数。例如,在这样的图像上:
contours, _ = cv2.findContours(img_expanded_padded, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
除了如上图所示切掉轮廓内侧的角落外,它的效果很好。是否有任何选择可以留在这个角落?
沿着轮廓行进并手动填充它们的计算成本太高。以上只是一个例子。这将在5400x5400或更高的图像上多次执行...
我可以使用下面的代码找到边缘,并且因此填充了角落,但是我需要再次将它们提取为轮廓。
# FIND ALL HORIZONTAL AND VERTICAL EDGES AND COMBINE THEM
edges_expanded_x = np.absolute(cv2.Sobel(img_expanded_padded,cv2.CV_64F, 1, 0, ksize=3))
edges_expanded_y = np.absolute(cv2.Sobel(img_expanded_padded,cv2.CV_64F, 0, 1, ksize=3))
edges_expanded = np.logical_or(edges_expanded_x, edges_expanded_y)
# GET RID OF DOUBLE EDGE THAT RESULTS FROM SOBEL FILTER
edges_expanded = np.multiply(img_expanded_padded,edges_expanded)
我可以使用任何OpenCV设置或功能来完成此任务吗?
编辑:我应该澄清,我的目标是拥有一个像素连续轮廓。我需要轮廓而不是整个图像的阵列,包括轮廓。
编辑:上面的图像放大到我的测试图像。实际像素如下图中的红色网格所示。
没有必要使用cv2.Sobel
你可以简单地在黑色背景上绘制cv2.drawContours
的轮廓。可以在np.zeros的帮助下绘制黑色背景。
img = cv2.imread('contouring.png',0)
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
bgr = np.zeros((img.shape[0], img.shape[1]), dtype= 'uint8')
cv2.drawContours(bgr, contours, -1, (255,255,255), 1)
如果你想要轮廓线很粗,那么你可以使用cv2.dilate
。然后,为了防止切角cv2.bitwise_and
可以与cv2.bitwise_not
一起使用,如下所示
bgr = cv2.dilate(bgr, np.ones((31, 31), np.uint8), iterations=1)
bgr = cv2.bitwise_and(bgr, cv2.bitwise_not(img))
编辑 - 薄轮廓的第一个图像仍在偷工减料。为了获得不是角的单像素轮廓,我们可以使用3 * 3的内核大小。
img = cv2.imread('contouring.png',0)
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
bgr = np.zeros((img.shape[0], img.shape[1]), dtype= 'uint8')
cv2.drawContours(bgr, contours, -1, (255,255,255), 1)
bgr = cv2.dilate(bgr, np.ones((3, 3), np.uint8), iterations=1)
bgr = cv2.bitwise_and(bgr, cv2.bitwise_not(img))
我通过在bgr和img之间使用cv2.bitwise_and
来检查它,我获得了一个黑色图像,表明没有白色像素正在切角。