【发布时间】:2022-01-09 10:45:31
【问题描述】:
我正在尝试使用 OpenCV 检测二进制图像中的轮廓,然后绘制生成的轮廓多边形以重新创建输入图像。但是,返回 OpenCV 轮廓多边形的表示方式并不容易。
首先,让我们设置数据:
import cv2
import numpy as np
def a_small_hole_with_diagonal_border() -> np.ndarray:
bitmask = np.zeros((10, 10), dtype=np.uint8) + 255
indices = [(2, 2), (2, 3), (2, 4), (2, 5), (2, 6),
(3, 4), (3, 5), (3, 6),
(4, 4), (4, 5), (4, 6)]
row_indices, col_indices = zip(*indices)
bitmask[row_indices, col_indices] = 0
bitmask[5:, 7:] = 0
return bitmask
bitmask = a_small_hole_with_diagonal_border()
padded_bitmask = np.zeros((bitmask.shape[0] + 2, bitmask.shape[1] + 2), dtype=bitmask.dtype)
padded_bitmask[1:-1, 1:-1] = bitmask
这张图是这样的(这些只是matplotlib的截图):
现在我正在运行 findContours 并绘制结果轮廓:
contours, hierarchy = cv2.findContours(image=padded_bitmask,
mode=cv2.RETR_TREE,
method=cv2.CHAIN_APPROX_SIMPLE)
def get_bitmask(*polygons: np.ndarray, width: int, height: int) -> np.ndarray:
image = np.zeros((width, height, 3), dtype=np.uint8)
for polygon in polygons:
polygon = polygon.reshape((-1, 1, 2)).astype(np.int32)
cv2.fillPoly(image, pts=[polygon], color=(0, 0, 255))
return image[..., -1]
get_bitmask(contours[0], 10, 10)
get_bitmask(contours[1], 10, 10)
我得到以下输出:
外围区域的轮廓正是我想要的, 但是对于中间的洞,我想以某种方式勾勒坐标 不代表轮廓的最内边界,而是代表孔的最外边界。 这就是我的意思:
(我手动使用 gimp 将第二个轮廓覆盖在原始图像上)
我想要的是描述孔的这些像素的轮廓(请原谅我的绘画技巧不佳):
所以本质上,如果我在第一个轮廓上绘制第二个轮廓(我正在为此解析树层次结构),我想重新创建输入图像。 我怎样才能做到这一点? 如果我只是按照here 的建议绘制孔的多边形,我会得到错误的结果:
img = np.zeros((10, 10, 3), dtype=np.uint8)
polygon = contours[1].reshape((-1, 1, 2)).astype(np.int32)
cv2.fillPoly(img, polygon, color=(255, 0, 0),)
cv2.CHAIN_APPROX_SIMPLE 和 cv2.CHAIN_APPROX_NONE
我尝试在图像及其逆图像上运行 findContours,然后合并结果,但必须有一种更简单的方法,因为我无法让它在所有情况下都能正常工作,而只需获得正确的表示即可容易很多。
【问题讨论】:
标签: python numpy opencv contour