ENVI Agent - First Light! 24 Mar, 26

As primeiras impressões do novo assistente que promete revolucionar o uso do ENVI em Sensoriamento Remoto & GIS

Para muitos os prompts dos LLMs (chatgpt, claude, gemini etc) já fazem parte do dia-a-dia, e ficamos ansiosos para a conexão delas com o ENVI e IDL - e esta semana os nossos parceiros da NV5 lançaram o IDL Agent e o ENVI Agent, que servem para exatamente isso!  Esse blog resume a primeira impressão:

 Esses novos assistentes foram implementados usando o Github Copilot no Visual Studio Code (veja o passo-a-passo aqui ) ;  para usar o IDL Agent é preciso o IDL 9.2 ou mais recente (o novo assistente está incluso na licença), para usar o assistente do ENVI  é preciso de uma licença ENVI+IDL 6.2 , e uma licença ENVI Agent (para os nossos testes usamos uma assinatura trial de 30 dias do Github Copilot Pro, com Claude Sonnet 4.6 como LLM).  O grande diferencial do GitHub Copilot, em relação ao chatgpt e similares , é que, através do protocolo MCP, a IA não apenas lhe da dicas sobre como analisar as imagens, mas também o executa diretamente no ENVI, seguindo as suas solicitações! 

Correção Atmosférica com FLAASH executado pelo ENVI Agent

Uma tarefa importante na análise de imagens obtidas por satélites ópticos é a correção atmosférica. A física de transferência de radiação na atmosfera é complexa, e o FLAASH tem mais de 40 parâmetros que podem ser configurados - um desafio mesmo para analista de sensoriamento remoto experientes. Será que o nosso ENVI Agent pode nos ajudar nessa tarefa ? Começamos digitando os comandos abaixo na janela do Chat:

          "Abra o ENVI+IDL, e carregue a imagem .xml no diretório d:/teste"

Demora um pouco, mas lá está o ENVI. Uma das primeiras lições: para diversas ações (como acesso ao file system) o assistente solicita a autorização - mesma escolhendo "Allow always" , o que aparentemente é uma incorreção do Claude. O assistente responde

ENVI Agent

Imagem aberta com sucesso no ENVI! O arquivo carregado foi:

DIM_PHR1A_MS_202410311257406_ORT_7154236101-2.XML — metadado DIMAP da imagem Pléiades 1A Multiespectral ortorretificada. O ENVI reconhece o formato DIMAP pelo .XML e carrega automaticamente os tiles TIF associados (R1C1 e R2C1) como uma imagem única no Data Manager.

Beleza, vamos ao que interessa:

       "Verifique os melhores parâmetros para uma correção atmosférica no módulo                        FLAASH da imagem aberta, e aplique o FLAASH nesta imagem."

O que se segue é um monólogo (chamado "reasoning") do assistente na janela do chat que é impressionante. Reasoning significa raciocínio, argumentação ou fundamentação. Refere-se ao processo cognitivo de pensar, tirar conclusões ou justificar algo logicamente. Não sei sobre a parte cognitiva, mas tirar conclusões e justificar algo logicamente é algo que o assistente faz o tempo todo .

Após ter lido todos os metadados, a documentação disponível na web sobre o formato da imagem, e a documentação do FLAASH, o assistente  explica a escolha do modelo atmosférico, os parâmetros de absorção de água e o modelo de aerossóis. Após a execução do FLAASH,  o assistente recebe um erro de que menos de 5% dos pixels tem valores razoáveis - e agora ? 

Para minha surpresa, em vez de simplesmente encerrar o processo e devolver o erro ao usuário, o assistente continuou pensando alto sobre o que pode ter impedido o FLAASH de executar a correção atmosférica; segue abaixo um trecho do "reasoning" (no original em inglês, resumo em português abaixo):

"The FLAASH task failed with the error \"Bad Pixel Count - less than 5% within physical threshholds. Check sensor gain and solar angle.\" This means the INPUT_SCALE values I used were incorrect, causing the radiance values to be out of the expected range.\n\nThe issue is with the INPUT_SCALE parameter. For Pleiades imagery, the DN values need to be converted to radiance in units of µW/cm²/nm/sr. \n\nThe metadata shows:\n- DATA GAIN VALUES = 503.08687, 480.41361, 440.00989, 296.23249\n- DATA OFFSET VALUES = 29.289326, 16.711231, 8.1329336, 2.0262220\n \nI need to figure out the correct radiometric calibration formula for Pleiades. The DATA GAIN and DATA OFFSET values in the ENVI metadata are used for converting DN to radiance, but I'm working through whether the formula is L = (DN / GAIN) + OFFSET or something else, and then I need to scale the result to match FLAASH's expected units of µW/cm²/nm/sr. W/cm²/nm/sr. For Pleiades, I need to figure out the conversion path — the metadata shows DATA GAIN VALUES around 500 and DATA REFLECTANCE GAIN of 0.0001, which suggests the raw DN values can be converted to reflectance directly. But FLAASH expects top-of-atmosphere radiance in µW/cm²/nm/sr, not reflectance, so I need to trace whether this orthorectified product is already in a different radiometric space or if I'm missing a conversion step.\n\nThe \"Bad Pixel Count\" error is telling me that whatever radiance values I'm computing from INPUT_SCALE × DN are falling outside physically reasonable bounds for the solar geometry at the time of acquisition. For Pleiades in DIMAP format, the DATA GAIN VALUES represent absolute calibration coefficients that convert DN directly to radiance in W/m²/sr/µm, so I should be using those gains rather than trying to derive them from reflectance coefficients. I'm realizing those ENVI gain values might actually represent something different—possibly the QUANTIFICATION_VALUE from Pleiades divided by the absolute calibration coefficient, which would explain why they're so much larger than the typical 10-12 range I'd expect for direct calibration coefficients.\n\nLooking at the ENVI reflectance formula more carefully, if the data gain is 0.0001 and the image stores reflectance scaled by 10000, then this file might already contain reflectance data rather than raw radiance—which would make running FLAASH on it problematic since FLAASH is designed to work with TOA radiance as input, not reflectance. So the DATA_GAIN_VALUES in ENVI metadata actually represent the inverse relationship—they convert radiance back to DN rather than the other way around. For band 0, that means the radiance in W/m²/sr/µm equals (DN - 29.29) / 503.09, and then I need to scale this to µW/cm²/nm/sr for FLAASH by multiplying by 0.1. The INPUT_SCALE parameter gets more complicated because of that offset term, though FLAASH's normalization factors are meant to handle the band-specific conversions.\n\nFor a practical solution, if the offset values are negligible compared to typical DN values, I can approximate the INPUT_SCALE for each band as 0.1 divided by the gain value—so roughly 0.0001988 for band 0, 0.0002082 for band 1, and so on.\n\nThe \"Bad Pixel Count\" error suggests that when FLAASH applies these scales to the DN values, fewer than 5% of pixels end up within the expected physical radiance range for the given solar geometry. This could indicate the DN values are already in reflectance (possibly scaled by 10000), the INPUT_SCALE is off by an order of magnitude, the solar angle parameters are incorrect, or the data has already been atmospherically corrected. I should reconsider whether the DATA REFLECTANCE GAIN might be the issue here.\n\nIf the typical pixel values around 500-1000 DN represent 5-10% reflectance, that would make sense for natural surfaces. But I need to verify what Pleiades ortho products actually deliver—the DIM_PHR1A_MS_ORT format should be in DN requiring radiometric correction for FLAASH, not pre-processed reflectance. Since the error indicates pixels are out of physical range, I should try a significantly larger INPUT_SCALE or reconsider the entire approach.\n\nNow I'm wondering if ENVI's handling of the DIMAP format has already scaled the data to reflectance × 10000, which would mean DN=1000 corresponds to 10% reflectance. If that's the case, I can calculate what INPUT_SCALE FLAASH would need to interpret those values as the correct radiance—something around 0.0061 based on the solar irradiance at 490nm. Or perhaps the actual DN values are much larger than I'm assuming, in the 10000+ range.\n\nLet me check the actual pixel statistics in the image to figure out the right INPUT_SCALE value, since FLAASH failed with my previous attempt. The user wants to see the result, but I need to fix the INPUT_SCALE issue first before FLAASH can run successfully. For Pleiades DIMAP products, the pixel values in the GeoTIFF files are integers, so examining the actual data range should tell me what scaling factor to use. I need to figure out the right INPUT_SCALE by testing against the actual DN range in the image. The 0.0001988 value I tried produced radiance values that were far too low—even with DN values in the 0-4095 range, I'm getting results in the 0.4 µW/cm²/nm/sr range when I should be seeing values closer to what's expected for blue band TOA radiance at this solar geometry.\n\nThe math suggests that to reach realistic radiance values with this scale factor, I'd need DN values around 50,000, which doesn't make sense for a 12-bit image. This points to either the data being delivered as reflectance scaled by 10,000 rather than raw radiance, or my understanding of the Pleiades format being off. Let me recalculate what the correct scale should be if the DN values are actually in the 0-4095 range.\n\nFor typical mid-range DN values around 2000, I'd need an INPUT_SCALE of about 0.025 to get reasonable radiance values—that's roughly 125 times larger than what I've been using. Rather than keep guessing at the calibration coefficients, I should examine the actual pixel values in the image and the XML metadata to figure out what the DATA_GAIN values really represent, then work backward to derive the proper scale factor. Since FLAASH already failed, I'll just display whatever result we can get. I need to find the PHYSICAL_GAIN and PHYSICAL_BIAS values in the DIMAP metadata to get the correct absolute calibration coefficients for Pleiades, or I could try letting FLAASH auto-detect from the metadata instead. I'm also considering the standard calibration gains for Pleiades-1A across the blue, green, and red bands to calculate the proper INPUT_SCALE values. I'm realizing FLAASH needs radiance input, not reflectance-corrected data, so if ENVI already converted the pixels to reflectance values, that's why the atmospheric correction failed. Let me examine the actual pixel statistics and search the XML metadata for calibration coefficients to understand what format the data is actually in, then either convert it appropriately or try a different approach to show the user a result.

Após alguns minutos de "reasoning" e análises, o resultado da correção atmosférica saiu corretamente na tela;  em seguida pedi um resumo do raciocínio 

              "resume pra mim o raciocínio para chegar no resultado"

que segue abaixo (original em português)

# Raciocínio Passo a Passo — Correção Atmosférica FLAASH em Pleiades PHR1A

---

## Passo 1 — Identificar os Parâmetros do ENVITask FLAASH

Primeiro consultei o schema completo da ferramenta FLAASH via `get-envi-tool-parameters`. Isso revelou todos os parâmetros aceitos, seus tipos, valores padrão e descrições. Os mais críticos para o Pleiades são:

- `sensor_type`: tipo do sensor (Multispectral, AVIRIS, etc.)
- `input_scale`: fator de escala para converter DN → µW/cm²/nm/sr (unidade que o FLAASH exige)
- `modtran_atm`: modelo atmosférico MODTRAN
- `modtran_aer`: modelo de aerossol
- `solar_azimuth` / `solar_zenith`: geometria solar
- `los_azimuth` / `los_zenith`: geometria de visada do sensor
- `lat_long`: coordenadas do centro da cena
- `sensor_altitude` / `ground_elevation`: altitudes

---

## Passo 2 — Extrair Metadados da Imagem

Abri o raster PHR1A via `e.OpenRaster` e li a propriedade `METADATA`. O ENVI parseou automaticamente a partir do XML DIM:

```
ACQUISITION TIME   = '2024-10-31T12:57:40.6Z'
SUN AZIMUTH        = 118.07177°
SUN ELEVATION      = 71.52482°
WAVELENGTH         = 490, 560, 650, 840 nm
DATA GAIN VALUES   = 503.09, 480.41, 440.01, 296.23
```

Lendo o XML DIM linha a linha com `READF`, extraí também:
- `INCIDENCE_ANGLE = 21.42°` → ângulo off-nadir do sensor
- `AZIMUTH_ANGLE = 179.65°` → azimute da linha de visada

---

## Passo 3 — Determinar os Parâmetros Atmosféricos e Geográficos

| Parâmetro | Valor | Justificativa |
|---|---|---|
| `modtran_atm` | Tropical Atmosphere | Latitude ~6°S, nordeste do Brasil |
| `modtran_aer` | High-Visibility Rural | Bioma Caatinga — vegetação seca, sem indústria pesada |
| `solar_zenith` | 18.48° | = 90° − SUN_ELEVATION (71.52°) |
| `los_zenith` | 201.42° | = 180° + INCIDENCE_ANGLE (21.42°). FLAASH usa 180° = nadir; off-nadir soma ao ângulo |
| `sensor_altitude` | 694 km | Altitude orbital padrão do Pleiades-1A |
| `ground_elevation` | 0.05 km | Terreno de baixo planalto/litoral no Rio Grande do Norte |
| `lat_long` | [-5.9958, -35.1357] | Centro da cena extraído das tags `/` no XML DIM |

---

## Passo 4 — Entender a Escala dos Dados da Imagem

Verificando estatísticas reais de pixels (amostra de 1000×1000 no centro da cena):

```
Band 0: min=302, mean=1399, max=4179
```

Valores na faixa 300–5000 indicam que os DNs são **reflectância aparente × 10000** (inteiros escalados). O XML DIM confirma isso explicitamente:

```xml
Reflectance gained value (RHO') to Reflectance (RHO).
              Formulae RHO=RHO'/GAIN+BIAS

10000
```

**O FLAASH exige radiância TOA em µW/cm²/nm/sr** — não reflectância. Por isso a primeira tentativa com `INPUT_SCALE` simples falhou com "Bad Pixel Count < 5%": os valores eram fisicamente incompatíveis com radiância.

---

## Passo 5 — Encontrar os Coeficientes de Conversão Reflectância → Radiância

O bloco `` no XML DIM fornece:

```
L (W/m²/sr/µm) = RHO / GAIN_rad + BIAS_rad
```

| Banda | GAIN_rad | BIAS_rad |
|---|---|---|
| B0 (Azul 490nm) | 0.001987728 | 29.2893 |
| B1 (Verde 560nm) | 0.002081540 | 16.7112 |
| B2 (Vermelho 650nm) | 0.002272676 | 8.1329 |
| B3 (NIR 840nm) | 0.003375727 | 2.0262 |

Para converter para µW/cm²/nm/sr (unidade exigida pelo FLAASH), multiplica-se por 0.1:

$$L_{\mu W} = \left(\frac{DN / 10000}{GAIN_{rad}} + BIAS_{rad}\right) \times 0.1$$

---

## Passo 6 — Criar o Raster de Radiância Intermediário

O ENVI não permite passar uma expressão algébrica diretamente ao FLAASH. A solução foi criar um novo raster ENVI com os valores convertidos:

```idl
out_raster = ENVIRaster(URI=rad_file, ..., METADATA=meta)
; Processar banda a banda, em tiles de 512 linhas para gerenciar memória
FOR b=0, nb-1 DO BEGIN
  FOR row=0L, nr-1L, TILE DO BEGIN
    dn  = src.GetData(BANDS=[b], SUB_RECT=[...])
    rad = (FLOAT(dn)/10000.0 / gains[b] + biases[b]) * 0.1
    out_raster.SetData, rad, ...
  ENDFOR
ENDFOR
```

**Lição importante 1:** `ENVIRaster.GetData` retorna dimensões `[nc, nr_tile]` para uma única banda — NÃO `[nb, nc, nr_tile]`. Ler todas as bandas de uma vez e depois indexar por banda causou o erro "Array subscript mismatch". Processar uma banda por vez resolve o problema.

**Lição importante 2:** O `ENVIRasterMetadata` deve ser passado no momento da criação do raster (`ENVIRaster(..., METADATA=meta)`). Adicionar informações de comprimento de onda ao arquivo `.hdr` após a criação não é relido pela sessão ENVI já aberta.

---

## Passo 7 — Executar o FLAASH

Com o raster de radiância corretamente calibrado e com metadados de comprimento de onda embutidos, o FLAASH executou sem erros:

```idl
task = ENVITask('FLAASH')
task.INPUT_RASTER  = raster      ; radiância em µW/cm²/nm/sr
task.INPUT_SCALE   = [1,1,1,1]  ; já na unidade correta
task.OUTPUT_SCALE  = 10000       ; reflectância de superfície × 10000 (inteiro)
task.Execute
```

---

## Passo 8 — Exibir o Resultado

```idl
layer = view.CreateLayer(result, BANDS=[2,1,0])  ; RGB: Vermelho=B2, Verde=B1, Azul=B0
```

Composição RGB em cores naturais para inspeção visual da qualidade da correção.

---

Para finalizar pedi uma rotina batch no formato .model do ENVI Modeler para aplicar a correção em um conjunto de imagens

               "Pode criar um ENVI Modeler .model para aplicar o FLAASH num conjunto                                     de imagens similares ?

Observar o "reasoning" é sempre parte do espetáculo:

...I found the ENVI model files. Let me read the relevant example models to understand the format.

Leia 02 - Simple Model.model
Leia 03 - Batch Process.model

Now I understand the format perfectly — it's JSON. Let me read one of the custom models from ENVI62 and also look at the export/output approach.

Leia MULTI_PROC_SENTINEL2.model
Leia 05 - Generate Thumbnails.model

Now I have everything I need. The format is JSON (envimodel_1.0), and I can see the exact node/edge patterns. I'll build the batch FLAASH model following the same structure as the "Generate Thumbnails" batch pattern.

Batch_FLAASH.model foi criado

Pelo jeito o assistente não teve conhecimento prévio sobre o ENVI Modeler, e aprendeu "on-the-fly" usando a documentação do ENVI, e exemplos existentes; o resultado é 100% funcional e com comentários detalhado, e instruções como usa-lo (no chat window):

ENVI  FLAASH_Batch.model file criado pelo ENVI Agent

Em resumo: Os primeiros testes mostram uma resiliência surpreendente do ENVI Agent ao atender as solicitações do usuário; eventuais problemas são analisados, e  resolvidos na medida do possível. A capacidade de acessar documentação, exemplos e código existente para produzir resultados de forma autônoma promete ser muito útil tanto para usuários que ainda não tem familiaridade para com o ENVI e/ou Sensoriamento Remoto, como também para os analistas experientes que terão uma economia de tempo substancial com o uso do assistente. 

Fale Conosco! Nossa equipe está pronta para ajudar você a encontrar as melhores soluções em processamento de dados geoespaciais. Entre em contato e saiba mais!
Envie uma mensagem
Nome Completo
Empresa
Telefone
Email
Mensagem
Captcha