Calculadora raster do QGIS: fórmulas testadas e 4 armadilhas silenciosas
Publicado em
Abra a calculadora raster do QGIS em Raster > Raster Calculator (Raster > Calculadora Raster) ou pela Caixa de Ferramentas de Processamento. Para o NDVI do Sentinel-2, use ("B08@1" - "B04@1") / ("B08@1" + "B04@1"): a calculadora do menu calcula em Float32 automaticamente. Fique atento à calculadora do GDAL, que dá a volta nos inteiros sem sinal, às máscaras com *, que gravam 0 em vez de nodata, e às ferramentas de declividade, que quebram em grades em graus.
Testei tudo isso em 7 de novembro de 2026 no QGIS 3.44.15, em uma janela de 5 km por 5 km de lavouras em relevo ondulado ao sul de Machado, Minas Gerais (2.500 ha, 250.000 pixels de 10 m em UTM 23S, EPSG:32723). Usei uma cena Sentinel-2 L2A de 3 de novembro de 2026 e um MDE Copernicus GLO-30 de 30 m, e conferi cada resultado com uma referência numpy em ponto flutuante de 64 bits, fora do QGIS.
O que é a calculadora raster do QGIS, e qual delas você está abrindo?
Uma calculadora raster avalia uma expressão matemática ou booleana pixel a pixel em uma ou mais bandas raster e grava uma nova grade. No QGIS, você se refere a uma banda como "layername@band" (por exemplo "B08@1" para a banda 1 da camada B08), combina bandas com +, -, *, /, <, >, AND, OR ou if(condition, true, false), e grava o resultado em um GeoTIFF ou em uma camada virtual na memória.
O que confunde muita gente é que o QGIS traz cinco ferramentas chamadas "Raster calculator", e elas não usam todas o mesmo motor. Quatro usam o interpretador de expressões nativo do QGIS e calculam em ponto flutuante. A do GDAL (por baixo, gdal_calc.py) usa variáveis com as letras A/B/C e avalia expressões numpy no próprio tipo de dado da banda de entrada.
| Ferramenta no QGIS 3.44 | Sintaxe da banda | Tipo de saída | Pixels com erro > 0,01 no 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 (na memória) | 0 |
Processing: Raster calculator (legacy) (qgis:rastercalculator) | "B08@1" | Float32 | 0 |
Processing: GDAL Raster calculator (gdal:rastercalculator) | A, B | Arquivo Float32, cálculo no tipo de entrada | 703 (0,28%, valores até 126,7) |
Se você só quer uma fórmula que funcione sem converter tipos, use Raster > Raster Calculator no menu superior, ou a primeira Raster calculator do grupo nativo do QGIS no Processamento.
Passo a passo: calcular o NDVI na calculadora raster do QGIS
Se você ainda precisa das bandas do Sentinel-2, nosso guia sobre como baixar imagens Sentinel-2 no QGIS mostra o caminho pelo catálogo STAC. Com as bandas B04 (vermelho, 10 m) e B08 (infravermelho próximo, 10 m) no painel Camadas, calcular o que o NDVI mede leva quatro passos.
Selecione a camada que define a grade de saída
Clique em B08 no painel Camadas antes de abrir a janela. Quando Raster > Raster Calculator abre, ela lê a extensão de saída, o sistema de coordenadas (SRC), a largura e a altura da camada raster selecionada no momento no painel Camadas. Confira se o cabeçalho mostra Extent (current: B08).
Digite a expressão do NDVI
Em Raster > Raster Calculator, clique duas vezes em B08@1 e B04@1 na lista Raster Bands (ou digite os nomes entre aspas duplas) para montar:
("B08@1" - "B04@1") / ("B08@1" + "B04@1")
Confira se a mensagem logo abaixo da caixa de expressão diz Expression valid. Nesta janela, você não precisa converter as bandas Sentinel-2 de 16 bits sem sinal para float.
Escolha um arquivo de saída ou uma camada virtual
Defina Output layer com um caminho .tif e deixe Output format em GeoTIFF. Se você só quer uma prévia rápida e não quer arquivo em disco, marque Create on-the-fly raster instead of writing layer to disk (isso guarda no arquivo do projeto um URI com a fórmula e caminhos absolutos para as entradas, e bate com o arquivo gravado até 3e-8).
Execute e aplique o estilo ao resultado
Clique em OK. Na nossa janela de 500 por 500 pixels, o cálculo terminou em 0,12 segundo, com valores de -0.5507 a 0.9547 e diferença máxima de 2.98e-8 em relação ao numpy de 64 bits. Abra Layer Properties > Symbology, mude para Singleband pseudocolor, escolha a rampa RdYlGn e defina o mínimo em 0 e o máximo em 0.9.
Esta é a janela logo antes de clicar em OK, com a extensão tirada de B08:

Com o estilo RdYlGn, a vegetação densa em volta de Machado aparece em verde-escuro, o solo exposto e as estradas em vermelho, e os 703 pixels onde o vermelho supera o infravermelho próximo (água e pontos escuros) ficam negativos. O NDVI médio de toda a janela é 0.727. Se o seu dossel é denso a ponto de saturar o NDVI ou deixa solo exposto entre as linhas, veja como a fórmula muda na nossa comparação entre NDVI, EVI, SAVI e NDRE.

Receitas de fórmulas para a calculadora raster do QGIS
Cada expressão abaixo foi executada no QGIS 3.44.15 (QgsRasterCalculator) com os dados de Machado e conferida pixel a pixel com o numpy. Copie a sintaxe com aspas duplas em volta de "layer@band".
| Tarefa | Expressão testada (Raster > Raster Calculator) | O que ela gerou na janela de teste de Machado |
|---|---|---|
| NDVI (Sentinel-2 10 m) | ("B08@1" - "B04@1") / ("B08@1" + "B04@1") | Float32 de -0.5507 a 0.9547 em 250.000 pixels; erro máximo 2.98e-8. |
| NDWI (índice de água de McFeeters) | ("B03@1" - "B08@1") / ("B03@1" + "B08@1") | Float32; "ndwi@1" > 0 isolou 637 pixels de água (6,4 ha de açudes e córregos). |
| Mascarar abaixo de um limiar como nodata | "ndvi@1" / ("ndvi@1" > 0.3) | Divide por 0 onde é falso e grava nodata de verdade (11,343 pixels excluídos; média 0.753). |
Substituição condicional (if) | if("ndvi@1" > 0.3, "ndvi@1", 0) | É aceita e mantém os valores acima de 0.3, mas grava 0 no resto, como a máscara com *. |
| Reclassificar o MDE em 5 classes (soma 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 de 1 a 5 em 54.901 pixels do MDE; idêntico em cada pixel ao native:reclassifybytable. |
Reclassificar o MDE em 5 classes (if aninhado) | if("dem@1" < 800, 1, if("dem@1" < 850, 2, if("dem@1" < 900, 3, if("dem@1" < 1000, 4, 5)))) | As mesmas 5 classes (96,9 ha, 1.089,4 ha, 1.323,1 ha, 1.759,7 ha, 582,7 ha). |
| Limiar de declividade | "slope@1" > 15 | Grava 1 acima de 15 graus e 0 em 15 ou menos (17,327 de 52,979 pixels válidos do MDE em UTM, 32,61%). |
| Altitude de metros para pés | "dem@1" * 3.28084 | Erro máximo de 0.98 ft (0.026% a 1.168 m) se você usar o 3.28 do manual do QGIS em vez de 3.28084. |
Quatro armadilhas silenciosas que dão números errados (e como identificá-las)
Nenhuma das quatro falhas abaixo gera aviso no QGIS. Cada uma termina, adiciona uma camada ao projeto e entrega números que parecem plausíveis até você conferir.
1. A calculadora raster do GDAL dá a volta nos inteiros sem sinal quando o NDVI é negativo
A calculadora raster nativa do QGIS nunca cai em um erro de divisão inteira com bandas Sentinel-2, mas a GDAL Raster calculator do Processamento (gdal:rastercalculator) avalia (A-B)/(A+B) no próprio tipo de dado numpy do arquivo de entrada e corrompe cada pixel onde o vermelho é maior que o NIR.
As bandas Sentinel-2 Level-2A vêm como inteiros de 16 bits sem sinal (uint16). Na nossa janela de 250.000 pixels, 703 pixels (0,28%, água e pontos escuros) têm B04 maior que B08. Quando gdal:rastercalculator subtrai B04 de B08 em uint16, o resultado negativo dá a volta em 65.536, e a ferramenta grava esses 703 pixels em um arquivo Float32 com valores entre 0 e 126.7 em vez de NDVI negativo.

Se você usa a calculadora do GDAL, converta o tipo na própria expressão com (A.astype(numpy.float32)-B)/(A+B) (o que zerou os pixels errados no nosso teste), ou use a calculadora raster nativa do QGIS. E nunca defina o tipo de saída do GDAL como Int16 ou Byte em um índice: forçar Int16 arredondou 249.973 dos nossos 250.000 pixels (99,99%) para apenas -1, 0 ou 1.
2. Multiplicar por uma condição (*) grava 0, não nodata, e puxa a média para baixo
Multiplicar um raster por uma condição booleana como ("ndvi@1" > 0.3) * "ndvi@1" coloca 0 em cada pixel excluído em vez de nodata, o que baixou o NDVI médio da área mantida de 0.753 para 0.719.
O manual oficial do QGIS ensina ("elevation@1" >= 0) * "elevation@1" como o jeito padrão de mascarar um raster. Na nossa camada de NDVI de Machado, 11,343 pixels ficam em 0.3 ou abaixo. Quando você multiplica por ("ndvi@1" > 0.3), todos os 11,343 pixels são gravados com o número válido 0.0, então as estatísticas da camada continuam contando os 250.000 pixels e incluem 11,343 zeros em cada média, histograma e estatística zonal que você rodar depois.
| Expressão da máscara | O que os pixels excluídos viram | Pixels contados nas estatísticas da camada | NDVI médio da área mantida |
|---|---|---|---|
("ndvi@1" > 0.3) * "ndvi@1" | 0.0 (contado como dado) | 250.000 | 0.719 (erro de -0.034) |
"ndvi@1" / ("ndvi@1" > 0.3) | nodata (-3.40282e+38) | 238.657 | 0.753 (exato) |
Para gravar nodata de verdade em um passo só, divida pela condição em vez de multiplicar: "ndvi@1" / ("ndvi@1" > 0.3). Onde a condição é verdadeira (1), o valor não muda; onde é falsa (0), a divisão por zero gera nodata.
3. Rodar a declividade em um MDE em graus antes da calculadora marca 100% do mapa como íngreme
Rodar a ferramenta Slope do QGIS com as configurações padrão em um MDE geográfico (como o Copernicus GLO-30 em EPSG:4326) antes de aplicar o limiar "slope@1" > 15 marcou 100% das nossas lavouras em relevo ondulado como mais íngremes que 15 graus, com declividade média de 89.99 graus, enquanto o valor real depois de reprojetar para UTM é 32.61%.
O Copernicus GLO-30 e outros MDEs globais gratuitos (veja nosso guia de downloads gratuitos de MDE no QGIS) vêm em graus geográficos (EPSG:4326) com altitudes em metros. Com o fator Z padrão, a ferramenta Slope lê uma subida em metros contra um passo horizontal de 0.000278 (a largura de um pixel em graus), então cada encosta parece um paredão vertical.
Como a declividade foi calculada antes de "slope@1" > 15 | Pixels > 15 graus | Declividade média |
|---|---|---|
Slope nativo no MDE em EPSG:4326, fator Z padrão 1 | 100.00% | 89.99° |
Slope do GDAL no MDE em EPSG:4326, escala 1 | 100.00% | 89.99° |
Slope do GDAL no MDE em EPSG:4326, escala 111120 | 31.61% | 12.54° |
| Slope nativo depois de reprojetar o MDE para UTM 23S 30 m (referência) | 32.61% | 12.68° |
| Slope do GDAL depois de reprojetar o MDE para UTM 23S 30 m | 32.71% | 12.71° |
Até o atalho de escala de 111120 metros por grau fica um ponto percentual inteiro abaixo (31.61% contra 32.61%), porque a 22°S um grau de longitude é cerca de 7% mais curto que um grau de latitude (cos 22° = 0.93). Sempre reprojete o MDE para a zona UTM local (Raster > Projections > Warp (Reproject), reamostragem bilinear, e um valor nodata de -9999 para a borda não gerar falsas declividades de 87°) antes de rodar a declividade e a calculadora raster.
4. Subtrair o deslocamento de +1000 do Sentinel-2 sem conferir a cena estraga 90,6% dos pixels
Subtrair 1000 das nossas bandas Sentinel-2 L2A antes de calcular o NDVI jogou 226,413 de 250,000 pixels (90,6%) para fora da faixa válida [-1, 1], com valores de -1273 a 1217 e média de 1.39 em vez de 0.727.
A partir da baseline de processamento 04.00, a ESA adicionou ao Sentinel-2 um deslocamento de +1000 nos números digitais para os pixels escuros não serem cortados em zero, e os metadados STAC trazem scale: 0.0001 e offset: -0.1. Mas quando você baixa Cloud-Optimized GeoTIFFs da API STAC do Earth Search (como fizemos para a cena S2A_23KLR_20261103_0_L2A, baseline 05.13), o provedor já deslocou os valores e define earthsearch:boa_offset_applied: true nos metadados do item.
No nosso arquivo B04, 226,773 de 250,000 pixels (90,7%) tinham números digitais brutos abaixo de 1000 (mínimo 59, mediana 491). Confira o valor mínimo de B04 em Layer Properties > Information antes de mexer na fórmula: se os pixels escuros ficam por volta de 50 a 300, o deslocamento já foi removido e o (B08 - B04) / (B08 + B04) bruto é exato (dividir pelo fator de escala 10,000 se cancela na razão). Só subtraia 1000 se os seus pixels mais escuros de céu limpo ficarem acima de 1000.
Bônus: o que "Expression valid" e a barra de erro vermelha genérica querem dizer de fato
Dois outros comportamentos de Raster > Raster Calculator fazem perder muito tempo depurando:
- Resoluções misturadas em uma grade grossa não fazem média. Quando você combina uma banda de 10 m (
B08) com uma de 20 m (B11), a calculadora nativa reamostra na hora usando vizinho mais próximo (a calculadora do GDAL para na hora comError! Dimensions of file ... (250, 250) are different from other files (500, 500). Cannot proceed). Em uma grade de saída de 10 m, repetir cada pixel de 20 m em 2 por 2 funciona bem. Em uma grade de saída de 20 m, a calculadora não faz a média dos quatro pixels de 10 m: em62,250de62,500células ela simplesmente pegou o pixel de 10 m do canto superior direito de cada bloco 2 por 2, com diferença de até0.71em relação à média dos 4 pixels em(B08 - B11) / (B08 + B11). - "Expression valid" só confere a sintaxe, não os nomes das bandas. Se você deixa um operador sobrando no fim, como
"B08@1" /, a janela detecta (Expression invalid, OK desativado).

Mas se você digita uma camada ou banda que não está no projeto (como "B04@2" ou "B02@1" quando B02 não está carregada), a mensagem continua dizendo Expression valid. Quando você clica em OK, o QGIS grava um GeoTIFF de 500 por 500 preenchido 100% com nodata, não adiciona nada ao mapa e mostra uma faixa vermelha: Raster calculator: An error occurred while performing the calculation. Sempre que vir essa faixa, confira cada nome "layer@band" com a lista Raster Bands.

Sem passar pela janela: cálculo raster pedindo a um agente de IA no QGIS
Nós desenvolvemos o AI Agent, então esta seção fala do nosso próprio plugin. Ele abre um painel de chat dentro do QGIS que busca em catálogos STAC, reprojeta MDEs, faz cálculo raster em Python ou pelo Processamento e aplica o estilo ao resultado no seu mapa.
Para ver se ele evita as armadilhas acima com exatamente os mesmos dados de Machado, desenhei o polígono de uma fazenda de 120,07 ha (E 405300-406300, N 7594400-7595600 em UTM 23S) sobre um projeto vazio com OpenStreetMap e enviei três prompts de uma mensagem só, em esforço Medium, permissões Balanced, um chat novo por tarefa.
Teste 1: NDVI em 5 classes com hectares por classe
Digitei:
Compute NDVI for this field from the latest cloud-free Sentinel-2 and class it in 5 classes with hectares per class
O agente consultou o catálogo STAC, notou que existia uma cena de 6 de novembro de 2026 mas com muitas nuvens, e escolheu a mesma cena de 3 de novembro de 2026 (1.65% de cobertura de nuvens no tile) que usei no teste manual. Ele baixou B08 e B04 a 10 m, calculou o NDVI, classificou em cinco intervalos, aplicou o estilo à camada e informou a área por classe na grade métrica de 10 m.
| Classe de NDVI | Relatório do AI Agent | Minha checagem independente com numpy (os mesmos 12.000 pixels) | Diferença |
|---|---|---|---|
-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% |
| Área válida total | 120.00 ha | 120.00 ha (de um polígono de 120.07 ha) | 0.0% |
Pixel a pixel no raster de NDVI exportado por ele, a diferença absoluta média em relação à minha referência foi 5e-5, e o raster de classes diferiu do meu em 4 pixels de 12.000.

Teste 2: declividade acima de 15 graus (sem MDE no projeto)
Em um chat novo, só com o polígono da fazenda carregado, digitei:
Show where slope is above 15 degrees on the farm layer
O agente baixou o MDE Copernicus de 30 m, reprojetou para uma grade métrica em vez de calcular a declividade em graus, e aplicou um estilo de duas classes (15 degrees or less em amarelo-claro, above 15 degrees em vermelho). Ele informou 331 de 1,320 pixels da fazenda acima de 15 graus (25.08%, máximo 29.15°). Minha própria referência com Slope nativo e MDE reprojetado em UTM, no mesmo retângulo, deu 341 de 1,360 pixels (25.07%, máximo 29.29°), uma diferença de 0.01 ponto percentual.

Teste 3: onde você ainda precisa conferir o agente
Em um terceiro chat, pedi:
Mask out everything with NDVI below 0.3 on the farm layer and tell me the mean NDVI of what is left
Repare que não escrevi "cloud-free" nem "latest" neste prompt. O agente evitou a armadilha da máscara com 0: gravou nodata -9999 em cada pixel mascarado e retornou um NDVI médio de 0.552 em 2,277 pixels mantidos. A média do arquivo gerado por ele foi 0.5515; a minha, com a mesma cena e a mesma regra, foi 0.5513.
Só que ele pegou a cena Sentinel-2 de 27 de outubro de 2026, e nessa data 80.5% da fazenda (9,656 de 12,000 pixels na banda Scene Classification) estava coberta por nuvem, sombra ou cirros. Ele citou a data na resposta, mas nunca mencionou que 0.552 descrevia só o quinto do talhão que estava limpo. Na cena limpa de 3 de novembro, a mesma regra dá uma média de 0.766 em 8.785 pixels.
Minha regra prática: quer você use a calculadora raster à mão, quer peça a um agente do ecossistema de IA do QGIS, sempre confira a data da cena e carregue a banda de cor verdadeira ou a banda de nuvens SCL antes de confiar em um número resumido.
Como medimos. Todos os testes foram feitos em 7 de novembro de 2026 no QGIS 3.44.15-Solothurn no macOS (GDAL 3.13.3, numpy 2.5.2) em uma janela de 5 km por 5 km ao sul de Machado, Minas Gerais (EPSG:32723, E 402000-407000, N 7591000-7596000), com a cena Sentinel-2 L2A S2A_23KLR_20261103_0_L2A (e a cena de 27 de outubro de 2026 para o teste 3) do Earth Search e o tile Copernicus GLO-30 S22_00_W046_00. Os critérios de sucesso dos testes manuais e dos testes 1 e 2 do agente foram escritos antes de qualquer cálculo raster; os critérios do teste 3 foram escritos depois de ver os testes 1 e 2. As grades de referência foram calculadas em numpy com float de 64 bits fora do QGIS. O AI Agent 1.9.4 rodou em esforço Medium e permissões Balanced, uma mensagem por chat. Uma cena e um local formam um benchmark de caso único, não um levantamento estatístico entre baselines.
Perguntas frequentes
Por que o meu NDVI sai todo 0, -1 ou 1 no QGIS?
Você forçou um tipo de saída inteiro (Int16 ou Byte) na calculadora raster do GDAL, que arredonda cada decimal entre -1 e 1 para -1, 0 ou 1 (99,99% dos pixels no nosso teste). Deixe o tipo de saída em Float32, ou use Raster > Raster Calculator no menu superior, que gera Float32 automaticamente.
Por que a calculadora raster do QGIS falha com 'An error occurred while performing the calculation' e gera nodata?
Um nome "layer@band" da sua fórmula não corresponde a uma camada carregada ou a um número de banda (por exemplo, digitar "B04@2" em um arquivo de banda única, ou citar uma camada que você removeu). A mensagem Expression valid abaixo da caixa da fórmula só confere a sintaxe, não se as bandas existem. Insira de novo cada banda clicando duas vezes nela na lista Raster Bands.
Qual a diferença entre Raster > Raster Calculator e a calculadora raster do GDAL no Processamento?
Raster > Raster Calculator (e a Raster calculator nativa do Processamento) usa o interpretador do próprio QGIS com nomes "layer@band" e sempre calcula em ponto flutuante. A GDAL Raster calculator (gdal_calc.py) usa variáveis com letras (A, B) e avalia o cálculo numpy no tipo de dado da banda de entrada, então subtrair bandas inteiras de 16 bits sem sinal faz os números negativos darem a volta em 65,536, a menos que você converta com A.astype(numpy.float32).
Como escrever uma condição IF ou definir valores como nodata na calculadora raster do QGIS?
Você pode escrever if("ndvi@1" > 0.3, "ndvi@1", 0) para trocar os valores abaixo de 0.3 por 0. Se quiser que os pixels excluídos virem nodata de verdade, para não puxarem a média da camada para baixo, divida pela condição: "ndvi@1" / ("ndvi@1" > 0.3). Onde a condição é falsa (0), a divisão por zero grava nodata.
Leia a seguirO que é NDVI? Significado, valores e fórmula
Faça no QGIS só pedindo
O AI Agent executa a tarefa que você descreve, no seu próprio projeto QGIS. Grátis, sem cartão.
em Raster > Raster Calculator (Raster > Calculadora Raster) ou pela Caixa de Ferramentas de Processamento. Para o NDVI do Sentinel-2, use 

