Problem
Today I needed to convert raster to a shapefile with rectangular polygons representing each pixel of the raster in Python, including the pixels with value 0.
Related questions:
- Converting raster pixels to vector cells? does not consider Python solution.
- Convert raster to vector based on each pixel offers a solution in SAGA and OpenJUMP
- How to polygonize raster to shapely polygon does not polygonize zero pixels and if I understand it correctly, it groups the shapes by values - I explicitly want to have each recangular cell/pixel as a separate feature.
Solution attempt
I could not find an existing solution and so I wrote my own hacky solution using rasterio
, shapely
, and geopandas
.
I am assuming that I know the raster file is in epsg:4326.
First import the libraries
import itertools
import rasterio
from shapely.geometry import box
import geopandas as gpd
Create rectangles using shapely
with rasterio.open(sample_raster) as dataset:
data = dataset.read(1)
t = dataset.transform
move_x = t[0]
# t[4] is negative, as raster start upper left 0,0 and goes down
# later for steps calculation (ymin=...) we use plus instead of minus
move_y = t[4]
height = dataset.height
width = dataset.width
polygons = []
indices = list(itertools.product(range(width), range(height)))
for x,y in indices:
x_min, y_max = t * (x,y)
x_max = x_min + move_x
y_min = y_max + move_y
polygons.append(box(x_min, y_min, x_max, y_max))
Extract the data
data_list = []
for x,y in indices:
data_list.append(data[y,x])
Combine in a GeoDataFrame
using geopandas
gdf = gpd.GeoDataFrame(data=data_list, crs={'init':'epsg:4236'}, geometry=polygons, columns=['value'])
Question
This is a quick solution and I suspect not ideal. I have two questions
1) Is this solution correct? Are there some obvious or necessary improvements?
2) Is there a quicker / standard way to do this? Perhaps I have missed some library, or a function.