【问题标题】:How to transform contours obtained from OpenCV to SHP file polygons?如何将从 OpenCV 获得的轮廓转换为 SHP 文件多边形?
【发布时间】:2020-04-01 12:49:36
【问题描述】:

我已经使用 OpenCV 从掩码图像中成功提取了轮廓:

image = cv2.imread(file)

lower = np.array([240, 240, 240])
upper = np.array([255, 255, 255])
shape_mask = cv2.inRange(image, lower, upper)

contours, hierarchy = cv2.findContours(shape_mask.copy(), cv2.RETR_CCOMP,
                                       cv2.CHAIN_APPROX_SIMPLE)

现在我该如何继续将此轮廓映射到一个多边形列表(带孔)中,并将它们导出为 SHP 文件?

这里给出部分答案: How to convert NumPy arrays obtained from cv2.findContours to Shapely polygons?

但是,这忽略了多边形内部有孔的情况。我将如何继续获得所有多边形?

【问题讨论】:

  • 多个嵌套轮廓会发生什么?例如,我们不能将三个嵌套的轮廓表示为带孔的 Shapely Polygon。
  • 我也想过这个。我在 GitHub 上找到的解决方案(见下文)通过创建一个 MultiPolygon 来解决这个问题,该 MultiPolygon 包含第一个轮廓作为带孔的多边形(第二个轮廓),第三个轮廓也作为带孔的多边形等。我对其进行了测试,它工作得很好(在 QGis 中打开很好)。关键是函数 cv2.findContours 中的“cv2.RETR_CCOMP”标志。

标签: python opencv polygon shapely


【解决方案1】:

找到答案: https://michhar.github.io/masks_to_polygons_and_back/

帮助从蒙版图像创建 MultiPolygons 作为 numpy 数组:

def mask_to_polygons(mask, epsilon=10., min_area=10.):
    """Convert a mask ndarray (binarized image) to Multipolygons"""
    # first, find contours with cv2: it's much faster than shapely
    image, contours, hierarchy = cv2.findContours(mask,
                                  cv2.RETR_CCOMP,
                                  cv2.CHAIN_APPROX_NONE)
    if not contours:
        return MultiPolygon()
    # now messy stuff to associate parent and child contours
    cnt_children = defaultdict(list)
    child_contours = set()
    assert hierarchy.shape[0] == 1
    # http://docs.opencv.org/3.1.0/d9/d8b/tutorial_py_contours_hierarchy.html
    for idx, (_, _, _, parent_idx) in enumerate(hierarchy[0]):
        if parent_idx != -1:
            child_contours.add(idx)
            cnt_children[parent_idx].append(contours[idx])
    # create actual polygons filtering by area (removes artifacts)
    all_polygons = []
    for idx, cnt in enumerate(contours):
        if idx not in child_contours and cv2.contourArea(cnt) >= min_area:
            assert cnt.shape[1] == 1
            poly = Polygon(
                shell=cnt[:, 0, :],
                holes=[c[:, 0, :] for c in cnt_children.get(idx, [])
                       if cv2.contourArea(c) >= min_area])
            all_polygons.append(poly)
    all_polygons = MultiPolygon(all_polygons)

    return all_polygons

创建这些辅助函数的功劳:

这些助手的原始来源是 Konstantin 的 Kaggle 帖子 Lopuhin here - 你需要登录 Kaggle 才能看到它

【讨论】:

    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-09-09
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 1970-01-01
    • 2014-05-21
    相关资源
    最近更新 更多