Spaces:
Sleeping
Sleeping
| # ============================================================ | |
| # SMARTVISION AI - YOLOv8 EVALUATION SCRIPT | |
| # - Loads best.pt from training | |
| # - Computes mAP, per-class metrics | |
| # - Measures inference speed (FPS) | |
| # - Saves sample prediction images | |
| # - Saves metrics to JSON for reporting | |
| # ============================================================ | |
| import os | |
| import glob | |
| import time | |
| import json | |
| from ultralytics import YOLO | |
| # ------------------------------------------------------------ | |
| # 1. PATHS | |
| # ------------------------------------------------------------ | |
| BASE_DIR = "smartvision_dataset" | |
| DET_DIR = os.path.join(BASE_DIR, "detection") | |
| DATA_YAML = os.path.join(DET_DIR, "data.yaml") | |
| # Folder created by your train_yolo.py script | |
| RUN_DIR = "yolo_runs/smartvision_yolov8s" | |
| BEST_WEIGHTS = os.path.join(RUN_DIR, "weights", "best.pt") | |
| # NOTE: all detection images are in detection/images (no "val" subfolder) | |
| VAL_IMAGES_DIR = os.path.join(DET_DIR, "images") | |
| print("π DATA_YAML :", DATA_YAML) | |
| print("π¦ BEST_WEIGHTS:", BEST_WEIGHTS) | |
| print("π VAL_IMAGES :", VAL_IMAGES_DIR) | |
| # ------------------------------------------------------------ | |
| # 2. LOAD TRAINED MODEL | |
| # ------------------------------------------------------------ | |
| model = YOLO(BEST_WEIGHTS) | |
| print("\nβ Loaded trained YOLOv8 model from best.pt") | |
| # ------------------------------------------------------------ | |
| # 3. VALIDATION METRICS (mAP, precision, recall) | |
| # ------------------------------------------------------------ | |
| print("\n===== RUNNING VALIDATION (YOLO model.val) =====") | |
| metrics = model.val( | |
| data=DATA_YAML, | |
| split="val", # uses val split defined in data.yaml (here both train/val point to 'images') | |
| imgsz=640, | |
| save_json=False | |
| ) | |
| print("\n===== YOLOv8 Validation Metrics =====") | |
| print(f"mAP@0.5 : {metrics.box.map50:.4f}") | |
| print(f"mAP@0.5:0.95 : {metrics.box.map:.4f}") | |
| # metrics.box.maps is a list of per-class mAP values in the same order as names | |
| print("\nPer-class mAP@0.5 (first 10 classes):") | |
| for i, m in enumerate(metrics.box.maps[:10]): | |
| print(f" Class {i}: {m:.4f}") | |
| # ------------------------------------------------------------ | |
| # 4. INFERENCE SPEED (FPS) ON VALIDATION IMAGES | |
| # ------------------------------------------------------------ | |
| print("\n===== MEASURING INFERENCE SPEED (FPS) =====") | |
| # Collect all JPG images in detection/images | |
| val_images = glob.glob(os.path.join(VAL_IMAGES_DIR, "*.jpg")) | |
| val_images = sorted(val_images) | |
| num_test_images = min(50, len(val_images)) # test on up to 50 images | |
| test_images = val_images[:num_test_images] | |
| print(f"Found {len(val_images)} images in {VAL_IMAGES_DIR}") | |
| print(f"Using {len(test_images)} images for speed test.") | |
| # Defaults in case there are no images | |
| time_per_image = 0.0 | |
| fps = 0.0 | |
| if len(test_images) == 0: | |
| print("β οΈ No images found for FPS test. Skipping speed measurement.") | |
| else: | |
| start = time.perf_counter() | |
| _ = model.predict( | |
| source=test_images, | |
| imgsz=640, | |
| conf=0.5, | |
| verbose=False | |
| ) | |
| end = time.perf_counter() | |
| total_time = end - start | |
| time_per_image = total_time / len(test_images) | |
| fps = 1.0 / time_per_image | |
| print(f"Total time : {total_time:.2f} sec for {len(test_images)} images") | |
| print(f"Avg time / image : {time_per_image*1000:.2f} ms") | |
| print(f"Approx FPS : {fps:.2f} images/sec") | |
| # ------------------------------------------------------------ | |
| # 5. SAVE SAMPLE PREDICTIONS (BOXES + LABELS) | |
| # ------------------------------------------------------------ | |
| print("\n===== SAVING SAMPLE PREDICTION IMAGES =====") | |
| sample_out_project = "yolo_vis" | |
| sample_out_name = "samples" | |
| if len(test_images) == 0: | |
| print("β οΈ No images available for sample visualization. Skipping sample predictions.") | |
| else: | |
| sample_results = model.predict( | |
| source=test_images[:8], # first 8 images | |
| imgsz=640, | |
| conf=0.5, | |
| save=True, # save annotated images | |
| project=sample_out_project, | |
| name=sample_out_name, | |
| verbose=False | |
| ) | |
| print(f"β Saved sample predictions (with boxes & labels) to: {sample_out_project}/{sample_out_name}/") | |
| # ------------------------------------------------------------ | |
| # 6. SAVE METRICS TO JSON (FOR REPORTING) | |
| # ------------------------------------------------------------ | |
| print("\n===== SAVING METRICS TO JSON =====") | |
| yolo_metrics = { | |
| "model_name": "yolov8s_smartvision", | |
| "map_50": float(metrics.box.map50), | |
| "map_50_95": float(metrics.box.map), | |
| "num_val_images_for_speed_test": int(len(test_images)), | |
| "avg_inference_time_sec": float(time_per_image), | |
| "fps": float(fps), | |
| } | |
| os.makedirs("yolo_metrics", exist_ok=True) | |
| metrics_json_path = os.path.join("yolo_metrics", "yolov8s_metrics.json") | |
| with open(metrics_json_path, "w") as f: | |
| json.dump(yolo_metrics, f, indent=2) | |
| print(f"β Saved YOLO metrics JSON to: {metrics_json_path}") | |
| print("\nπ― YOLOv8 evaluation complete.") | |