Calcolatore raster QGIS: formule testate e 4 trappole silenziose
Pubblicato il
Apri il Raster Calculator di QGIS da Raster > Raster Calculator (Raster > Calcolatore raster) o dal Processing Toolbox. Per l'NDVI di Sentinel-2 usa ("B08@1" - "B04@1") / ("B08@1" + "B04@1"): il calcolatore del menu lavora in Float32 in automatico. Attenzione al calcolatore GDAL che fa traboccare gli interi senza segno, alle maschere con * che scrivono 0 invece di nodata e agli strumenti di pendenza che sbagliano sulle griglie in gradi.
Ho testato tutti questi casi il 7 novembre 2026 in QGIS 3.44.15 su una finestra di 5 km per 5 km di terreni agricoli collinari a sud di Machado, Minas Gerais, Brasile (2.500 ha, 250.000 pixel a 10 m in UTM 23S, EPSG:32723). Ho usato una scena Sentinel-2 L2A del 3 novembre 2026 e un DEM Copernicus GLO-30 a 30 m, e ho confrontato ogni risultato con un riferimento numpy in virgola mobile a 64 bit fuori da QGIS.
Cos'è il Raster Calculator di QGIS, e quale stai aprendo?
Un calcolatore raster valuta un'espressione matematica o booleana pixel per pixel su una o più bande raster e scrive una nuova griglia. In QGIS indichi una banda come "layername@band" (per esempio "B08@1" per la banda 1 del layer B08), combini le bande con +, -, *, /, <, >, AND, OR o if(condition, true, false) e scrivi il risultato in un GeoTIFF o in un layer virtuale in memoria.
Il punto che confonde è che QGIS include cinque strumenti chiamati "Raster calculator", e non usano tutti lo stesso motore. Quattro usano il parser di espressioni nativo di QGIS e calcolano in virgola mobile. Quello GDAL (gdal_calc.py dietro le quinte) usa variabili con lettere A/B/C e valuta espressioni numpy nel tipo di dato della banda in ingresso.
| Strumento in QGIS 3.44 | Sintassi delle bande | Tipo in uscita | Pixel sbagliati di oltre 0,01 su NDVI uint16 (su 250.000) |
|---|---|---|---|
Raster > Raster Calculator (QgsRasterCalculator) | "B08@1" | Float32 | 0 |
Processing: Raster calculator (native:rastercalc) | "B08@1" | Float32 | 0 |
Processing: Raster calculator (virtual) (native:virtualrastercalc) | "B08@1" | Float64 (in memoria) | 0 |
Processing: Raster calculator (legacy) (qgis:rastercalculator) | "B08@1" | Float32 | 0 |
Processing: GDAL Raster calculator (gdal:rastercalculator) | A, B | File Float32, calcolo nel tipo in ingresso | 703 (0,28%, valori fino a 126,7) |
Se vuoi solo una formula che funzioni senza convertire i tipi, usa Raster > Raster Calculator dal menu in alto, oppure il primo Raster calculator nel gruppo nativo di QGIS in Processing.
Passo per passo: calcolare l'NDVI nel Raster Calculator di QGIS
Se prima ti servono le bande Sentinel-2, la nostra guida su come scaricare immagini Sentinel-2 in QGIS spiega il percorso dal catalogo STAC. Una volta che le bande B04 (rosso, 10 m) e B08 (infrarosso vicino, 10 m) sono nel pannello Layers, calcolare ciò che misura l'NDVI richiede quattro passaggi.
Seleziona il layer che definisce la griglia di uscita
Clicca B08 nel pannello Layers prima di aprire la finestra. Quando Raster > Raster Calculator si apre, legge estensione, sistema di coordinate (CRS), larghezza e altezza dal layer raster selezionato in quel momento nel pannello Layers. Controlla che l'intestazione indichi Extent (current: B08).
Inserisci l'espressione NDVI
In Raster > Raster Calculator, fai doppio clic su B08@1 e B04@1 nell'elenco Raster Bands (o scrivili tra virgolette doppie) per ottenere:
("B08@1" - "B04@1") / ("B08@1" + "B04@1")
Controlla che la nota subito sotto il campo dell'espressione indichi Expression valid. In questa finestra non serve convertire in float le bande Sentinel-2 a 16 bit senza segno.
Scegli un file di uscita o un layer virtuale
Imposta Output layer su un percorso .tif e lascia Output format su GeoTIFF. Se vuoi solo un'anteprima veloce senza un file su disco, spunta Create on-the-fly raster instead of writing layer to disk (salva nel file di progetto un URI con la formula e i percorsi assoluti degli input, e corrisponde al file scritto entro 3e-8).
Esegui il calcolo e applica uno stile al risultato
Clicca OK. Sulla nostra finestra di 500 per 500 pixel il calcolo è terminato in 0,12 secondi, con valori da -0.5507 a 0.9547 e una differenza massima di 2.98e-8 rispetto a numpy a 64 bit. Apri Layer Properties > Symbology, passa a Singleband pseudocolor, scegli la rampa RdYlGn e imposta il minimo a 0 e il massimo a 0.9.
Ecco la finestra subito prima di cliccare OK, con l'estensione presa da B08:

Con lo stile RdYlGn, la vegetazione fitta intorno a Machado appare in verde scuro, il suolo nudo e le strade in rosso, e i 703 pixel in cui il rosso supera l'infrarosso vicino (acqua e zone scure) diventano negativi. L'NDVI medio sull'intera finestra è 0.727. Se la tua chioma è abbastanza fitta da saturare l'NDVI o lascia suolo nudo scoperto tra i filari, guarda come cambia la formula nel nostro confronto tra NDVI, EVI, SAVI e NDRE.

Ricettario di formule per il Raster Calculator di QGIS
Ogni espressione qui sotto è stata eseguita in QGIS 3.44.15 (QgsRasterCalculator) sul dataset di Machado e verificata pixel per pixel con numpy. Copia la sintassi con le virgolette doppie intorno a "layer@band".
| Operazione | Espressione testata (Raster > Raster Calculator) | Cosa ha prodotto sulla finestra di test di Machado |
|---|---|---|
| NDVI (Sentinel-2 10 m) | ("B08@1" - "B04@1") / ("B08@1" + "B04@1") | Float32 da -0.5507 a 0.9547 su 250.000 pixel; errore massimo 2.98e-8. |
| NDWI (indice dell'acqua di McFeeters) | ("B03@1" - "B08@1") / ("B03@1" + "B08@1") | Float32; "ndwi@1" > 0 ha isolato 637 pixel d'acqua (6,4 ha di stagni e torrenti). |
| Maschera sotto soglia a nodata | "ndvi@1" / ("ndvi@1" > 0.3) | Divide per 0 dove la condizione è falsa, scrivendo un vero nodata (11,343 pixel esclusi; media 0.753). |
Sostituzione condizionale (if) | if("ndvi@1" > 0.3, "ndvi@1", 0) | Viene accettata e mantiene i valori sopra 0.3, ma scrive 0 altrove, come la maschera con *. |
| Riclassificare il DEM in 5 classi (somma booleana) | ("dem@1" < 800) * 1 + ("dem@1" >= 800 AND "dem@1" < 850) * 2 + ("dem@1" >= 850 AND "dem@1" < 900) * 3 + ("dem@1" >= 900 AND "dem@1" < 1000) * 4 + ("dem@1" >= 1000) * 5 | Codici da 1 a 5 su 54.901 pixel del DEM; identico su ogni pixel a native:reclassifybytable. |
Riclassificare il DEM in 5 classi (if annidati) | if("dem@1" < 800, 1, if("dem@1" < 850, 2, if("dem@1" < 900, 3, if("dem@1" < 1000, 4, 5)))) | Stesse 5 classi (96,9 ha, 1.089,4 ha, 1.323,1 ha, 1.759,7 ha, 582,7 ha). |
| Soglia di pendenza | "slope@1" > 15 | Scrive 1 sopra i 15 gradi e 0 fino a 15 compresi (17,327 su 52,979 pixel validi del DEM UTM, 32,61%). |
| Quota da metri a piedi | "dem@1" * 3.28084 | Errore massimo di 0.98 ft (0.026% a 1.168 m) se usi il 3.28 del manuale di QGIS invece di 3.28084. |
Quattro trappole silenziose che danno numeri sbagliati (e come riconoscerle)
Nessuno dei quattro errori qui sotto genera un avviso in QGIS. Ognuno arriva in fondo, aggiunge un layer al progetto e ti consegna numeri plausibili finché non li controlli.
1. Il GDAL Raster Calculator fa traboccare gli interi senza segno sull'NDVI negativo
Il Raster Calculator nativo di QGIS non incontra mai un problema di divisione intera sulle bande Sentinel-2, ma il GDAL Raster calculator di Processing (gdal:rastercalculator) valuta (A-B)/(A+B) nel tipo di dato numpy del file in ingresso e corrompe ogni pixel in cui il rosso è più alto del NIR.
Le bande Sentinel-2 Level-2A arrivano come interi a 16 bit senza segno (uint16). Nella nostra finestra di 250.000 pixel, 703 pixel (0,28%, acqua e zone scure) hanno B04 maggiore di B08. Quando gdal:rastercalculator sottrae B04 da B08 in uint16, il risultato negativo riparte da 65.536, e lo strumento scrive quei 703 pixel in un file Float32 con valori tra 0 e 126.7 invece di un NDVI negativo.

Se usi il calcolatore GDAL, converti il tipo nell'espressione con (A.astype(numpy.float32)-B)/(A+B) (nel nostro test ha portato a 0 i pixel errati), oppure usa il Raster Calculator nativo di QGIS. E non impostare mai il tipo di uscita GDAL su Int16 o Byte per un indice: forzare Int16 ha arrotondato 249.973 dei nostri 250.000 pixel (99,99%) a soli -1, 0 o 1.
2. Moltiplicare per una condizione (*) scrive 0, non nodata, e abbassa la media
Moltiplicare un raster per una condizione booleana come ("ndvi@1" > 0.3) * "ndvi@1" porta ogni pixel escluso a 0 invece di nodata, e questo ha abbassato l'NDVI medio dell'area mantenuta da 0.753 a 0.719.
Il manuale ufficiale di QGIS insegna ("elevation@1" >= 0) * "elevation@1" come metodo standard per mascherare un raster. Sul nostro layer NDVI di Machado, 11,343 pixel sono a 0.3 o meno. Quando moltiplichi per ("ndvi@1" > 0.3), tutti gli 11,343 pixel vengono scritti come il numero valido 0.0, quindi le statistiche del layer contano ancora tutti i 250.000 pixel e includono 11,343 zeri in ogni media, istogramma e statistica zonale che calcoli dopo.
| Espressione di maschera | Cosa diventano i pixel esclusi | Pixel contati nelle statistiche del layer | NDVI medio dell'area mantenuta |
|---|---|---|---|
("ndvi@1" > 0.3) * "ndvi@1" | 0.0 (contato come dato) | 250.000 | 0.719 (errore di -0.034) |
"ndvi@1" / ("ndvi@1" > 0.3) | nodata (-3.40282e+38) | 238.657 | 0.753 (esatto) |
Per scrivere un vero nodata in un solo passaggio, dividi per la condizione invece di moltiplicare: "ndvi@1" / ("ndvi@1" > 0.3). Dove la condizione è vera (1) il valore resta invariato; dove è falsa (0) la divisione per zero produce nodata.
3. Calcolare la pendenza su un DEM in gradi prima del calcolatore segna il 100% della mappa come ripido
Lanciare lo strumento Slope di QGIS con le impostazioni predefinite su un DEM geografico (come Copernicus GLO-30 in EPSG:4326) prima della soglia "slope@1" > 15 ha segnato il 100% dei nostri terreni collinari come più ripido di 15 gradi, con una pendenza media di 89.99 gradi, mentre il valore reale dopo la riproiezione in UTM è 32.61%.
Copernicus GLO-30 e gli altri DEM globali gratuiti (vedi la nostra guida ai download gratuiti di DEM in QGIS) arrivano in gradi geografici (EPSG:4326) con quote in metri. Con lo Z factor predefinito, lo strumento Slope legge un dislivello in metri su un passo orizzontale di 0.000278 (la larghezza di un pixel in gradi), quindi ogni versante sembra una parete verticale.
Come è stata calcolata la pendenza prima di "slope@1" > 15 | Pixel > 15 gradi | Pendenza media |
|---|---|---|
Slope nativo su DEM EPSG:4326, Z factor predefinito 1 | 100.00% | 89.99° |
Slope GDAL su DEM EPSG:4326, scala 1 | 100.00% | 89.99° |
Slope GDAL su DEM EPSG:4326, scala 111120 | 31.61% | 12.54° |
| Slope nativo dopo la riproiezione del DEM in UTM 23S a 30 m (riferimento) | 32.61% | 12.68° |
| Slope GDAL dopo la riproiezione del DEM in UTM 23S a 30 m | 32.71% | 12.71° |
Anche la scorciatoia della scala a 111120 metri per grado resta un punto percentuale sotto (31.61% contro 32.61%), perché a 22°S un grado di longitudine è circa il 7% più corto di un grado di latitudine (cos 22° = 0.93). Riproietta sempre il DEM nella sua zona UTM locale (Raster > Projections > Warp (Reproject), ricampionamento bilineare e un valore nodata di -9999 perché il bordo non si riempia di finte pendenze a 87°) prima di lanciare Slope e il Raster Calculator.
4. Sottrarre l'offset +1000 di Sentinel-2 senza controllare la scena rovina il 90,6% dei pixel
Sottrarre 1000 dalle nostre bande Sentinel-2 L2A prima di calcolare l'NDVI ha spinto 226,413 pixel su 250,000 (90,6%) fuori dall'intervallo valido [-1, 1], con valori da -1273 a 1217 e una media di 1.39 invece di 0.727.
La processing baseline 04.00 di ESA per Sentinel-2 e le successive hanno aggiunto un offset di +1000 sui digital number perché i pixel scuri non vengano tagliati a zero, e i metadati STAC indicano scale: 0.0001 e offset: -0.1. Ma quando scarichi Cloud-Optimized GeoTIFF dalla STAC API di Earth Search (come abbiamo fatto per la scena S2A_23KLR_20261103_0_L2A, baseline 05.13), il fornitore ha già spostato i valori e imposta earthsearch:boa_offset_applied: true nei metadati dell'elemento.
Nel nostro file B04, 226,773 pixel su 250,000 (90,7%) avevano digital number grezzi sotto 1000 (minimo 59, mediana 491). Controlla il valore minimo di B04 in Layer Properties > Information prima di toccare la formula: se i pixel scuri stanno intorno a 50-300, l'offset è già stato rimosso e la formula grezza (B08 - B04) / (B08 + B04) è esatta (la divisione per il fattore di scala 10,000 si annulla nel rapporto). Sottrai 1000 solo se i tuoi pixel più scuri a cielo sereno stanno sopra 1000.
Bonus: cosa significano davvero "Expression valid" e la barra rossa di errore generica
Altri due comportamenti di Raster > Raster Calculator fanno perdere molto tempo nel debug:
- Risoluzioni diverse su una griglia grossolana non vengono mediate. Quando combini una banda a 10 m (
B08) e una a 20 m (B11), il calcolatore nativo ricampiona al volo con il vicino più prossimo (il calcolatore GDAL si ferma subito conError! Dimensions of file ... (250, 250) are different from other files (500, 500). Cannot proceed). Su una griglia di uscita a 10 m, ripetere ogni pixel da 20 m in un blocco 2 per 2 funziona bene. Su una griglia di uscita a 20 m, il calcolatore non fa la media dei quattro pixel da 10 m: in62,250celle su62,500ha semplicemente preso il pixel da 10 m in alto a destra di ogni blocco 2 per 2, con uno scarto fino a0.71rispetto alla media dei 4 pixel in(B08 - B11) / (B08 + B11). - "Expression valid" controlla solo la sintassi, non i nomi delle bande. Se lasci un operatore finale come
"B08@1" /, la finestra se ne accorge (Expression invalid, OK disattivato).

Ma se scrivi un layer o una banda che non è nel progetto (come "B04@2" o "B02@1" quando B02 non è caricato), l'etichetta indica comunque Expression valid. Quando clicchi OK, QGIS scrive un GeoTIFF di 500 per 500 pieno al 100% di nodata, non aggiunge nulla alla mappa e mostra un solo banner rosso: Raster calculator: An error occurred while performing the calculation. Ogni volta che vedi quel banner, confronta ogni nome "layer@band" con l'elenco Raster Bands.

Saltare la finestra: fare calcoli raster chiedendo a un agente AI in QGIS
Sviluppiamo AI Agent, quindi questa sezione parla del nostro plugin. Aggiunge in QGIS un pannello di chat che può cercare nei cataloghi STAC, riproiettare DEM, fare calcoli raster in Python o con Processing e applicare uno stile al risultato sulla mappa.
Per vedere se evita le trappole qui sopra sugli stessi dati di Machado, ho disegnato il poligono di un'azienda agricola di 120,07 ha (E 405300-406300, N 7594400-7595600 in UTM 23S) su un progetto OpenStreetMap vuoto e ho inviato tre prompt di un solo messaggio con effort Medium e permessi Balanced, una chat nuova per ogni compito.
Test 1: NDVI in 5 classi con gli ettari per classe
Ho scritto:
Compute NDVI for this field from the latest cloud-free Sentinel-2 and class it in 5 classes with hectares per class
L'agente ha consultato il catalogo STAC, ha notato che esisteva una scena del 6 novembre 2026 ma molto nuvolosa, e ha scelto la stessa scena del 3 novembre 2026 (1.65% di copertura nuvolosa sul tile) che avevo usato per il test manuale. Ha scaricato B08 e B04 a 10 m, ha calcolato l'NDVI, lo ha suddiviso in cinque intervalli, ha applicato uno stile al layer e ha riportato la superficie per classe sulla griglia metrica a 10 m.
| Classe NDVI | Risultato di AI Agent | Mia verifica indipendente con numpy (stessi 12.000 pixel) | Differenza |
|---|---|---|---|
-1 to < 0 | 0.76 ha | 0.76 ha | 0.0% |
0 to < 0.2 | 23.85 ha | 23.84 ha | < 0.1% |
0.2 to < 0.4 | 9.27 ha | 9.27 ha | 0.0% |
0.4 to < 0.6 | 8.70 ha | 8.69 ha | 0.1% |
0.6 to 1 | 77.42 ha | 77.44 ha | < 0.1% |
| Superficie valida totale | 120.00 ha | 120.00 ha (su un poligono di 120.07 ha) | 0.0% |
Pixel per pixel sul raster NDVI che ha esportato, la differenza assoluta media rispetto al mio riferimento è stata 5e-5, e il suo raster delle classi differiva dal mio su 4 pixel su 12.000.

Test 2: pendenza sopra i 15 gradi (senza DEM nel progetto)
In una nuova chat, con solo il poligono dell'azienda caricato, ho scritto:
Show where slope is above 15 degrees on the farm layer
L'agente ha scaricato il DEM Copernicus a 30 m, lo ha riproiettato su una griglia metrica invece di calcolare la pendenza in gradi, e ha creato un layer a due classi (15 degrees or less in giallo chiaro, above 15 degrees in rosso). Ha riportato 331 pixel su 1,320 dell'azienda sopra i 15 gradi (25.08%, massimo 29.15°). Il mio riferimento con Slope nativo su DEM riproiettato in UTM, sullo stesso rettangolo, ha dato 341 pixel su 1,360 (25.07%, massimo 29.29°), una differenza di 0.01 punti percentuali.

Test 3: dove devi ancora controllare l'agente
In una terza chat ho chiesto:
Mask out everything with NDVI below 0.3 on the farm layer and tell me the mean NDVI of what is left
Nota che in questo prompt non ho scritto "cloud-free" né "latest". L'agente ha evitato la trappola della maschera a 0: ha scritto nodata -9999 per ogni pixel mascherato e ha restituito un NDVI medio di 0.552 su 2,277 pixel mantenuti. La media del suo file di uscita era 0.5515; la mia, sulla stessa scena e con la stessa regola, 0.5513.
Però ha preso la scena Sentinel-2 del 27 ottobre 2026, e in quella data l'80.5% dell'azienda (9,656 pixel su 12,000 nella banda Scene Classification) era coperto da nuvole, ombre o cirri. Ha indicato la data nella risposta, ma non ha mai detto che 0.552 descriveva solo il quinto sereno del campo. Sulla scena serena del 3 novembre, la stessa regola dà una media di 0.766 su 8.785 pixel.
La mia regola pratica: che tu usi il Raster Calculator a mano o chieda a un agente dell'ecosistema QGIS AI, controlla sempre la data della scena e carica la banda a colori reali o la banda nuvole SCL prima di fidarti di un numero di sintesi.
Come abbiamo misurato. Tutti i test si sono svolti il 7 novembre 2026 in QGIS 3.44.15-Solothurn su macOS (GDAL 3.13.3, numpy 2.5.2) su una finestra di 5 km per 5 km a sud di Machado, Minas Gerais, Brasile (EPSG:32723, E 402000-407000, N 7591000-7596000), con la scena Sentinel-2 L2A S2A_23KLR_20261103_0_L2A (e la scena del 27 ottobre 2026 per il test 3) da Earth Search e il tile Copernicus GLO-30 S22_00_W046_00. I criteri di successo per i test manuali e per i test 1 e 2 dell'agente sono stati scritti prima di qualsiasi calcolo raster; i criteri per il test 3 sono stati scritti dopo aver visto i test 1 e 2. Le griglie di riferimento sono state calcolate con numpy in float a 64 bit fuori da QGIS. AI Agent 1.9.4 ha lavorato con effort Medium e permessi Balanced, un messaggio per chat. Una scena e un sito sono un benchmark su un singolo caso, non un'indagine statistica su più baseline.
Domande frequenti
Perché il mio NDVI in QGIS è tutto 0, -1 o 1?
Hai forzato un tipo di uscita intero (Int16 o Byte) nel calcolatore raster GDAL, che arrotonda ogni decimale tra -1 e 1 a -1, 0 o 1 (il 99,99% dei pixel nel nostro test). Lascia il tipo di uscita su Float32, oppure usa Raster > Raster Calculator dal menu in alto, che produce Float32 in automatico.
Perché il Raster Calculator di QGIS fallisce con 'An error occurred while performing the calculation' e restituisce nodata?
Un nome "layer@band" nella formula non corrisponde a un layer caricato o a un numero di banda (per esempio scrivere "B04@2" su un file a banda singola, o indicare un layer che hai rimosso). Il messaggio Expression valid sotto il campo della formula controlla solo la sintassi, non se le bande esistono. Reinserisci ogni banda con un doppio clic nell'elenco Raster Bands.
Qual è la differenza tra Raster > Raster Calculator e il GDAL Raster Calculator in Processing?
Raster > Raster Calculator (e il Raster calculator nativo di Processing) usa il parser di QGIS con nomi "layer@band" e calcola sempre in virgola mobile. Il GDAL Raster calculator (gdal_calc.py) usa variabili con lettere (A, B) e valuta il calcolo numpy nel tipo di dato della banda in ingresso, quindi sottraendo bande intere a 16 bit senza segno i numeri negativi ripartono da 65,536 se non converti con A.astype(numpy.float32).
Come scrivo una condizione IF o imposto valori a nodata nel Raster Calculator di QGIS?
Puoi scrivere if("ndvi@1" > 0.3, "ndvi@1", 0) per sostituire con 0 i valori sotto 0.3. Se vuoi che i pixel esclusi diventino un vero nodata e non abbassino la media del layer, dividi invece per la condizione: "ndvi@1" / ("ndvi@1" > 0.3). Dove la condizione è falsa (0), la divisione per zero scrive nodata.
Continua a leggereCos'è l'NDVI? Significato, valori e formula
Fallo in QGIS semplicemente chiedendolo
AI Agent esegue l'attività che descrivi, direttamente nel tuo progetto QGIS. Gratis, senza carta.
da Raster > Raster Calculator (Raster > Calcolatore raster) o dal Processing Toolbox. Per l'NDVI di Sentinel-2 usa 

