PnLCalib / test-api.py
2nzi's picture
ADD INFERENCE ENDPOINTS for images and video
fe10d2a
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()