代码之家  ›  专栏  ›  技术社区  ›  Eduardo

从numpy布尔网格获取多边形的外部坐标

  •  2
  • Eduardo  · 技术社区  · 8 年前

    我试图从一个numpy布尔网格中获取多边形的外部坐标。例如,从(16,16)ndarray,例如下面的一个

    [
        [False False False False False False  True  True  True  True False False False False False False],
        [False False False False False  True  True  True  True  True  True False False False False False],
        [False False False False False False False False False False  True  True False False False False],
        [False False False False False False False False False False  False True False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False],
        [False False False False False False False False False False False False False False False False]
    ]
    

    如果我们把它画出来 ndarray 如下所示:

    Boolean grid as image

    我想得到以下坐标,以便我们可以画出这样的多边形的外环,例如。, [(5 1), (6 0), (7 0), (8 0), (9 0), (10 1), (11 2), (11 3), (10 2), (9 1), (8 1), (7 1), (6 1)] 。到目前为止,我掌握的情况如下:

    # Consider that the boolean ndarray above is called 'prediction'
    
    import numpy as np
    from shapely.geometry import Polygon, Point
    import matplotlib.pyplot as plt
    
    # Get the coordinates that match the boolean polygon
    (y, x) = np.where(prediction == True)
    
    # Iterate on each of the coordinates, however my problem is that it is not aware of the contour order as it should be :/
    coordinates = [Point(x_coordinate, y_coordinate) for x_coordinate, y_coordinate in itertools.izip(x, y)]
    # Build the polygon out of the points
    polygon = Polygon([[coordinate.x, coordinate.y] for coordinate in coordinates])
    
    exterior_x, exterior_y = polygon.exterior.xy
    
    # Plotting
    
    fig = plt.figure(1, figsize=(5, 5))
    ax = fig.add_subplot(1, 2, 1)
    ax.plot(exterior_x, exterior_y, color='#6699cc')
    ax.invert_yaxis()
    
    plt.subplot(1, 2, 2)
    plt.imshow(prediction)
    plt.show()
    

    问题是我在构建多边形时没有考虑顺序,因此 polygon.exterior.xy 将创建外环。我的方法将创建错误的多边形轮廓,例如:

    enter image description here

    然而,我无法找到解决这个问题的一般方法。我欢迎任何关于如何解决这个问题的建议。提前谢谢。

    2 回复  |  直到 8 年前
        1
  •  3
  •   eguaio    8 年前

    也许你可以把问题转移到 GIS stack exchange site 。在这方面,您可能会得到更多帮助。

    总之,快速搜索显示 this anwer ,建议使用 rasterio 图书馆,我知道这是你需要的。

    根据您的情况进行调整,可以是:

    import numpy as np
    import rasterio.features
    
    # Convert your array to 0-1 integers
    myarray = [[1 if t else 0 for t in row] for row in myarray]
    # Build a numpy array
    myarray = np.array(myarray)
    # Convert the type (don't even know why this was needed in my computer, but raised exception if not converted.
    myarray = myarray.astype(np.int32)
    
    # Let the library do the magic. You should take a look at the rasterio.features.shapes output
    mypols = [p[0]['coordinates'] 
                       for p in  rasterio.features.shapes(myarray)]
    

    mypols 现在是可以轻松转换为的坐标数组 shapely 多边形。

    小心正确测试陌生人案例。我尝试构建一个多多边形,库将每个连接的组件作为多边形返回。幸运的是,它为每个多边形返回关联的值,因此您可以根据需要进行后期处理。 不过,带内环的多边形似乎处理得不错。 我不知道你在这种情况下会有什么样的行为。

        2
  •  0
  •   Jean Rostan    8 年前

    我会使用ConvexHull,它试图找到包含所有点的最小包络线,即多边形轮廓: ConvexHull with Scipy