'GeoDataFrame is Inverted when I converted from Raster to Vector using RasterIO

I'm currently using this code to convert a raster file to a geodataframe:

import rasterio 
from rasterio.features import shapes
mask = None 

with rasterio.open(#INSERT TIF FILE HERE) as src:
    image = src.read(1) # first band, not sure yet how to do it with multiple bands
    results = (
    {'properties': {'raster_val': v}, 'geometry': s}
    for i, (s, v) 
    in enumerate(
        shapes(image, mask=mask))) geoms = list(results)

import geopandas as gpd
gpd_polygonized_raster = gpd.GeoDataFrame.from_features(geoms)

The problem is, the geodataframe is showing upside down instead of its expected oreintation.

Any help on this would be appreciated. Thank you!

Take note that the TIFF file has a projection already of EPSG:4326.



Solution 1:[1]

  • you can use shapely affine_transform()
  • have picked up a sample GEOTIFF* to make this working example
import rasterio
from rasterio.features import shapes
import geopandas as gpd
from shapely.affinity import affine_transform as T
from pathlib import Path
import plotly.express as px
import requests
from pathlib import Path

# https://www.sciencebase.gov/catalog/item/53f5a87ae4b09d12e0e8547b
url = "https://www.sciencebase.gov/catalog/file/get/53f5a87ae4b09d12e0e8547b?f=__disk__7f%2Fe7%2F94%2F7fe7943c77f2c6c4eb4c129153fd4e80f6079091"
f = Path.cwd().joinpath("FAA_UTM18N_NAD83.tif")
r = requests.get(url, stream=True, headers={"User-Agent": "XY"})
with open(f, "wb") as fd:
    for chunk in r.iter_content(chunk_size=128):
        fd.write(chunk)

results = []

with rasterio.open(f) as src:
    crs = src.crs
    for layer in range(1,20):
        try:
            image = src.read(layer)  # use all bands / layers
            results += [
                {"properties": {"raster_val": v, "layer":layer}, "geometry": s}
                for i, (s, v) in enumerate(shapes(image, mask=src.dataset_mask()))
            ]
        except IndexError as e:
            print(e)
            break


gdf = gpd.GeoDataFrame.from_features(results, crs=crs)

# flip top and bottom using affine transform
gdf["geometry"] = gdf["geometry"].apply(lambda g: T(g, [1, 0, 0, -1, 0, 0]))

# exclude areas where it's white in source TIFF
gdf.to_crs("EPSG:4326").loc[gdf["raster_val"].lt(255)].plot(column="raster_val")

enter image description here

Solution 2:[2]

you could vectorize the tif file using gdal_polygonize and then read the vector file with geopandas
import subprocess
import geopandas as gpd

# execute 'gdal_polygonize.py' in the shell
cmd = ['gdal_polygonize.py', tif_path, vector_path]
subprocess.call(cmd, shell=True)

# read the vector file (.shp, .geojson, etc..)
gpd_polygonized_raster =  gpd.read_file(vector_path)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rob Raymond
Solution 2 EOEAGLE