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

Python 从numpy布尔网格获取多边形的外部坐标,python,numpy,shapely,Python,Numpy,Shapely,我试图从一个numpy布尔网格中获取多边形的外部坐标。例如,从一个(16,16)数组,比如下面的一个 [ [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

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

[
    [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
,它将如下所示:

# 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()

我想得到以下坐标,以便我们可以绘制这样的多边形的外环,例如,
[(51),(60),(70),(80),(90),(101),(112),(113),(102),(91),(81),(71),(61)]
。到目前为止,我掌握的情况如下:

# 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.external.xy
的结果将创建外环。我的方法将创建错误的多边形轮廓,例如:


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

也许你可以将问题转移到。在这方面你可能会得到更多的帮助

总之,快速搜索显示,建议使用
rasterio
library,我知道这正是您需要的

根据您的情况,它可以是:

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
多边形

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

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

此答案仅链接,因此可能会被删除。请参阅。请解决这个问题。好的,我会完成它。它工作得非常好,谢谢。我也尝试过在
坐标
周围使用alpha形状(凹面外壳),但与您提出的解决方案相比,它在更大的图像上太慢了。很高兴听到它起作用了。在这类复杂问题中,在web上进行全面搜索总是值得的。请记住,stack exchange还有几个其他站点更适合于其他需求,尽管在SO中您总是可以得到更快的答案。凹面外壳可以复制边界。凸面外壳在这种特殊情况下不会出现,因为它不是凸面多边形。