giovedì 5 marzo 2026

Red Edge Position Enmap

In "Fundamental of geological and environmental remote sensing R.K.Vincent, Prentice Hall (1997)" cap 7 viene indicato che lo spostamento del Red Edge della vegetazione puo' essere un indicatore diagnostico per il tipo di mineralogia del suolo quando questo non possa essere visibile a causa della copertura vegetale

 

 

pag 197 del libro 

Questo spostamento e' indicativamente verso il blu per zone a maggiore mineralizzazione (anche se puo' accadere l'opposto)

Gavorrano

Ho provato con lo script sottostante a verificare cosa accadeva nei dintorni dei depositi minerari della Toscana Meridionale

 Questi sono gli spettri di alcuni punti nell'intorno


se si effettua la normalizzazione fondamentalmente non si vede nessun spostamento del red edg

 

plottando la posizione del red edge con come semplice spettro ma come mappa di ogni singolo pixel con lo script sottostante (per fare un lavoro completo avrei dovuto mascherare i punti che non sono vegetazione) si conferma che non ci sono particolari indicazion di variazioni del red edge attorno al sito minerario




import h5py
import numpy as np
import rasterio
from rasterio.transform import from_origin

file_path = 'gavorrano.h5'
output_tiff = 'gavorrano_REP_normalized.tif'

# Lunghezze d'onda nominali EnMAP VNIR (approssimative se mancano i metadati)
# In un file standard: Band 42 ~671nm, Band 52 ~703nm, Band 62 ~736nm, Band 75 ~779nm
def get_band_data(f, nr):
return f[f'bands/band_{nr:03d}'][:]

with h5py.File(file_path, 'r') as f:

band_indices = range(38, 81)
first_band = get_band_data(f, band_indices[0])
rows, cols = first_band.shape
cube = np.zeros((rows, cols, len(band_indices)), dtype=np.float32)
print("Caricamento e normalizzazione bande...")
for i, b_nr in enumerate(band_indices):
cube[:, :, i] = get_band_data(f, b_nr)

# 2. Normalizzazione Min-Max (0-1) lungo l'asse spettrale
c_min = cube.min(axis=2, keepdims=True)
c_max = cube.max(axis=2, keepdims=True)
denom_norm = c_max - c_min
# Evitiamo divisioni per zero
norm_cube = np.divide(cube - c_min, denom_norm,
out=np.zeros_like(cube),
where=denom_norm != 0)

r670 = norm_cube[:, :, 42-38] # Banda 42
r700 = norm_cube[:, :, 52-38] # Banda 52
r740 = norm_cube[:, :, 62-38] # Banda 62
r780 = norm_cube[:, :, 75-38] # Banda 75

re_reflectance = (r670 + r780) / 2
denom_rep = r740 - r700
rep = np.full((rows, cols), -999, dtype='float32')
mask = (denom_rep != 0)
rep[mask] = 700 + 40 * ((re_reflectance[mask] - r700[mask]) / denom_rep[mask])
rep = np.where((rep > 680) & (rep < 760), rep, -999)

west = 500000.0 # Min Easting
north = 5200000.0 # Max Northing
pixel_size = 30.0 # Resolution in meters
transform = from_origin(west, north, pixel_size, pixel_size)
#transform = from_origin(680000, 4750000, 30, 30)

crs = 'EPSG:32632'

# 6. Scrittura GeoTIFF
with rasterio.open(
output_tiff, 'w',
driver='GTiff',
height=rows, width=cols,
count=1, dtype='float32',
crs=crs,
transform=transform,
nodata=-999
) as dst:
dst.write(rep, 1)

print(f"Completato! File salvato: {output_tiff}")


mercoledì 4 marzo 2026

Aster Silica Index

Non ho mai lavorato in termico..tempo di studiarlo

 


 

Il telerilevamento termico permette di distinguere tra i vari minerali silicati lavorando sulla posizione spettrale del legame Si-O...piu' ci sono legami Si-O maggiore e' lo spostamento della firma verso il blu

Il problema con i dati termici e' che la correzione atmosferica deve essere rigorosa. Inoltre la radianza e' data da due contributi ovvero dall'emissivita' e dalla funzione di Planck relativa alla temperatura..per il telerilevamento e' di interesse solo la 

Il dato completamente preprocessato e gia' pronto per le elaborazioni e' il livello AST05

I dati scaricati Eartdata sono distribuiti in geotiff separati per banda. Per fare lo stacking su Esa Snap tramite Raster/Geometric/Collocation

I nomi dei geotiff sono del tipo AST_05_00410242025195203_20251124071745_SRE_TIR_B10 

Si devono poi aggiustare le wavelength che sono

B10 = 8300 nm
B11 = 8650 nm
B12 = 9100 nm
B13 = 10600 nm
B14 = 11400 nm 

I dati sono  quindi pronti per calcolare SI (indice siliceo)

SI = (B11xB11)/(B10xB12)

 


lunedì 2 marzo 2026

C2RCC Sentinel 2 Esa Snap

Per processare le immagini Sentinel 2 su acqua per la rimozione atmosferica si puo' usare, oltre a sen2water, anche C2RCC (Case 2 Regional CoastColour)


 

Si parte da un prodotto L1C ed in modo preliminare si deve otterenere la stessa risoluzione spaziale tra tutte le bande con Raster/Geometric/Resampling

Successivamente si usa Optical/Thematic Water Processing/C2RCC Processor/S2-MSI 

La risposta del modello sono numerose bande

RTOARadiometricoRiflettanza top-of-atmosphere
RHOWRadiometricoRiflettanza emergente dall’acqua
RHOWNRadiometricoRiflettanza normalizzata
CONCBiochimicoConcentrazioni (clorofilla, TSM materia sospesa totale, CDOM materia organica disciolta)
IOPFisicoProprietà ottiche intrinseche
KDFisicoAttenuazione verticale della luce
UNCQualitàIncertezza del modello

 Per gli indici spettrali e' conveniente usare RHOWN

Casio E-SF400

Forse il pezzo piu' esotico del mio piccolo museo dell'informatica. Casio E-SF400 in versione giapponese, un PDA a cavallo tra gli anni 80 e gli anni 90

Ci sono poche informazioni a giro su internet tra cui questo manuale

https://www.manualshelf.com/manual/casio/e-sf400/user-manual-e-sf99-200-300-400-wc-part-1-simplified-chinese/page-1.html 

di fatto e' un vocabolario inglese/cinese/giapponese 






domenica 1 marzo 2026

Kernel Panic QrCode

 In tanti anni ho visto qualche kernel panic, ma in questo formato non mi era mai successo

 


 la cosa curiosa che al riavvio successivo nessun problema

Spectralunmixing

Per processare le immagini Emit ed ottenere il prodotto L2B e' stato utilizzato il software di spectral unmixing SpectralUnmixing.jl  

Il software usa il linguaggio Julia che si installa tramite 

curl -fsSL https://install.julialang.org | sh

 Dopo si clona il repository

git clone  https://github.com/emit-sds/SpectralUnmixing.jl

julia

si preme il tasto parentesi quadrata chiusa il prompt si modifica da julia in pkg

addSpectralUnmixing

si esce con CTRL+C

using SpectralUnmixing

CLI.install()

si esce con CTRL+D 

 


 

Nella cartella data sono presenti dati di test per il software

nel file csv ci sono le firme spettrali degli endmeber (nome classe e riflettanza), ed una immagine in formato Envi

Per lanciare l'unmixing si usa  

cd data

julia --project=/home/luca/SpectralUnmixing.jl /home/luca/.julia/bin/unmix.jl   emit20250324t221005_jpl_unmix_ex  basic_endmember_library.csv  Class output_test --mode sma-best --n_mc 30 

--normalization brightness

 

n_mc indica il numero di boostraping con il metodo Montecarlo 

gli endmember sono Soil, PV (vegetazione fotosintetica),NPV (vegetazione non fotosintetica)


 

Questo l'output 

 ┌ Info: Unmixing was processed on: HW27747
└ @ Main /home/luca/.julia/bin/unmix.jl:177
┌ Info: Reflectance file processed: emit20250324t221005_jpl_unmix_ex
└ @ Main /home/luca/.julia/bin/unmix.jl:178
┌ Info: Arguments: Dict{String, Any}("optimizer" => "bvls", "write_complete_fractions" => true, "mode" => "sma-best", "reflectance_uncertainty_file" => "", "combination_type" => "class-even", "log_file" => nothing, "normalization" => "none", "spectral_starting_column" => 2, "endmember_file" => "basic_endmember_library.csv", "truncate_end_columns" => 0, "refl_scale" => 1.0, "reflectance_file" => "emit20250324t221005_jpl_unmix_ex", "endmember_class_header" => "Class", "n_mc" => 30, "endmember_classes" => [""], "refl_nodata" => -9999.0, "output_file_base" => "output_test", "num_endmembers" => [3], "start_line" => 1, "end_line" => -1, "wavelength_ignore_regions" => [0.0, 440.0, 1310.0, 1490.0, 1770.0, 2050.0, 2440.0, 2880.0], "max_combinations" => -1)
└ @ Main /home/luca/.julia/bin/unmix.jl:179
┌ Info: Ignoring wavelength regions: Any[[0.0, 440.0], [1310.0, 1490.0], [1770.0, 2050.0], [2440.0, 2880.0]]
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/EndmemberLibrary.jl:191
┌ Info: Running from lines: 1 - 10
└ @ Main /home/luca/.julia/bin/unmix.jl:211
AbstractString[InlineStrings.String7("SOIL"), InlineStrings.String7("PV"), InlineStrings.String7("NPV")]
AbstractString[InlineStrings.String7("SOIL"), InlineStrings.String7("PV"), InlineStrings.String7("NPV"), "Brightness"]
┌ Info: Output Image Size (x,y,b): 10, 10, [4, 4, 6].
│         Creating output fractional cover dataset.
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/Datasets.jl:77
┌ Info: Output Image Size (x,y,b): 10, 10, [4, 4, 6].
│         Creating output fractional cover dataset.
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/Datasets.jl:77
┌ Info: Output Image Size (x,y,b): 10, 10, [4, 4, 6].
│         Creating output fractional cover dataset.
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/Datasets.jl:77
┌ Info: Unmix output files: ["output_test_fractional_cover", "output_test_fractional_cover_uncertainty", "output_test_complete_fractions"]
└ @ Main /home/luca/.julia/bin/unmix.jl:267
┌ Info: total number of workers available: 1
└ @ Main /home/luca/.julia/bin/unmix.jl:268
┌ Info: Line 2 run in 0.0142 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 3 run in 0.0138 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 4 run in 0.0138 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 5 run in 0.0138 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 6 run in 0.0155 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 7 run in 0.0144 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 8 run in 0.0207 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 9 run in 0.0181 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
┌ Info: Line 10 run in 0.0137 seconds
└ @ SpectralUnmixing /home/luca/SpectralUnmixing.jl/src/SpectralUnmixing.jl:542
 17.617387 seconds (18.76 M allocations: 1.104 GiB, 32.59% gc time, 66.76% compilation time)


i file di output saranno file hdr (complete_fractions, fractional_cover, fractional_cover_uncertainty)

complete_fractions: indica la percentuale  della classe contenuta nel pixel

fractional_cover : se complete_fraction indica tipo il 60%, fractional_cover indica la divisione percentuale delle frazioni mineralogiche (Ematite, Goethite....). Se la complete_fractions della categoria Soil e' inferiore al 20% e' inutile questo successivo raffinamento

Le bande in fractional_cover individuano 

    Fraction of Endmember 1
    Fraction of Endmember 2
    Fraction of Endmember 3
    Possibly Shade (if included)
    Possibly Residual
    Possibly RMSE

 

fractional_cover_uncertainty: indica la qualita' del dato...valori bassi unmixing migliore 

Emit L3 ASA

Il prodotto Emit L3 ASA (scaricabile da qui) corrisponde all'unmixing mineralogico dei dati ipespettrali di Emit. La copertura e' a livello mondiale tra le latitudini 55N/-54.5S ed una risoluzione spaziale di mezzo grado decimale (circa 55 km) con specializzazione su suoli aridi (i dati sono mascherati per la vegetazione)

Vengono calcolate 10 categorie mineralogiche  

Il prodotto e' nato per polveri e non per suoli. Per indagini mineralogiche di suoli e' piu' affidale il prodotto L2B a cui pero' si deve effettuare in proprio l'unmixing spettrale 

  


 

Red Edge Position Enmap

In " Fundamental of geological and environmental remote sensing R.K.Vincent, Prentice Hall (1997) " cap 7 viene indicato che lo sp...