jacob
jacob

Reputation: 899

python: boolean array to polygon

I have a boolean array with one connected component of True values, the border of which I would like to convert to a polygon, e.g. in shapely.

Assuming my array is img, I can get the border indices like this

import numpy as np
from skimage.morphology binary_erosion

border_indices = np.transpose(np.nonzero(np.logical_xor(binary_erosion(img), img)))

but just feeding those into a shapely.Polygon object does not work because the points are not ordered along the boundary, but in increasing x and y values.

It may be possible to use alpha shapes to solve this (note that I'm not looking for the convex hull), but maybe someone can suggest a simpler way of getting to the bounding polygon, ideally directly operating on the original array.

Upvotes: 2

Views: 2790

Answers (1)

jdmcbr
jdmcbr

Reputation: 6426

It sounds like rasterio.features.shapes is what you are looking for. A simple example that should illustrate the procedure:

import rasterio.features
import shapely.geometry
import numpy as np

im = np.zeros([5, 5], dtype=np.uint8)
im[1:-1, 1:-1] = 1

shapes = rasterio.features.shapes(im)

shapes is a generator with pairs of (geometry, value). To get the geometry corresponding to where the value is equal to 1:

polygons = [shapely.geometry.Polygon(shape[0]["coordinates"][0]) for shape in shapes if shape[1] == 1]

This creates a list of shapely polygons corresponding to the areas in the array where the value is equal to 1.

print(polygons)
[<shapely.geometry.polygon.Polygon object at 0x7f64bf9ac9e8>]

Upvotes: 10

Related Questions