Suppression de la visualisation Texture GLCM

- Suppression de generate_texture() de visualizations.py
- Suppression de l'entrée 'texture' de VIZ_STEPS et COLORMAPS
- Suppression du test TestTexture
- Mise à jour README (19 → 18 visualisations)
- Mise à jour CLAUDE.md (17 → 16 fonctions generate_*)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jacquin Antoine
2026-05-10 03:30:07 +02:00
parent bc92689acc
commit f03b3873bd
6 changed files with 8 additions and 107 deletions

View File

@ -676,88 +676,6 @@ def generate_wavelet(dem_file, basename, vis_dir, resolution):
return None
# ============================================================
# Texture GLCM
# ============================================================
def generate_texture(dem_file, basename, vis_dir, resolution):
"""GLCM-inspired texture analysis — contrast, entropy, homogeneity (GPU-accelerated)."""
gpu_tag = " [GPU]" if HAS_GPU else ""
logger.info(f" → Texture GLCM{gpu_tag}...")
t0 = time.time()
output = vis_dir / f"{basename}_texture.tif"
try:
dem_np, transform, crs = _read_dem(dem_file)
# Hillshade — compute on CPU to avoid holding DEM on GPU during texture
gy, gx = np.gradient(dem_np, resolution)
slope = np.arctan(np.sqrt(gx**2 + gy**2))
alt_rad = np.radians(45)
az_rad = np.radians(315)
aspect = np.arctan2(gy, gx)
shading = (np.sin(alt_rad) * np.cos(slope) +
np.cos(alt_rad) * np.sin(slope) *
np.cos(az_rad - aspect))
hillshade = np.clip(shading, 0, 1)
valid = np.asarray(hillshade[~np.isnan(hillshade)])
if len(valid) == 0:
raise ValueError("No valid data for texture analysis")
lo, hi = np.percentile(valid, (1, 99))
img = np.clip((hillshade - lo) / max(hi - lo, 0.001), 0, 1)
del hillshade, shading, slope, aspect, gy, gx # free memory
window = int(5 / resolution)
if window % 2 == 0:
window += 1
# Contrast (variance) — GPU-accelerated
img_gpu = to_gpu(img.astype(np.float32))
local_mean = xp_uniform_filter(img_gpu, size=window)
local_mean_sq = xp_uniform_filter(img_gpu * img_gpu, size=window)
contrast = to_cpu(local_mean_sq - local_mean * local_mean).astype(np.float64)
del img_gpu, local_mean, local_mean_sq # free GPU memory
# Entropy — compute bin-by-bin to avoid large 3D allocation
n_bins = 16
img_clean = np.nan_to_num(img, nan=0.0)
img_uint8 = np.clip(img_clean * 255, 0, 255).astype(np.uint8)
quantized = (img_uint8 // (256 // n_bins)).astype(np.int32)
entropy = np.zeros_like(img, dtype=np.float64)
win_area = max(window * window, 1)
for b in range(n_bins):
plane = (quantized == b).astype(np.float32)
plane_gpu = to_gpu(plane)
prob_plane = to_cpu(xp_uniform_filter(plane_gpu, size=window))
prob_val = prob_plane / win_area
prob_val = np.clip(prob_val, 1e-10, None)
entropy -= prob_val * np.log2(prob_val)
del plane_gpu # free GPU memory per bin
del quantized, img_uint8 # free CPU memory
# Homogeneity — 1 / (1 + variance)
homogeneity = 1.0 / (1.0 + contrast)
def norm(arr):
valid_arr = arr[~np.isnan(arr)]
if len(valid_arr) == 0:
return arr
std_val = max(np.std(valid_arr), 0.01)
return (arr - np.mean(valid_arr)) / std_val
texture_combined = 0.4 * norm(contrast) + 0.4 * norm(entropy) - 0.2 * norm(homogeneity)
_save_tif(output, texture_combined, transform, crs)
logger.info(f" ✓ Texture terminée ({time.time()-t0:.1f}s){gpu_tag}")
return output
except Exception as e:
logger.error(f" ✗ Erreur texture GLCM: {e}", exc_info=True)
return None
# ============================================================
# Flow accumulation
# ============================================================