giovedì 12 marzo 2026

QGis e PythonPath

Ultimamente ho incasinato la Debian box e mi compare questo errore aprendo QGis...dopo funziona ma non disponibili i plugin 

la soluzione e' settare in modo esplicito la PythoPath

 

PYTHONPATH=/usr/lib/python3/dist-packages:$PYTHONPATH 

qgis

mercoledì 11 marzo 2026

Campionamento rifiuti in spiaggia

Un tentativo di quantificare rifiuti su una spiaggia toscana 

L'idea e'

1) fotografare

2) incollare le immagini (possibilmente georiferite)

3) tagliare in quadrati di 1mx1m

4) istruire una rete neurale con Yolo 8 su un sottoinsieme dei quadrati al punto 3 

 

Le immagini di partenza sono di questo tipo (si avrei dovuto portarmi uno stick per non fotografarmi di continuo i piedi), in sequenza scattate in automatico ogni secondo 


 

Il primo dataset sono immagini da drone 

Le immagini sono state incollate (stitching) con WebOdm 

Come si legge il GCD e' di 0.92..io voglio tagliare il geotiff in quadrati di 1x1 tramite GDAL...per ottenere il valore del parametro ps calcolo 100 cm /0.92 cm (GCD) ed ottendo 109 (non vengono accettati valori float)

gdal_retile.py -ps 109 109 -targetDir ./ritagli_drone/ ortophoto_drone.tif  

Usando invece foto fatte a mano dal cellulare (quindi altezza indicativa di 140 cm) si ha un GCD di  0.12

 


gdal_retile.py -ps 833 833 -targetDir ./ritagli_samsung/ ortophoto_samsung.tif

una volta effettuato il taglio si hanno immagini di questo tipo (la distorsione e' derivante dall'algoritmo di ODM)

 

che devono essere classificate per istruire la rete neurale
 

Di solito uso labelImg ma ho visto che nella versione nuova di Debian crasha a causa delle Qt6...intanto trasformiamo i tiff in jpg perche' labelimg non supporta tiff

 

 mogrify -format jpg -quality 90 -colorspace sRGB -flatten *.tif

 e poi lanciamo questo docker container per non impazzire con l'installazione

docker run -ti --rm -e DISPLAY=$DISPLAY --device=/dev/video0:/dev/video0  -v /tmp/.X11-unix:/tmp/.X11-unix   -v /home/luca/:/home/luca -w /home/luca         ludwigprager/labelimg:1
 

dopo aver definito le classi e gli oggetti all'interno delle immagini si passa ad addestrare il modello facendo un retrain di Yolo

i dati sono nel folder /home/luca/images/1, al di sotto ci sono i folders ./train/images,./train/labels,./val/images,./val/labels


 

il file data.yaml deve essere in /home/luca/images/1

-------------------- 

train: /ultralytics/my_data/train/images
val: /ultralytics/my_data/val/images

nc: 3
names: ['waste', 'alga', 'wood']

-------------------- 

 ancora la cosa piu' semplice e' un docker per addestrare la rete (size 833 e' la dimensione in pixels di ogni mattonella di 1 m) 

docker run -it --rm \
  --ipc=host \
  -v "/home/luca/images/1":/ultralytics/my_data \
  ultralytics/ultralytics:latest-cpu \
  yolo train \
  model=yolov8n.pt \
  data=/ultralytics/my_data/data.yaml \
  epochs=50 \
  imgsz=833 \
  device=cpu \
  project=/ultralytics/my_data/runs

 

i risultati sono pessimi principalmente a causa del dataset ristretto ma dal punto di vista software tutto ha funzionato




 


 






 se, dopo aver fatto il modello, si vuole fare inferenza questo e' il comando

docker run -it --rm \
  -v "/home/luca/images/1":/ultralytics/my_data \
  ultralytics/ultralytics:latest-cpu \
  yolo predict \
  model=/ultralytics/my_data/runs/train/weights/best.pt \
  source=/ultralytics/my_data/train/images/ortophoto_samsung_04_03.jpg \
  project=/ultralytics/my_data/predictions \
  save=True

 

 


venerdì 6 marzo 2026

NRDE

 

 

 

 

Questa e' una estensione di questo post usando come parametro indice NRDE al posto di NDVI. Questo indice puo'essere calcolato per Sentinel 2 ma non per Landsat e per questo motivo la serie storica e' ridotta ad un decennio 

 

NRDE = (NIR-RedEdge)/(Nir+RedEdge) 

// 1. Coordinate e Geometria
var lon = 10.926468160041452;
var lat = 43.01919548868449;
var poi = ee.Geometry.Point([lon, lat]);

// 2. Funzione di pre-elaborazione per Sentinel-2
function preprocessSentinel2(image) {
  var qa = image.select('QA60');

  // Maschera per nuvole e cirri
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  // Scaling (Sentinel-2 Surface Reflectance)
  var opticalBands = image.divide(10000);
  
  // Calcolo NDRE 
  // NIR = B8, Red Edge = B5 (prima banda red-edge di Sentinel-2)
  var ndre = opticalBands.normalizedDifference(['B8', 'B5']).rename('NDRE');
  
  return image.addBands(ndre).updateMask(mask);
}

// 3. Caricamento Collezione Sentinel-2 (Disponibile dal 2015/2017)
var s2Col = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
  .filterBounds(poi)
  .filterDate('2017-01-01', '2026-01-01') // Sentinel-2 SR data standard
  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
  .map(preprocessSentinel2);

// 4. Creazione del Grafico Temporale
var chart = ui.Chart.image.series({
  imageCollection: s2Col.select('NDRE'),
  region: poi,
  reducer: ee.Reducer.mean(),
  scale: 20, // Sentinel-2 Red Edge è a 20m
  xProperty: 'system:time_start'
})
.setOptions({
  title: 'Serie Storica NDRE: Sentinel-2 (2017-2026)',
  vAxis: {title: 'NDRE', viewWindow: {min: -0.1, max: 1}},
  hAxis: {title: 'Anno', format: 'YYYY'},
  lineWidth: 1,
  pointSize: 2,
  trendlines: {0: {color: 'blue', lineWidth: 1, opacity: 0.7}},
  series: {
    0: {color: '006400'} // Verde scuro
  }
});

// 5. Visualizzazione
print(chart);
Map.centerObject(poi, 13);
Map.addLayer(poi, {color: 'red'}, 'Sito di analisi'); 

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 






Indici Ensomap

Un breve riassunto degli indici utilizzati in Ensomap all'interno del plugin Enmap toolbox di QGis   Carbonate 1) assorbimento dopo rim...