Istogramma zonale
A cura di
Totò Fiandaca 
		
		| issue 
		#258
		
		
		
		| guida/e
		
		Andrea Borruso
		
		Totò Fiandaca
		
		
	
Questa ricetta risolve un problema specifico ma facilmente generalizzabile per chi lavora spesso con raster e vettori e ha bisogno di estrarre statistiche o istogrammi zonali.
Quesito
Dopo aver estratto da un DTM la pendenza:
- raster delle pendenze riclassificato con valori 1,2,3,4;
 - vettore poligonale che copre il raster;
 - QUESITO: che tool/procedura usare per calcolare una sorta di statistiche zonali? ovvero: al poligonale come aggiungere 4 attributi (pend_1, pend_2, pend_3 e pend_4) e popolarli con il conteggio dei relativi valori dei pixel che vi ricadono dentro (pend_1 = conteggio dei soli pixel con valore 1; pend_2 = conteggio dei soli pixel con valore 2 e cosi via);
 
sotto uno screenshot:
Python
Soluzione brillante con python, occorre installare alcune librerie come rasterio, geopandas e rasterstats e poi lanciare lo script da bash: python3 nomescript.py
i dati di input e output sono definiti dentro lo script.
import rasterio
import geopandas as gpd
from rasterstats import zonal_stats
import os
input_raster = 'testOneR.tif'
input_shapefile = 'zone.shp'
output_shapefile = 'output_shapefile.shp'
# Carica lo shapefile
gdf = gpd.read_file(input_shapefile)
# Loop per i valori dei pixel da 1 a 4
for value in range(1, 5):
    temp_raster_file = f'temp_raster_{value}.tif'
    
    # Crea un raster temporaneo per ogni valore
    with rasterio.open(input_raster) as src:
        data = src.read(1)
        data[data != value] = src.nodata
        profile = src.profile
        with rasterio.open(temp_raster_file, 'w', **profile) as dst:
            dst.write(data, 1)
    # Calcola le statistiche zonali
    stats = zonal_stats(input_shapefile, temp_raster_file, stats="count")
    gdf[f'pend_{value}'] = [stat['count'] if stat else None for stat in stats]
    # Rimuovi il file temporaneo
    os.remove(temp_raster_file)
# Salva il nuovo shapefile con le colonne aggiunte
gdf.to_file(output_shapefile)
QGIS
per chi usasse solo QGIS, la soluzione immediata è un algoritmo presente nel core di QGIS tra gli strumenti di Processing: Istogramma zonale
restituisce un altro shapefile con i 4 campi popolati:
rio e zonalstasts
dopo aver installato le librerie python viste sopra, è possibile lanciare (sotto per bash) il seguente codice avendo cura di usare come vettore il formato geojson
rio zonalstats --categorical zone.geojson prefix Andrea_ -r testOneR.tif >out.geojson
dati di esempio
RIFERIMENTI
- https://www.python.org/
 - https://geopandas.org/en/stable/
 - https://pythonhosted.org/rasterstats/cli.html?highlight=command#command-line-interface
 - https://www.qgis.org/it/site/
 - https://docs.qgis.org/3.28/en/docs/user_manual/processing_algs/qgis/rasteranalysis.html#qgiszonalhistogram