Calculadora ráster de QGIS: fórmulas probadas y 4 trampas silenciosas
Publicado el
Abre la calculadora ráster de QGIS desde Raster > Raster Calculator (Ráster > Calculadora ráster) o desde la caja de herramientas de Processing. Para el NDVI de Sentinel-2, usa ("B08@1" - "B04@1") / ("B08@1" + "B04@1"): la calculadora del menú calcula en Float32 de forma automática. Cuidado con la calculadora de GDAL, que desborda los enteros sin signo, con las máscaras *, que escriben 0 en lugar de nodata, y con las herramientas de pendiente, que fallan sobre rejillas en grados.
Probé todo eso el 7 de noviembre de 2026 en QGIS 3.44.15 sobre una ventana de 5 km por 5 km de tierras de cultivo onduladas al sur de Machado, Minas Gerais, Brasil (2,500 ha, 250,000 píxeles de 10 m en UTM 23S, EPSG:32723). Usé una escena Sentinel-2 L2A del 3 de noviembre de 2026 y un DEM Copernicus GLO-30 de 30 m, y comparé cada resultado con una referencia numpy en coma flotante de 64 bits fuera de QGIS.
¿Qué es la calculadora ráster de QGIS y cuál de ellas estás abriendo?
Una calculadora ráster evalúa una expresión matemática o booleana píxel a píxel sobre una o varias bandas ráster y escribe una nueva rejilla. En QGIS, una banda se escribe como "layername@band" (por ejemplo "B08@1" para la banda 1 de la capa B08), las bandas se combinan con +, -, *, /, <, >, AND, OR o if(condition, true, false), y el resultado se guarda en un GeoTIFF o en una capa virtual en memoria.
Lo que confunde a la gente es que QGIS trae cinco herramientas llamadas "Raster calculator", y no todas usan el mismo motor. Cuatro usan el analizador de expresiones nativo de QGIS y calculan en coma flotante. La de GDAL (gdal_calc.py por debajo) usa variables con letras A/B/C y evalúa expresiones numpy en el propio tipo de dato de la banda de entrada.
| Herramienta en QGIS 3.44 | Sintaxis de banda | Tipo de salida | Píxeles con error > 0.01 en NDVI uint16 (de 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 (en memoria) | 0 |
Processing: Raster calculator (legacy) (qgis:rastercalculator) | "B08@1" | Float32 | 0 |
Processing: GDAL Raster calculator (gdal:rastercalculator) | A, B | Archivo Float32, cálculo en el tipo de entrada | 703 (0.28%, valores de hasta 126.7) |
Si solo quieres una fórmula que funcione sin convertir tipos, usa Raster > Raster Calculator en el menú superior, o la primera Raster calculator del grupo nativo de QGIS en Processing.
Paso a paso: calcular el NDVI en la calculadora ráster de QGIS
Si primero necesitas las bandas de Sentinel-2, nuestra guía sobre cómo descargar imágenes Sentinel-2 en QGIS explica el camino por el catálogo STAC. Cuando las bandas B04 (rojo, 10 m) y B08 (infrarrojo cercano, 10 m) estén en tu panel de capas, calcular lo que mide el NDVI lleva cuatro pasos.
Selecciona la capa que define la rejilla de salida
Haz clic en B08 en el panel de capas antes de abrir el diálogo. Al abrirse, Raster > Raster Calculator toma la extensión de salida, el sistema de coordenadas (SRC), el ancho y el alto de la capa ráster que esté seleccionada en el panel de capas. Comprueba que el encabezado diga Extent (current: B08).
Escribe la expresión del NDVI
En Raster > Raster Calculator, haz doble clic en B08@1 y B04@1 en la lista Raster Bands (o escríbelas entre comillas dobles) para construir:
("B08@1" - "B04@1") / ("B08@1" + "B04@1")
Comprueba que la nota justo debajo del cuadro de expresión diga Expression valid. En este diálogo no hace falta convertir a float las bandas Sentinel-2 de 16 bits sin signo.
Elige un archivo de salida o una capa virtual
Pon en Output layer una ruta .tif y deja Output format en GeoTIFF. Si solo quieres una vista previa rápida sin archivo en disco, marca Create on-the-fly raster instead of writing layer to disk (guarda en el proyecto un URI con la fórmula y rutas absolutas a las entradas, y coincide con el archivo escrito hasta 3e-8).
Ejecuta y da estilo al resultado
Haz clic en OK. En nuestra ventana de 500 por 500 píxeles, el cálculo tardó 0.12 segundos, con valores de -0.5507 a 0.9547 y una diferencia máxima de 2.98e-8 frente a numpy en 64 bits. Abre Layer Properties > Symbology, cambia a Singleband pseudocolor, elige la rampa RdYlGn y pon el mínimo en 0 y el máximo en 0.9.
Este es el diálogo justo antes de hacer clic en OK, con la extensión tomada de B08:

Con el estilo RdYlGn, la vegetación densa alrededor de Machado aparece en verde oscuro, el suelo desnudo y los caminos en rojo, y los 703 píxeles donde el rojo supera al infrarrojo cercano (agua y zonas oscuras) quedan en negativo. El NDVI medio de toda la ventana es 0.727. Si tu dosel es tan denso que satura el NDVI o deja suelo desnudo entre hileras, mira cómo cambia la fórmula en nuestra comparación de NDVI vs EVI, SAVI y NDRE.

Recetario de fórmulas para la calculadora ráster de QGIS
Cada expresión de abajo se ejecutó en QGIS 3.44.15 (QgsRasterCalculator) sobre los datos de Machado y se comprobó píxel a píxel frente a numpy. Copia la sintaxis con comillas dobles alrededor de "layer@band".
| Tarea | Expresión probada (Raster > Raster Calculator) | Lo que dio en la ventana de prueba de Machado |
|---|---|---|
| NDVI (Sentinel-2 10 m) | ("B08@1" - "B04@1") / ("B08@1" + "B04@1") | Float32 de -0.5507 a 0.9547 en 250,000 píxeles; error máximo 2.98e-8. |
| NDWI (índice de agua de McFeeters) | ("B03@1" - "B08@1") / ("B03@1" + "B08@1") | Float32; "ndwi@1" > 0 aisló 637 píxeles de agua (6.4 ha de estanques y arroyos). |
| Pasar a nodata lo que queda bajo un umbral | "ndvi@1" / ("ndvi@1" > 0.3) | Divide por 0 donde es falso y escribe nodata real (11,343 píxeles excluidos; media 0.753). |
Reemplazo condicional (if) | if("ndvi@1" > 0.3, "ndvi@1", 0) | Se analiza bien y conserva los valores por encima de 0.3, pero escribe 0 en el resto, como la máscara *. |
| Reclasificar un DEM en 5 clases (suma 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 | Códigos 1 a 5 en 54,901 píxeles del DEM; idéntico en cada píxel a native:reclassifybytable. |
Reclasificar un DEM en 5 clases (if anidados) | if("dem@1" < 800, 1, if("dem@1" < 850, 2, if("dem@1" < 900, 3, if("dem@1" < 1000, 4, 5)))) | Las mismas 5 clases (96.9 ha, 1,089.4 ha, 1,323.1 ha, 1,759.7 ha, 582.7 ha). |
| Umbral de pendiente | "slope@1" > 15 | Escribe 1 por encima de 15 grados y 0 en 15 o menos (17,327 de 52,979 píxeles válidos del DEM en UTM, 32.61%). |
| Elevación de metros a pies | "dem@1" * 3.28084 | Error máximo de 0.98 ft (0.026% a 1,168 m) si usas el 3.28 del manual de QGIS en lugar de 3.28084. |
Cuatro trampas silenciosas que dan números erróneos (y cómo detectarlas)
Ninguno de los cuatro fallos de abajo muestra un aviso en QGIS. Todos terminan, añaden una capa al proyecto y te dan números que parecen razonables hasta que los compruebas.
1. La calculadora ráster de GDAL desborda los enteros sin signo con NDVI negativo
La calculadora ráster nativa de QGIS nunca cae en un error de división entera con bandas Sentinel-2, pero la GDAL Raster calculator de Processing (gdal:rastercalculator) evalúa (A-B)/(A+B) en el propio tipo de dato numpy del archivo de entrada y corrompe todos los píxeles donde el rojo es mayor que el NIR.
Las bandas Sentinel-2 de nivel 2A vienen como enteros de 16 bits sin signo (uint16). En nuestra ventana de 250,000 píxeles, 703 píxeles (0.28%, agua y zonas oscuras) tienen B04 mayor que B08. Cuando gdal:rastercalculator resta B04 de B08 en uint16, el resultado negativo da la vuelta a 65,536, y la herramienta escribe esos 703 píxeles en un archivo Float32 con valores entre 0 y 126.7 en lugar de un NDVI negativo.

Si usas la calculadora de GDAL, convierte el tipo en la expresión con (A.astype(numpy.float32)-B)/(A+B) (en nuestra prueba bajó los píxeles erróneos a 0), o usa en su lugar la calculadora ráster nativa de QGIS. Y nunca pongas el tipo de salida de GDAL en Int16 o Byte para un índice: forzar Int16 redondeó 249,973 de nuestros 250,000 píxeles (99.99%) a solo -1, 0 o 1.
2. Multiplicar por una condición (*) escribe 0, no nodata, y baja tu media
Multiplicar un ráster por una condición booleana como ("ndvi@1" > 0.3) * "ndvi@1" pone cada píxel excluido en 0 en lugar de nodata, lo que bajó el NDVI medio de la zona conservada de 0.753 a 0.719.
El manual oficial de QGIS enseña ("elevation@1" >= 0) * "elevation@1" como la forma estándar de enmascarar un ráster. En nuestra capa de NDVI de Machado, 11,343 píxeles están en 0.3 o por debajo. Al multiplicar por ("ndvi@1" > 0.3), los 11,343 píxeles se escriben como el número válido 0.0, así que las estadísticas de la capa siguen contando los 250,000 píxeles e incluyen 11,343 ceros en cada media, histograma y estadística zonal que calcules después.
| Expresión de máscara | En qué se convierten los píxeles excluidos | Píxeles contados en las estadísticas | NDVI medio de la zona conservada |
|---|---|---|---|
("ndvi@1" > 0.3) * "ndvi@1" | 0.0 (contado como dato) | 250,000 | 0.719 (error de -0.034) |
"ndvi@1" / ("ndvi@1" > 0.3) | nodata (-3.40282e+38) | 238,657 | 0.753 (exacto) |
Para escribir nodata real en un solo paso, divide por la condición en lugar de multiplicar: "ndvi@1" / ("ndvi@1" > 0.3). Donde la condición es verdadera (1), el valor no cambia; donde es falsa (0), la división por cero produce nodata.
3. Calcular la pendiente sobre un DEM en grados antes de la calculadora marca el 100% del mapa como empinado
Ejecutar la herramienta Slope de QGIS con los ajustes por defecto sobre un DEM geográfico (como Copernicus GLO-30 en EPSG:4326) antes de aplicar el umbral "slope@1" > 15 marcó el 100% de nuestras tierras onduladas como más empinadas que 15 grados, con una pendiente media de 89.99 grados, cuando la cifra real tras reproyectar a UTM es 32.61%.
Copernicus GLO-30 y otros DEM globales gratuitos (consulta nuestra guía de descargas gratuitas de DEM en QGIS) llegan en grados geográficos (EPSG:4326) con elevaciones en metros. Con el factor Z por defecto, la herramienta Slope compara una subida en metros con un paso horizontal de 0.000278 (el ancho de un píxel en grados), así que cada ladera parece un acantilado vertical.
Cómo se calculó la pendiente antes de "slope@1" > 15 | Píxeles > 15 grados | Pendiente media |
|---|---|---|
Slope nativa sobre DEM EPSG:4326, factor Z por defecto 1 | 100.00% | 89.99° |
Slope de GDAL sobre DEM EPSG:4326, escala 1 | 100.00% | 89.99° |
Slope de GDAL sobre DEM EPSG:4326, escala 111120 | 31.61% | 12.54° |
| Slope nativa tras reproyectar el DEM a UTM 23S 30 m (referencia) | 32.61% | 12.68° |
| Slope de GDAL tras reproyectar el DEM a UTM 23S 30 m | 32.71% | 12.71° |
Incluso el atajo de escala de 111120 metros por grado se queda un punto porcentual corto (31.61% frente a 32.61%), porque a 22°S un grado de longitud es un 7% más corto que un grado de latitud (cos 22° = 0.93). Reproyecta siempre tu DEM a su zona UTM local (Raster > Projections > Warp (Reproject), remuestreo bilineal, y un valor nodata de -9999 para que el borde no se llene de falsas pendientes de 87°) antes de ejecutar Slope y la calculadora ráster.
4. Restar el desplazamiento +1000 de Sentinel-2 sin revisar la escena rompe el 90.6% de los píxeles
Restar 1000 a nuestras bandas Sentinel-2 L2A antes de calcular el NDVI dejó 226,413 de 250,000 píxeles (90.6%) fuera del rango válido [-1, 1], con valores de -1273 a 1217 y una media de 1.39 en lugar de 0.727.
La línea base de procesamiento 04.00 de Sentinel-2 de la ESA y las posteriores añadieron un desplazamiento de +1000 en los números digitales para que los píxeles oscuros no se recorten en cero, y los metadatos STAC indican scale: 0.0001 y offset: -0.1. Pero cuando descargas GeoTIFF optimizados para la nube desde la API STAC de Earth Search (como hicimos con la escena S2A_23KLR_20261103_0_L2A, línea base 05.13), el proveedor ya ha corregido los valores y pone earthsearch:boa_offset_applied: true en los metadatos del elemento.
En nuestro archivo B04, 226,773 de 250,000 píxeles (90.7%) tenían números digitales brutos por debajo de 1000 (mínimo 59, mediana 491). Revisa el valor mínimo de B04 en Layer Properties > Information antes de tocar la fórmula: si los píxeles oscuros están entre 50 y 300, el desplazamiento ya está quitado y el (B08 - B04) / (B08 + B04) bruto es exacto (dividir por el factor de escala 10,000 se anula en el cociente). Resta 1000 solo si tus píxeles despejados más oscuros están por encima de 1000.
Extra: lo que significan de verdad "Expression valid" y la barra roja de error genérica
Otros dos comportamientos de Raster > Raster Calculator hacen perder mucho tiempo depurando:
- Las resoluciones mezcladas en una rejilla gruesa no se promedian. Cuando combinas una banda de 10 m (
B08) y otra de 20 m (B11), la calculadora nativa remuestrea al vuelo por vecino más cercano (la calculadora de GDAL se detiene en el acto conError! Dimensions of file ... (250, 250) are different from other files (500, 500). Cannot proceed). En una rejilla de salida de 10 m, repetir cada píxel de 20 m en 2 por 2 funciona sin problema. En una rejilla de salida de 20 m, la calculadora no promedia los cuatro píxeles de 10 m: en62,250de62,500celdas simplemente tomó el píxel de 10 m superior derecho de cada bloque de 2 por 2, con diferencias de hasta0.71frente a la media de 4 píxeles en(B08 - B11) / (B08 + B11). - "Expression valid" solo comprueba la sintaxis, no los nombres de banda. Si dejas un operador al final, como
"B08@1" /, el diálogo lo detecta (Expression invalid, OK en gris).

Pero si escribes una capa o banda que no está en el proyecto (como "B04@2" o "B02@1" cuando B02 no está cargada), la etiqueta sigue diciendo Expression valid. Al hacer clic en OK, QGIS escribe un GeoTIFF de 500 por 500 lleno al 100% de nodata, no añade nada al mapa y muestra un único aviso rojo: Raster calculator: An error occurred while performing the calculation. Siempre que veas ese aviso, compara cada nombre "layer@band" con la lista Raster Bands.

Saltarse el diálogo: hacer cálculos ráster pidiéndoselo a un agente de IA en QGIS
Nosotros desarrollamos AI Agent, así que esta sección trata de nuestro propio plugin. Añade un panel de chat dentro de QGIS que puede buscar en catálogos STAC, reproyectar DEM, hacer cálculos ráster en Python o Processing y dar estilo al resultado en tu mapa.
Para ver si evita las trampas anteriores con exactamente los mismos datos de Machado, dibujé un polígono de finca de 120.07 ha (E 405300-406300, N 7594400-7595600 en UTM 23S) sobre un proyecto vacío de OpenStreetMap y envié tres instrucciones de un solo mensaje con esfuerzo Medium y permisos Balanced, un chat nuevo por tarea.
Prueba 1: NDVI en 5 clases con hectáreas por clase
Escribí:
Compute NDVI for this field from the latest cloud-free Sentinel-2 and class it in 5 classes with hectares per class
El agente consultó el catálogo STAC, vio que existía una escena del 6 de noviembre de 2026 pero muy nublada, y eligió la misma escena del 3 de noviembre de 2026 (1.65% de nubosidad en la tesela) que usé en la prueba manual. Descargó B08 y B04 a 10 m, calculó el NDVI, lo clasificó en cinco intervalos, dio estilo a la capa e informó de la superficie de cada clase en la rejilla métrica de 10 m.
| Clase de NDVI | Informe de AI Agent | Mi comprobación independiente con numpy (los mismos 12,000 píxeles) | Diferencia |
|---|---|---|---|
-1 a < 0 | 0.76 ha | 0.76 ha | 0.0% |
0 a < 0.2 | 23.85 ha | 23.84 ha | < 0.1% |
0.2 a < 0.4 | 9.27 ha | 9.27 ha | 0.0% |
0.4 a < 0.6 | 8.70 ha | 8.69 ha | 0.1% |
0.6 a 1 | 77.42 ha | 77.44 ha | < 0.1% |
| Superficie válida total | 120.00 ha | 120.00 ha (de un polígono de 120.07 ha) | 0.0% |
Píxel a píxel sobre el ráster de NDVI que exportó, la diferencia absoluta media frente a mi referencia fue de 5e-5, y su ráster de clases difería del mío en 4 píxeles de 12,000.

Prueba 2: pendiente por encima de 15 grados (sin DEM en el proyecto)
En un chat nuevo, con solo el polígono de la finca cargado, escribí:
Show where slope is above 15 degrees on the farm layer
El agente descargó el DEM Copernicus de 30 m, lo reproyectó a una rejilla métrica en lugar de calcular la pendiente en grados, y dio estilo a una capa de dos clases (15 degrees or less en amarillo pálido, above 15 degrees en rojo). Informó de 331 de 1,320 píxeles de la finca por encima de 15 grados (25.08%, máximo 29.15°). Mi propia referencia con Slope nativa sobre el DEM reproyectado a UTM, en el mismo rectángulo, dio 341 de 1,360 píxeles (25.07%, máximo 29.29°), una diferencia de 0.01 puntos porcentuales.

Prueba 3: donde todavía tienes que revisar al agente
En un tercer chat, pedí:
Mask out everything with NDVI below 0.3 on the farm layer and tell me the mean NDVI of what is left
Fíjate en que en esta instrucción no escribí "cloud-free" ni "latest". El agente evitó la trampa de la máscara a 0: escribió nodata -9999 en cada píxel enmascarado y devolvió un NDVI medio de 0.552 sobre 2,277 píxeles conservados. La media de su archivo de salida era 0.5515; la mía, con la misma escena y la misma regla, 0.5513.
Sin embargo, tomó la escena Sentinel-2 del 27 de octubre de 2026, y en esa fecha el 80.5% de la finca (9,656 de 12,000 píxeles en la banda Scene Classification) estaba cubierto de nubes, sombras o cirros. Dio la fecha en su respuesta, pero nunca mencionó que 0.552 describía solo la quinta parte despejada del campo. Con la escena despejada del 3 de noviembre, la misma regla da una media de 0.766 sobre 8,785 píxeles.
Mi regla práctica: tanto si usas la calculadora ráster a mano como si se lo pides a un agente del ecosistema de IA de QGIS, revisa siempre la fecha de la escena y carga el color real o la banda de nubes SCL antes de fiarte de una cifra resumen.
Cómo lo medimos. Todas las pruebas se hicieron el 7 de noviembre de 2026 en QGIS 3.44.15-Solothurn en macOS (GDAL 3.13.3, numpy 2.5.2) sobre una ventana de 5 km por 5 km al sur de Machado, Minas Gerais, Brasil (EPSG:32723, E 402000-407000, N 7591000-7596000), con la escena Sentinel-2 L2A S2A_23KLR_20261103_0_L2A (y la escena del 27 de octubre de 2026 para la prueba 3) de Earth Search y la tesela Copernicus GLO-30 S22_00_W046_00. Los criterios de éxito de las pruebas manuales y de las pruebas 1 y 2 del agente se escribieron antes de ejecutar ningún cálculo ráster; los de la prueba 3 se escribieron después de ver las pruebas 1 y 2. Las rejillas de referencia se calcularon con numpy en coma flotante de 64 bits fuera de QGIS. AI Agent 1.9.4 funcionó con esfuerzo Medium y permisos Balanced, un mensaje por chat. Una escena y un sitio son una prueba de un solo caso, no un estudio estadístico entre líneas base.
Preguntas frecuentes
¿Por qué mi NDVI sale todo 0, -1 o 1 en QGIS?
Forzaste un tipo de salida entero (Int16 o Byte) en la calculadora ráster de GDAL, que redondea cada decimal entre -1 y 1 a -1, 0 o 1 (el 99.99% de los píxeles en nuestra prueba). Deja el tipo de salida en Float32, o usa Raster > Raster Calculator en el menú superior, que da Float32 de forma automática.
¿Por qué la calculadora ráster de QGIS falla con 'An error occurred while performing the calculation' y devuelve nodata?
Un nombre "layer@band" de tu fórmula no coincide con una capa cargada o un número de banda (por ejemplo, escribir "B04@2" en un archivo de una sola banda, o citar una capa que quitaste). El mensaje Expression valid bajo el cuadro de la fórmula solo comprueba la sintaxis, no si las bandas existen. Vuelve a insertar cada banda con doble clic en la lista Raster Bands.
¿Qué diferencia hay entre Raster > Raster Calculator y la GDAL Raster Calculator de Processing?
Raster > Raster Calculator (y la Raster calculator nativa de Processing) usa el analizador propio de QGIS con nombres "layer@band" y siempre calcula en coma flotante. La GDAL Raster calculator (gdal_calc.py) usa variables con letras (A, B) y evalúa el cálculo numpy en el tipo de dato de la banda de entrada, así que al restar bandas de enteros de 16 bits sin signo los números negativos dan la vuelta a 65,536 salvo que conviertas con A.astype(numpy.float32).
¿Cómo escribo una condición IF o paso valores a nodata en la calculadora ráster de QGIS?
Puedes escribir if("ndvi@1" > 0.3, "ndvi@1", 0) para reemplazar por 0 los valores por debajo de 0.3. Si quieres que los píxeles excluidos pasen a nodata real para que no bajen la media de la capa, divide por la condición: "ndvi@1" / ("ndvi@1" > 0.3). Donde la condición es falsa (0), dividir por cero escribe nodata.
Sigue leyendoQué es el NDVI: significado, valores y fórmula
Hazlo en QGIS pidiéndoselo
AI Agent realiza la tarea que describes, en tu propio proyecto de QGIS. Gratis, sin tarjeta.
desde Raster > Raster Calculator (Ráster > Calculadora ráster) o desde la caja de herramientas de Processing. Para el NDVI de Sentinel-2, usa 

