website color mapping update

This commit is contained in:
Grégoire Mureau 2025-09-04 10:15:09 +02:00
parent ce963b2cf7
commit 9186bfd1c5
3 changed files with 113 additions and 43 deletions

View file

@ -171,9 +171,10 @@ def initialize_models():
print("🔄 Configuration de MLflow...")
configure_mlflow()
print("🔄 Chargement de la configuration Cityscapes...")
mapping_config = load_cityscapes_config(CITYSCAPES_CONFIG_PATH, verbose=False)
print("✅ Configuration Cityscapes chargée")
print("🔄 Chargement de la configuration Cityscapes avec couleurs WCAG...")
mapping_config = load_cityscapes_config(CITYSCAPES_CONFIG_PATH, verbose=False, use_wcag_colors=True)
print("✅ Configuration Cityscapes chargée avec couleurs WCAG")
print("🔄 Chargement du meilleur modèle...")
best_model, best_run_id, best_encoder_name, best_img_size = load_model(
@ -296,28 +297,34 @@ def get_models_info():
if best_model is None or second_best_model is None:
raise HTTPException(status_code=503, detail="Models not loaded")
# Couleurs accessibles pour les classes
accessible_class_colors = [
[0, 102, 204], # primary_blue
[204, 0, 0], # primary_red
[0, 102, 0], # primary_green
[204, 102, 0], # primary_orange
[102, 51, 153], # secondary_purple
[0, 102, 102], # secondary_teal
[51, 51, 51], # neutral_dark
[102, 102, 102] # neutral_medium
# NOUVELLE RÉPARTITION DES COULEURS selon votre mapping final
wcag_accessible_colors = [
[102, 102, 102], # Flat: neutral_medium (gris moyen pour routes/trottoirs)
[204, 0, 0], # Human: primary_red (rouge pour piétons/cyclistes)
[102, 51, 153], # Vehicle: secondary_purple (violet pour véhicules)
[204, 102, 0], # Construction: primary_orange (orange pour bâtiments)
[0, 102, 102], # Object: secondary_teal (teal pour objets/signalétique)
[0, 102, 0], # Nature: primary_green (vert pour végétation)
[0, 102, 204], # Sky: primary_blue (bleu pour ciel)
[51, 51, 51] # Void: neutral_dark (gris foncé pour zones non-définies)
]
# Mettre à jour la configuration avec les nouvelles couleurs
if mapping_config:
mapping_config['group_colors'] = np.array(wcag_accessible_colors, dtype=np.uint8)
return {
"best_model": best_model_info,
"second_best_model": second_best_model_info,
"num_classes": mapping_config['num_classes'],
"class_names": mapping_config['group_names'],
"class_colors": accessible_class_colors,
"class_colors": wcag_accessible_colors,
"accessibility_info": get_accessibility_info(),
"preprocessing_resolution": best_model_info.get("input_size", (512, 512)) # Ajout pour clarté
"preprocessing_resolution": best_model_info.get("input_size", (512, 512))
}
@app.get("/dataset-info")
def get_dataset_info():
"""Retourne les informations sur le dataset"""

View file

@ -30,18 +30,37 @@ st.set_page_config(
# Palettes de couleurs conformes WCAG AA (ratio contraste ≥ 3:1)
WCAG_ACCESSIBLE_COLORS = {
'primary_blue': '#0066CC', # Contraste 4.5:1 avec blanc
'primary_red': '#CC0000', # Contraste 5.7:1 avec blanc
'primary_green': '#006600', # Contraste 4.8:1 avec blanc
'primary_orange': '#CC6600', # Contraste 4.2:1 avec blanc
'secondary_purple': '#663399', # Contraste 4.1:1 avec blanc
'secondary_teal': '#006666', # Contraste 4.4:1 avec blanc
'neutral_dark': '#333333', # Contraste 12.6:1 avec blanc
'neutral_medium': '#666666', # Contraste 5.7:1 avec blanc
'primary_blue': '#0066CC', # [0, 102, 204]
'primary_red': '#CC0000', # [204, 0, 0]
'primary_green': '#006600', # [0, 102, 0]
'primary_orange': '#CC6600', # [204, 102, 0]
'secondary_purple': '#663399', # [102, 51, 153]
'secondary_teal': '#006666', # [0, 102, 102]
'neutral_dark': '#333333', # [51, 51, 51]
'neutral_medium': '#666666', # [102, 102, 102]
'neutral_light': '#CCCCCC', # Pour éléments désactivés
'background_alt': '#F5F5F5' # Fond alternatif accessible
}
# Convertir hex vers RGB
def hex_to_rgb(hex_color):
"""Convertit une couleur hex en tuple RGB"""
hex_color = hex_color.lstrip('#')
return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
# Couleurs RGB pour les masques (dans le même ordre que les classes)
WCAG_RGB_COLORS = [
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['neutral_medium']), # Flat: gris moyen [102, 102, 102]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['primary_red']), # Human: rouge [204, 0, 0]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['secondary_purple']), # Vehicle: violet [102, 51, 153]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['primary_orange']), # Construction: orange [204, 102, 0]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['secondary_teal']), # Object: teal [0, 102, 102]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['primary_green']), # Nature: vert [0, 102, 0]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['primary_blue']), # Sky: bleu [0, 102, 204]
hex_to_rgb(WCAG_ACCESSIBLE_COLORS['neutral_dark']) # Void: gris foncé [51, 51, 51]
]
# Motifs pour différencier sans couleur uniquement
ACCESSIBILITY_PATTERNS = {
'solid': None,
@ -598,14 +617,14 @@ def display_model_stats_chart(stats, models_info, title):
# Couleurs accessibles WCAG
accessible_colors = [
WCAG_ACCESSIBLE_COLORS['primary_blue'],
WCAG_ACCESSIBLE_COLORS['primary_red'],
WCAG_ACCESSIBLE_COLORS['primary_green'],
WCAG_ACCESSIBLE_COLORS['primary_orange'],
WCAG_ACCESSIBLE_COLORS['secondary_purple'],
WCAG_ACCESSIBLE_COLORS['secondary_teal'],
WCAG_ACCESSIBLE_COLORS['neutral_dark'],
WCAG_ACCESSIBLE_COLORS['neutral_medium']
WCAG_ACCESSIBLE_COLORS['neutral_medium'], # Flat: gris moyen
WCAG_ACCESSIBLE_COLORS['primary_red'], # Human: rouge
WCAG_ACCESSIBLE_COLORS['secondary_purple'], # Vehicle: violet
WCAG_ACCESSIBLE_COLORS['primary_orange'], # Construction: orange
WCAG_ACCESSIBLE_COLORS['secondary_teal'], # Object: teal
WCAG_ACCESSIBLE_COLORS['primary_green'], # Nature: vert
WCAG_ACCESSIBLE_COLORS['primary_blue'], # Sky: bleu
WCAG_ACCESSIBLE_COLORS['neutral_dark'] # Void: gris foncé
]
colors = accessible_colors[:len(ordered_class_names)]

View file

@ -20,10 +20,47 @@ import albumentations as A
from albumentations.pytorch import ToTensorV2
def load_cityscapes_config(config_path="../cityscapes_config.json", verbose=True):
def update_colors_to_wcag(mapping_config):
"""
Met à jour les couleurs dans mapping_config pour utiliser les couleurs WCAG accessibles
avec redistribution sémantique intuitive finale
"""
# Redistribution sémantique finale :
# Flat → gris moyen, Human → rouge, Vehicle → violet, Construction → orange,
# Object → teal, Nature → vert, Sky → bleu, Void → gris foncé
wcag_colors = np.array([
[102, 102, 102], # Flat: gris moyen (routes, trottoirs)
[204, 0, 0], # Human: rouge (piétons, cyclistes)
[102, 51, 153], # Vehicle: violet (véhicules)
[204, 102, 0], # Construction: orange (bâtiments)
[0, 102, 102], # Object: teal (objets, signalétique)
[0, 102, 0], # Nature: vert (végétation)
[0, 102, 204], # Sky: bleu (ciel)
[51, 51, 51] # Void: gris foncé (zones non-définies)
], dtype=np.uint8)
# S'assurer qu'on a assez de couleurs pour le nombre de classes
num_classes = mapping_config['num_classes']
if len(wcag_colors) < num_classes:
print(f"⚠️ Attention: {num_classes} classes mais seulement {len(wcag_colors)} couleurs WCAG disponibles")
# Compléter avec les couleurs originales si nécessaire
original_colors = mapping_config['group_colors']
while len(wcag_colors) < num_classes:
wcag_colors = np.vstack([wcag_colors, original_colors[len(wcag_colors):len(wcag_colors)+1]])
mapping_config['group_colors'] = wcag_colors[:num_classes]
print(f"✅ Couleurs mises à jour vers WCAG pour {num_classes} classes")
return mapping_config
def load_cityscapes_config(config_path="../cityscapes_config.json", verbose=True, use_wcag_colors=False):
"""
Charge la configuration Cityscapes depuis un fichier JSON.
INCHANGÉ - Compatible PyTorch
Args:
config_path: Chemin vers le fichier de configuration
verbose: Affichage détaillé
use_wcag_colors: Utiliser les couleurs WCAG accessibles
"""
with open(config_path, "r", encoding="utf-8") as f:
config = json.load(f)
@ -40,6 +77,20 @@ def load_cityscapes_config(config_path="../cityscapes_config.json", verbose=True
num_classes = len(group_names)
mapping_config = {
"class_groups": class_groups,
"cityscapes_mapping": cityscapes_mapping,
"id_to_label": id_to_label,
"group_colors": group_colors,
"group_names": group_names,
"id_to_group": id_to_group,
"num_classes": num_classes
}
# Appliquer les couleurs WCAG si demandé
if use_wcag_colors:
mapping_config = update_colors_to_wcag(mapping_config)
if verbose:
print("== Groupes de classes Cityscapes ==")
for group, classes in class_groups.items():
@ -52,20 +103,13 @@ def load_cityscapes_config(config_path="../cityscapes_config.json", verbose=True
print(f" ID {id_:2d} ('{label}') → groupe '{group_names[group_id]}' ({group_id})")
print("\n== Liste des groupes et couleurs associées ==")
for i, (name, color) in enumerate(zip(group_names, group_colors)):
for i, (name, color) in enumerate(zip(group_names, mapping_config['group_colors'])):
print(f" Groupe {i}: {name} - Couleur RGB : {color}")
print(f"\nNombre total de groupes/classes : {num_classes}")
return {
"class_groups": class_groups,
"cityscapes_mapping": cityscapes_mapping,
"id_to_label": id_to_label,
"group_colors": group_colors,
"group_names": group_names,
"id_to_group": id_to_group,
"num_classes": num_classes
}
return mapping_config
def map_mask_ids(mask, id_to_group_mapping):
"""