Download test-api.py from 2nzi/PnLCalib: direct link, hf CLI and curl.
- Browser
- Download file 13.4 kB
-
https://huggingface.co/spaces/2nzi/PnLCalib/resolve/main/test-api.py
- Command line
-
hf download hf://spaces/2nzi/PnLCalib/test-api.py
-
curl -L -o test-api.py https://huggingface.co/spaces/2nzi/PnLCalib/resolve/main/test-api.py
13.4 kB
| import requests | |
| import json | |
| from pathlib import Path | |
| # Configuration | |
| API_URL = "http://localhost:8000" | |
| IMAGE_PATH = "examples/input/cam3.jpg" # Adaptez selon votre structure | |
| # IMAGE_PATH = "examples/input/FootDrone.jpg" # Adaptez selon votre structure | |
| VIDEO_PATH = "examples/input/FootDrone.mp4" # Adaptez selon votre structure | |
| # Données d'exemple (votre cam3_line_dict) | |
| cam3_line_dict = { | |
| "Big rect. right top": [ | |
| {"x": 1342.8861505076343, "y": 1076.997434976179}, | |
| {"x": 1484.7446330310781, "y": 906.3705391217808} | |
| ], | |
| "Big rect. right main": [ | |
| {"x": 1484.7446330310781, "y": 906.3705391217808}, | |
| {"x": 1049.6210183678218, "y": 748.0287797688992}, | |
| {"x": 828.6491513601493, "y": 668.8579000924583}, | |
| {"x": 349.8767728435256, "y": 500.9610345717304}, | |
| {"x": 32.736572890025556, "y": 397.21988189225624} | |
| ], | |
| "Big rect. right bottom": [ | |
| {"x": 32.736572890025556, "y": 397.21988189225624}, | |
| {"x": 0.3753980224568448, "y": 407.0286292126068} | |
| ], | |
| "Small rect. right top": [ | |
| {"x": 312.24913494809687, "y": 1075.6461846681693}, | |
| {"x": 426.66666666666663, "y": 999.9279904137233} | |
| ], | |
| "Small rect. right main": [ | |
| {"x": 426.66666666666663, "y": 999.9279904137233}, | |
| {"x": 0, "y": 769.079837198949} | |
| ], | |
| "Circle right": [ | |
| {"x": 828.6491513601493, "y": 668.8579000924583}, | |
| {"x": 821.7759602949911, "y": 612.2830792373484}, | |
| {"x": 782.8739995106773, "y": 564.5621490047902}, | |
| {"x": 722.6387053930304, "y": 529.3993583071158}, | |
| {"x": 623.5014504910696, "y": 503.02726528386006}, | |
| {"x": 494.24654853028534, "y": 492.980753655953}, | |
| {"x": 349.8767728435256, "y": 500.9610345717304} | |
| ], | |
| "Side line bottom": [ | |
| {"x": 2.0193824656299317, "y": 266.2605192109321}, | |
| {"x": 399.0443993689428, "y": 186.14824976426013}, | |
| {"x": 645.5533017804819, "y": 132.93313314748357}, | |
| {"x": 1001.1088573360372, "y": 53.39824942655338}, | |
| {"x": 1208.1676808654488, "y": 7.351737798646435} | |
| ], | |
| "Middle line": [ | |
| {"x": 645.5533017804819, "y": 132.93313314748357}, | |
| {"x": 1106.0585089650835, "y": 200.22939899146556}, | |
| {"x": 1580.7388158704541, "y": 269.8451725000601}, | |
| {"x": 1917.6527118636336, "y": 318.9857185061268} | |
| ], | |
| "Circle central": [ | |
| {"x": 1580.7388158704541, "y": 269.8451725000601}, | |
| {"x": 1580.7388158704541, "y": 269.8451725000601}, | |
| {"x": 1533.8366024891266, "y": 288.8643838246303}, | |
| {"x": 1441.810458698277, "y": 302.46903498742097}, | |
| {"x": 1316.3202626198458, "y": 304.5620582432349}, | |
| {"x": 1219.0653606590615, "y": 292.0039187083512}, | |
| {"x": 1135.4052299401073, "y": 274.2132210339326}, | |
| {"x": 1069.522876998931, "y": 237.5853140571884}, | |
| {"x": 1106.0585089650835, "y": 200.22939899146556}, | |
| {"x": 1139.5882364760548, "y": 189.4457791734675}, | |
| {"x": 1224.2941188289963, "y": 177.9341512664908}, | |
| {"x": 1314.2287593518718, "y": 174.79461638276985}, | |
| {"x": 1392.6601319008914, "y": 180.02717452230473}, | |
| {"x": 1465.8627462799764, "y": 190.49229080137454}, | |
| {"x": 1529.6535959531789, "y": 204.09694196416518}, | |
| {"x": 1581.9411776525253, "y": 230.2597326618396}, | |
| {"x": 1580.7388158704541, "y": 269.8451725000601} | |
| ], | |
| "Side line left": [ | |
| {"x": 1208.1676808654488, "y": 7.351737798646435}, | |
| {"x": 1401.9652021886754, "y": 20.565213248502545}, | |
| {"x": 1582.3573590514204, "y": 30.37625976013045}, | |
| {"x": 1679.416182580832, "y": 34.300678364781604}, | |
| {"x": 1824.5142217965183, "y": 41.23091697692868}, | |
| {"x": 1918.6318688553417, "y": 42.21202162809147} | |
| ], | |
| "Big rect. left bottom": [ | |
| {"x": 1401.9652021886754, "y": 20.565213248502545}, | |
| {"x": 1283.3377512082834, "y": 53.98527744204496} | |
| ], | |
| "Big rect. left main": [ | |
| {"x": 1283.3377512082834, "y": 53.98527744204496}, | |
| {"x": 1510.7887316004399, "y": 73.60737046530076}, | |
| {"x": 1808.8279472867146, "y": 94.21056813971936}, | |
| {"x": 1918.6318688553417, "y": 100.0971960466961} | |
| ], | |
| "Circle left": [ | |
| {"x": 1510.7887316004399, "y": 73.60737046530076}, | |
| {"x": 1548.0436335612244, "y": 86.36173093041702}, | |
| {"x": 1620.5926531690673, "y": 95.19167279088215}, | |
| {"x": 1681.3769668945574, "y": 97.15388209320773}, | |
| {"x": 1746.0828492474989, "y": 100.0971960466961}, | |
| {"x": 1808.8279472867146, "y": 94.21056813971936} | |
| ], | |
| "Small rect. left bottom": [ | |
| {"x": 1550.9848100318127, "y": 42.21202162809147}, | |
| {"x": 1582.3573590514204, "y": 30.37625976013045} | |
| ], | |
| "Small rect. left main": [ | |
| {"x": 1550.9848100318127, "y": 42.21202162809147}, | |
| {"x": 1918.418689198772, "y": 60.49417894940041} | |
| ] | |
| } | |
| def test_health(): | |
| """Test du health check""" | |
| try: | |
| response = requests.get(f"{API_URL}/health") | |
| print(f"Health check: {response.status_code} - {response.json()}") | |
| return response.status_code == 200 | |
| except requests.exceptions.ConnectionError: | |
| print("❌ Impossible de se connecter à l'API. Vérifiez qu'elle est démarrée.") | |
| return False | |
| except Exception as e: | |
| print(f"❌ Erreur health check: {e}") | |
| return False | |
| def test_calibration(): | |
| """Test de l'API de calibration avec lignes manuelles""" | |
| if not Path(IMAGE_PATH).exists(): | |
| print(f"❌ Image non trouvée: {IMAGE_PATH}") | |
| print(f" Chemin absolu: {Path(IMAGE_PATH).absolute()}") | |
| return | |
| print(f"📁 Test avec l'image: {IMAGE_PATH}") | |
| print(f" Taille du fichier: {Path(IMAGE_PATH).stat().st_size} bytes") | |
| try: | |
| with open(IMAGE_PATH, 'rb') as image_file: | |
| files = {'image': (Path(IMAGE_PATH).name, image_file, 'image/jpeg')} | |
| data = {'lines_data': json.dumps(cam3_line_dict)} | |
| print("🚀 Envoi de la requête de calibration...") | |
| response = requests.post( | |
| f"{API_URL}/calibrate", | |
| files=files, | |
| data=data | |
| ) | |
| print(f"📡 Réponse reçue: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print("✅ Calibration réussie!") | |
| print("Paramètres de la caméra:") | |
| print(json.dumps(result['camera_parameters'], indent=2)) | |
| else: | |
| print(f"❌ Erreur calibration: {response.status_code}") | |
| try: | |
| error_detail = response.json() | |
| print(f"Détail de l'erreur: {error_detail}") | |
| except: | |
| print(f"Réponse brute: {response.text}") | |
| except Exception as e: | |
| print(f"❌ Exception lors du test de calibration: {e}") | |
| def test_inference_image(): | |
| """Test de l'inférence automatique sur image""" | |
| if not Path(IMAGE_PATH).exists(): | |
| print(f"❌ Image non trouvée: {IMAGE_PATH}") | |
| print(f" Chemin absolu: {Path(IMAGE_PATH).absolute()}") | |
| return | |
| print(f"📁 Test inférence avec l'image: {IMAGE_PATH}") | |
| print(f" Taille du fichier: {Path(IMAGE_PATH).stat().st_size} bytes") | |
| try: | |
| with open(IMAGE_PATH, 'rb') as image_file: | |
| files = {'image': (Path(IMAGE_PATH).name, image_file, 'image/jpeg')} | |
| data = { | |
| 'kp_threshold': 0.15, | |
| 'line_threshold': 0.15 | |
| } | |
| print("🚀 Envoi de la requête d'inférence image...") | |
| response = requests.post( | |
| f"{API_URL}/inference/image", | |
| files=files, | |
| data=data | |
| ) | |
| print(f"📡 Réponse reçue: {response.status_code}") | |
| print(f"📡 Réponse reçue: {response.json()}") | |
| if response.status_code == 200 and response.json()['status'] == 'success': | |
| result = response.json() | |
| print("✅ Inférence image réussie!") | |
| print(f"Status: {result['status']}") | |
| print(f"Image info: {result['image_info']}") | |
| if result['camera_parameters']: | |
| print("Paramètres de la caméra:") | |
| cam_params = result['camera_parameters'].get('cam_params', {}) | |
| print(f" Position: {cam_params.get('position_meters', 'N/A')}") | |
| print(f" Focale X: {cam_params.get('x_focal_length', 'N/A')}") | |
| print(f" Focale Y: {cam_params.get('y_focal_length', 'N/A')}") | |
| else: | |
| print(f"❌ Erreur inférence image: {response.status_code}") | |
| try: | |
| error_detail = response.json() | |
| print(f"Détail de l'erreur: {error_detail}") | |
| except: | |
| print(f"Réponse brute: {response.text}") | |
| except Exception as e: | |
| print(f"❌ Exception lors du test d'inférence image: {e}") | |
| def test_inference_video(): | |
| """Test de l'inférence automatique sur vidéo""" | |
| if not Path(VIDEO_PATH).exists(): | |
| print(f"❌ Vidéo non trouvée: {VIDEO_PATH}") | |
| print(f" Chemin absolu: {Path(VIDEO_PATH).absolute()}") | |
| return | |
| print(f"📁 Test inférence avec la vidéo: {VIDEO_PATH}") | |
| print(f" Taille du fichier: {Path(VIDEO_PATH).stat().st_size} bytes") | |
| print("🎬 Test inférence vidéo (peut prendre du temps...)") | |
| try: | |
| with open(VIDEO_PATH, 'rb') as video_file: | |
| files = {'video': (Path(VIDEO_PATH).name, video_file, 'video/mp4')} | |
| data = { | |
| 'kp_threshold': 0.15, | |
| 'line_threshold': 0.15, | |
| 'frame_step': 200 # Traiter 1 frame sur 10 pour le test | |
| } | |
| print("🚀 Envoi de la requête d'inférence vidéo...") | |
| response = requests.post( | |
| f"{API_URL}/inference/video", | |
| files=files, | |
| data=data | |
| ) | |
| print(f"📡 Réponse reçue: {response.status_code}") | |
| if response.status_code == 200: | |
| result = response.json() | |
| print("✅ Inférence vidéo réussie!") | |
| print(f"Status: {result['status']}") | |
| print(f"Frames traitées: {result['frames_processed']}") | |
| print(f"Vidéo info: {result['video_info']}") | |
| if result['camera_parameters']: | |
| print(f"\n=== Exemples de paramètres ===") | |
| for i, params in enumerate(result['camera_parameters'][:3]): | |
| frame_num = params.get('frame_number', i) | |
| timestamp = params.get('timestamp_seconds', 0) | |
| print(f"Frame {frame_num} (t={timestamp:.2f}s):") | |
| if 'cam_params' in params: | |
| cam_params = params['cam_params'] | |
| print(f" Position: {cam_params.get('position_meters', 'N/A')}") | |
| print(f" Focales: X={cam_params.get('x_focal_length', 'N/A')}, Y={cam_params.get('y_focal_length', 'N/A')}") | |
| if len(result['camera_parameters']) > 3: | |
| print(f"... et {len(result['camera_parameters']) - 3} autres frames") | |
| else: | |
| print(f"❌ Erreur inférence vidéo: {response.status_code}") | |
| try: | |
| error_detail = response.json() | |
| print(f"Détail de l'erreur: {error_detail}") | |
| except: | |
| print(f"Réponse brute: {response.text}") | |
| except Exception as e: | |
| print(f"❌ Exception lors du test d'inférence vidéo: {e}") | |
| def test_all(): | |
| """Lance tous les tests""" | |
| print("=== TEST DE L'API FOOTBALL VISION ===\n") | |
| # Test 1: Health check | |
| # print("1. Test Health Check") | |
| # if not test_health(): | |
| # print("❌ API non accessible, arrêt des tests") | |
| # return | |
| # print() | |
| # # Vérifier les chemins des fichiers | |
| # print("2. Vérification des fichiers") | |
| # print(f" Image: {'✅' if Path(IMAGE_PATH).exists() else '❌'} {IMAGE_PATH}") | |
| # print(f" Vidéo: {'✅' if Path(VIDEO_PATH).exists() else '❌'} {VIDEO_PATH}") | |
| # print() | |
| # # Test 2: Calibration avec lignes manuelles | |
| # print("3. Test Calibration (lignes manuelles)") | |
| # test_calibration() | |
| # print() | |
| # Test 3: Inférence image | |
| print("4. Test Inférence Image (automatique)") | |
| test_inference_image() | |
| print() | |
| # # Test 4: Inférence vidéo | |
| # print("5. Test Inférence Vidéo (automatique)") | |
| # test_inference_video() | |
| # print() | |
| if __name__ == "__main__": | |
| test_all() |