Spaces:
Running on Zero
Running on Zero
File size: 4,547 Bytes
36dac13 b39045a 36dac13 b39045a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import spaces # MUST come before torch / any CUDA-touching import
import os
os.environ.setdefault("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
import tempfile
import gradio as gr
import numpy as np
import PIL.Image as Image
from huggingface_hub import hf_hub_download
from ultralytics import YOLO
# VisDrone class names (10 classes detected by this model)
VISDRONE_CLASSES = [
"pedestrian", "people", "bicycle", "car", "van",
"truck", "tricycle", "awning-tricycle", "bus", "motor",
]
# Load model weights at module scope — ZeroGPU intercepts .to("cuda")
weights_path = hf_hub_download(repo_id="dronefreak/visdrone-yolov26n", filename="best.pt")
model = YOLO(weights_path)
@spaces.GPU(duration=30)
def detect(
image,
conf_threshold: float = 0.25,
iou_threshold: float = 0.7,
show_labels: bool = True,
show_conf: bool = True,
imgsz: int = 640,
):
"""Detect objects in an aerial/drone image using YOLOv26n fine-tuned on VisDrone.
Args:
image: Input image (PIL or numpy array).
conf_threshold: Minimum confidence score for detections (0–1).
iou_threshold: IoU NMS threshold (0–1).
show_labels: Whether to draw class labels on the output.
show_conf: Whether to draw confidence scores on the output.
imgsz: Inference image size in pixels.
"""
results = model.predict(
source=image,
conf=conf_threshold,
iou=iou_threshold,
imgsz=imgsz,
verbose=False,
)
# Build detection summary
detection_counts = {}
if results[0].boxes is not None and len(results[0].boxes) > 0:
cls_ids = results[0].boxes.cls.cpu().numpy().astype(int)
for cid in cls_ids:
name = VISDRONE_CLASSES[cid] if cid < len(VISDRONE_CLASSES) else str(cid)
detection_counts[name] = detection_counts.get(name, 0) + 1
summary_lines = [f"**Total detections:** {sum(detection_counts.values())}"]
for name, count in sorted(detection_counts.items(), key=lambda x: -x[1]):
summary_lines.append(f"- {name}: {count}")
summary = "\n".join(summary_lines)
# Annotated image
annotated = results[0].plot(labels=show_labels, conf=show_conf)
annotated_pil = Image.fromarray(annotated[..., ::-1])
return annotated_pil, summary
CSS = """
#col-container { max-width: 1200px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks(title="YOLOv26n VisDrone Detection") as demo:
gr.Markdown(
"""
# YOLOv26n VisDrone Object Detection
A lightweight 2.6M-parameter YOLOv26n model fine-tuned on the [VisDrone](https://github.com/VisDrone/VisDrone-Dataset) benchmark for aerial/drone imagery.
It detects 10 classes: *pedestrian, people, bicycle, car, van, truck, tricycle, awning-tricycle, bus, motor*.
Upload a drone/aerial image and run detection, or try one of the examples below.
"""
)
with gr.Row():
with gr.Column():
input_image = gr.Image(type="pil", label="Input Image")
with gr.Accordion("Detection Settings", open=False):
conf_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.25, step=0.01, label="Confidence Threshold")
iou_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.7, step=0.01, label="IoU (NMS) Threshold")
imgsz_radio = gr.Radio(choices=[320, 640, 1024], value=640, label="Inference Image Size")
labels_checkbox = gr.Checkbox(value=True, label="Show Labels")
conf_show_checkbox = gr.Checkbox(value=True, label="Show Confidence Scores")
detect_btn = gr.Button("Detect Objects", variant="primary")
with gr.Column():
output_image = gr.Image(type="pil", label="Detection Result")
detection_summary = gr.Markdown(label="Detection Summary")
detect_btn.click(
fn=detect,
inputs=[input_image, conf_slider, iou_slider, labels_checkbox, conf_show_checkbox, imgsz_radio],
outputs=[output_image, detection_summary],
)
gr.Examples(
examples=[
["examples/0000001_02999_d_0000005.jpg"],
["examples/0000002_00005_d_0000014.jpg"],
["examples/0000006_00159_d_0000001.jpg"],
],
inputs=[input_image],
outputs=[output_image, detection_summary],
fn=detect,
cache_examples=True,
cache_mode="lazy",
)
demo.launch(mcp_server=True, theme=gr.themes.Citrus(), css=CSS) |