I'm trying to create a script to polygonalize a raster using rasterio. I want to only polygonalize pixel values that are not null.
From this SO answer, I derived this function:
def create_geometry(raster_input):
"""
Creates a shapely polygon from a raster image
:param raster_input: raster path
:return: shapely geometry
"""
mask = None
results = None
pixels = []
# with rasterio.drivers():
with rasterio.open(raster_input) as src:
image = src.read(1) # first band
results = (
{'properties': {'raster_val': v}, 'geometry': s}
for i, (s, v)
in enumerate(
shapes(image, mask=mask, transform=src.affine)))
return results
That function is called by this function, which then saves to shapefile using the polygonalize_geometry() function:
def shape_builder(raster_input, output_path):
"Builds a polygon out of the pixel polygons"
# polygons = []
polygons = create_geometry(raster_input)
for polygon in polygons:
polygon = shape(polygon[0]['geometry'])
print(polygon)
polygonalize_geometry(polygon, output_path)
I then convert it into shapely geometry, and then write a shapefile. However, the shapefile only contains one feature that encompasses one pixel (shown below). I believe that it is only operating on the first pixel it finds. The SO answer I linked above says that the function is a generator, but I haven't ever been able to figure out how to use them. I'm pretty sure that's the issue.
So the script is somewhat working.
Where did I go wrong?
Best Answer
Ross, I think the only thing that is wrong is that you're re-opening the shapefile in 'w' mode in
polygonalize_geometry()
for every shape. 'w' doesn't mean "append to shapefile", it means "overwrite shapefile". Try Python'sopen()
in 'w' mode, for example,fiona.open()
has exactly the same behavior. Change your program so that the output vector collection is opened only once and you'll be back on track.