""" Tests unitaires pour vision_utils.py """ import numpy as np import sys from pathlib import Path # Ajouter le répertoire parent au path sys.path.insert(0, str(Path(__file__).parent.parent.parent)) from geniusia2.core.utils.vision_utils import VisionUtils from geniusia2.core.models import Detection def test_initialization(): """Test l'initialisation de VisionUtils""" print("Test 1: Initialisation...") vision = VisionUtils() assert vision.primary_model == "owl-v2" assert len(vision.fallback_order) == 3 assert "owl-v2" in vision.fallback_order assert "dino" in vision.fallback_order assert "yolo" in vision.fallback_order print("✓ Initialisation OK") def test_filter_detections(): """Test le filtrage des détections""" print("\nTest 2: Filtrage des détections...") vision = VisionUtils() detections = [ Detection( label="button1", confidence=0.95, bbox=(100, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ), Detection( label="button2", confidence=0.25, bbox=(200, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ), Detection( label="button3", confidence=0.75, bbox=(300, 100, 50, 30), embedding=np.random.rand(512), model_source="dino" ), ] # Filtrer avec seuil de 0.5 filtered = vision.filter_detections(detections, min_confidence=0.5) assert len(filtered) == 2 assert all(d.confidence >= 0.5 for d in filtered) # Vérifier le tri par confiance assert filtered[0].confidence >= filtered[1].confidence print("✓ Filtrage OK") def test_select_best_detection(): """Test la sélection de la meilleure détection""" print("\nTest 3: Sélection de la meilleure détection...") vision = VisionUtils() detections = [ Detection( label="button1", confidence=0.75, bbox=(100, 100, 50, 30), embedding=np.random.rand(512), model_source="dino" ), Detection( label="button2", confidence=0.85, bbox=(200, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" # Modèle principal ), ] # Sans contexte, devrait favoriser owl-v2 avec bonus best = vision.select_best_detection(detections) assert best is not None assert best.model_source == "owl-v2" # Avec contexte de position précédente context = {"previous_bbox": (95, 95, 50, 30)} # Proche de button1 best_with_context = vision.select_best_detection(detections, context) assert best_with_context is not None print("✓ Sélection OK") def test_merge_overlapping_detections(): """Test la fusion des détections chevauchantes""" print("\nTest 4: Fusion des détections chevauchantes...") vision = VisionUtils() # Créer des détections qui se chevauchent detections = [ Detection( label="button", confidence=0.95, bbox=(100, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ), Detection( label="button", confidence=0.85, bbox=(105, 102, 48, 28), # Légèrement décalé, fort chevauchement embedding=np.random.rand(512), model_source="dino" ), Detection( label="button", confidence=0.70, bbox=(300, 100, 50, 30), # Pas de chevauchement embedding=np.random.rand(512), model_source="yolo" ), ] merged = vision.merge_overlapping_detections(detections, iou_threshold=0.5) # Devrait fusionner les 2 premières détections assert len(merged) == 2 # La meilleure confiance devrait être conservée assert merged[0].confidence == 0.95 print("✓ Fusion OK") def test_get_detection_statistics(): """Test le calcul des statistiques""" print("\nTest 5: Statistiques des détections...") vision = VisionUtils() detections = [ Detection( label="button1", confidence=0.95, bbox=(100, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ), Detection( label="button2", confidence=0.85, bbox=(200, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ), Detection( label="button3", confidence=0.75, bbox=(300, 100, 50, 30), embedding=np.random.rand(512), model_source="dino" ), ] stats = vision.get_detection_statistics(detections) assert stats["count"] == 3 assert stats["max_confidence"] == 0.95 assert stats["min_confidence"] == 0.75 assert abs(stats["avg_confidence"] - 0.85) < 0.01 assert "owl-v2" in stats["models_used"] assert "dino" in stats["models_used"] assert stats["model_distribution"]["owl-v2"] == 2 assert stats["model_distribution"]["dino"] == 1 print("✓ Statistiques OK") def test_empty_detections(): """Test le comportement avec des listes vides""" print("\nTest 6: Gestion des listes vides...") vision = VisionUtils() # Liste vide empty = [] # Filtrage filtered = vision.filter_detections(empty) assert len(filtered) == 0 # Sélection best = vision.select_best_detection(empty) assert best is None # Fusion merged = vision.merge_overlapping_detections(empty) assert len(merged) == 0 # Statistiques stats = vision.get_detection_statistics(empty) assert stats["count"] == 0 assert stats["avg_confidence"] == 0.0 print("✓ Gestion des listes vides OK") def test_single_detection(): """Test le comportement avec une seule détection""" print("\nTest 7: Gestion d'une seule détection...") vision = VisionUtils() single = [ Detection( label="button", confidence=0.85, bbox=(100, 100, 50, 30), embedding=np.random.rand(512), model_source="owl-v2" ) ] # Sélection best = vision.select_best_detection(single) assert best is not None assert best.label == "button" # Fusion merged = vision.merge_overlapping_detections(single) assert len(merged) == 1 print("✓ Gestion d'une seule détection OK") def run_all_tests(): """Exécute tous les tests""" print("=" * 60) print("Tests unitaires de VisionUtils") print("=" * 60) try: test_initialization() test_filter_detections() test_select_best_detection() test_merge_overlapping_detections() test_get_detection_statistics() test_empty_detections() test_single_detection() print("\n" + "=" * 60) print("✓ TOUS LES TESTS RÉUSSIS!") print("=" * 60) return True except AssertionError as e: print(f"\n✗ ÉCHEC DU TEST: {e}") return False except Exception as e: print(f"\n✗ ERREUR: {e}") import traceback traceback.print_exc() return False if __name__ == "__main__": success = run_all_tests() sys.exit(0 if success else 1)