It is also possible to use rasterio and extract the shapes of all connected pixel outlines:
from shapely.geometry import shape
import geopandas as gpd
import rasterio
from rasterio import features
rasterfile= r"/home/bera/Desktop/gistest/four_polygons_rasterized.tif"
dataset = rasterio.open(rasterfile, mode="r")
arr = dataset.read()[0,:,:]
#If your input raster have many values, each unique value will become one polygon.
#Reclassify to either 1 or 0. You dont have to do this.
arr[(arr>0)]=1
arr[(arr<1)]=0
#Vectorize each raster blob
mask = arr>0 #Dont create polygons where the value is <=0
shapes = rasterio.features.shapes(source=arr, connectivity=4, mask=mask,
transform=dataset.transform)
#Iterate over the shapes, each row is a tuple of the geometry and the raster value:
#({'type': 'Polygon', 'coordinates': [[(618821.3726, 6480531.5759), ....), 1.0)
rastervalues = [] #A list for the values
geometries = [] #And geometries
for geom, rasterval in shapes:
geometries.append(shape(geom)) #Create a shapely polygon
rastervalues.append(rasterval)
df = gpd.GeoDataFrame(data=rastervalues, geometry=geometries,
crs=dataset.crs.to_epsg(), columns=["rasterval"])
#df.to_file(r"/home/bera/Desktop/gistest/raster_boundaries.gpkg")