glenn-jocher commited on
Commit
dea8977
·
verified ·
1 Parent(s): 175d90d

Modernize app to match YOLO26/YOLOv8 (image/video/webcam)

Browse files
Files changed (1) hide show
  1. app.py +245 -26
app.py CHANGED
@@ -1,46 +1,265 @@
1
- # Ultralytics YOLO 🚀, AGPL-3.0 license
2
 
 
 
 
 
3
  import gradio as gr
 
4
  import PIL.Image as Image
 
5
 
6
- from ultralytics import ASSETS, YOLO
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- model = None
 
9
 
10
 
11
- def predict_image(img, conf_threshold, iou_threshold, model_name):
12
- """Predicts objects in an image using a YOLOv8 model with adjustable confidence and IOU thresholds."""
13
  model = YOLO(model_name)
14
  results = model.predict(
15
  source=img,
16
  conf=conf_threshold,
17
  iou=iou_threshold,
18
- show_labels=True,
19
- show_conf=True,
20
- imgsz=640,
21
  )
22
 
23
  for r in results:
24
- im_array = r.plot()
25
  im = Image.fromarray(im_array[..., ::-1])
26
 
27
  return im
28
 
29
 
30
- iface = gr.Interface(
31
- fn=predict_image,
32
- inputs=[
33
- gr.Image(type="pil", label="Upload Image"),
34
- gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold"),
35
- gr.Slider(minimum=0, maximum=1, value=0.45, label="IoU threshold"),
36
- gr.Radio(choices=["yolo11n", "yolo11s", "yolo11n-seg", "yolo11s-seg", "yolo11n-pose", "yolo11s-pose"], label="Model Name", value="yolo11n"),
37
- ],
38
- outputs=gr.Image(type="pil", label="Result"),
39
- title="Ultralytics Gradio Application 🚀",
40
- description="Upload images for inference. The Ultralytics YOLO11n model is used by default.",
41
- examples=[
42
- [ASSETS / "bus.jpg", 0.25, 0.45, "yolo11n.pt"],
43
- [ASSETS / "zidane.jpg", 0.25, 0.45, "yolo11n.pt"],
44
- ],
45
- )
46
- iface.launch(share=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
 
3
+ import tempfile
4
+ from pathlib import Path
5
+
6
+ import cv2
7
  import gradio as gr
8
+ import numpy as np
9
  import PIL.Image as Image
10
+ from ultralytics import YOLO
11
 
12
+ MODEL_CHOICES = [
13
+ "yolo11n",
14
+ "yolo11s",
15
+ "yolo11m",
16
+ "yolo11n-seg",
17
+ "yolo11s-seg",
18
+ "yolo11m-seg",
19
+ "yolo11n-pose",
20
+ "yolo11s-pose",
21
+ "yolo11m-pose",
22
+ "yolo11n-obb",
23
+ "yolo11s-obb",
24
+ "yolo11m-obb",
25
+ "yolo11n-cls",
26
+ "yolo11s-cls",
27
+ "yolo11m-cls",
28
+ ]
29
 
30
+ IMAGE_SIZE_CHOICES = [320, 640, 1024]
31
+ CUSTOM_CSS = (Path(__file__).parent / "ultralytics.css").read_text()
32
 
33
 
34
+ def predict_image(img, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
35
+ """Predicts objects in an image using a Ultralytics YOLO model with adjustable confidence and IOU thresholds."""
36
  model = YOLO(model_name)
37
  results = model.predict(
38
  source=img,
39
  conf=conf_threshold,
40
  iou=iou_threshold,
41
+ imgsz=imgsz,
42
+ verbose=False,
 
43
  )
44
 
45
  for r in results:
46
+ im_array = r.plot(labels=show_labels, conf=show_conf)
47
  im = Image.fromarray(im_array[..., ::-1])
48
 
49
  return im
50
 
51
 
52
+ def predict_video(video_path, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
53
+ """Predicts objects in a video using a Ultralytics YOLO model and returns the annotated video."""
54
+ if video_path is None:
55
+ return None
56
+
57
+ model = YOLO(model_name)
58
+
59
+ # Open the video
60
+ cap = cv2.VideoCapture(video_path)
61
+ if not cap.isOpened():
62
+ return None
63
+
64
+ # Get video properties
65
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
66
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
67
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
68
+
69
+ # Create temporary output file
70
+ temp_output = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
71
+ output_path = temp_output.name
72
+ temp_output.close()
73
+
74
+ # Initialize video writer
75
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
76
+ out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
77
+
78
+ while True:
79
+ ret, frame = cap.read()
80
+ if not ret:
81
+ break
82
+
83
+ # Run inference on the frame
84
+ results = model.predict(
85
+ source=frame,
86
+ conf=conf_threshold,
87
+ iou=iou_threshold,
88
+ imgsz=imgsz,
89
+ verbose=False,
90
+ )
91
+
92
+ # Get the annotated frame
93
+ annotated_frame = results[0].plot(labels=show_labels, conf=show_conf)
94
+ out.write(annotated_frame)
95
+
96
+ cap.release()
97
+ out.release()
98
+
99
+ return output_path
100
+
101
+
102
+ # Cache model for streaming performance
103
+ _model_cache = {}
104
+
105
+
106
+ def get_model(model_name):
107
+ """Get or create a cached model instance."""
108
+ if model_name not in _model_cache:
109
+ _model_cache[model_name] = YOLO(model_name)
110
+ return _model_cache[model_name]
111
+
112
+
113
+ def predict_webcam(frame, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
114
+ """Predicts objects in a webcam frame using a Ultralytics YOLO model (optimized for streaming)."""
115
+ if frame is None:
116
+ return None
117
+
118
+ # Use cached model for better streaming performance
119
+ model = get_model(model_name)
120
+
121
+ if isinstance(frame, np.ndarray):
122
+ # Gradio webcam sends RGB, but Ultralytics YOLO expects BGR for OpenCV operations
123
+ # Convert RGB to BGR for YOLO
124
+ frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
125
+
126
+ # Run inference
127
+ results = model.predict(
128
+ source=frame_bgr,
129
+ conf=conf_threshold,
130
+ iou=iou_threshold,
131
+ imgsz=imgsz,
132
+ verbose=False,
133
+ )
134
+
135
+ # YOLO's plot() returns BGR, convert back to RGB for Gradio display
136
+ annotated_frame = results[0].plot(labels=show_labels, conf=show_conf)
137
+ # Convert BGR to RGB for Gradio
138
+ return cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB)
139
+
140
+ return None
141
+
142
+
143
+ # Create the Gradio app with tabs
144
+ with gr.Blocks(title="Ultralytics YOLO11 Inference 🚀") as demo:
145
+ gr.Markdown(
146
+ """
147
+ <div align="center">
148
+ <p>
149
+ <a href="https://platform.ultralytics.com/?utm_source=huggingface&utm_medium=referral&utm_campaign=yolo11&utm_content=banner" target="_blank">
150
+ <img width="50%" src="https://raw.githubusercontent.com/ultralytics/assets/main/yolov8/banner-yolov8.png" alt="Ultralytics YOLO banner"></a>
151
+ </p>
152
+ <p style="margin: 3px 0;">
153
+ <a href="https://docs.ultralytics.com/zh/">中文</a> | <a href="https://docs.ultralytics.com/ko/">한국어</a> | <a href="https://docs.ultralytics.com/ja/">日本語</a> | <a href="https://docs.ultralytics.com/ru/">Русский</a> | <a href="https://docs.ultralytics.com/de/">Deutsch</a> | <a href="https://docs.ultralytics.com/fr/">Français</a> | <a href="https://docs.ultralytics.com/es">Español</a> | <a href="https://docs.ultralytics.com/pt/">Português</a> | <a href="https://docs.ultralytics.com/tr/">Türkçe</a> | <a href="https://docs.ultralytics.com/vi/">Tiếng Việt</a> | <a href="https://docs.ultralytics.com/ar/">العربية</a>
154
+ </p>
155
+
156
+ <div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 3px; margin-top: 3px;">
157
+ <a href="https://github.com/ultralytics/ultralytics/actions/workflows/ci.yml"><img src="https://github.com/ultralytics/ultralytics/actions/workflows/ci.yml/badge.svg" alt="Ultralytics CI"></a>
158
+ <a href="https://pepy.tech/projects/ultralytics"><img src="https://static.pepy.tech/badge/ultralytics" alt="Ultralytics Downloads"></a>
159
+ <a href="https://zenodo.org/badge/latestdoi/264818686"><img src="https://zenodo.org/badge/264818686.svg" alt="Ultralytics YOLO Citation"></a>
160
+ <a href="https://discord.com/invite/ultralytics"><img alt="Ultralytics Discord" src="https://img.shields.io/discord/1089800235347353640?logo=discord&logoColor=white&label=Discord&color=blue"></a>
161
+ <a href="https://community.ultralytics.com/"><img alt="Ultralytics Forums" src="https://img.shields.io/discourse/users?server=https%3A%2F%2Fcommunity.ultralytics.com&logo=discourse&label=Forums&color=blue"></a>
162
+ <a href="https://www.reddit.com/r/ultralytics/"><img alt="Ultralytics Reddit" src="https://img.shields.io/reddit/subreddit-subscribers/ultralytics?style=flat&logo=reddit&logoColor=white&label=Reddit&color=blue"></a>
163
+ </div>
164
+ <div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 3px; margin-top: 3px;">
165
+ <a href="https://console.paperspace.com/github/ultralytics/ultralytics"><img src="https://assets.paperspace.io/img/gradient-badge.svg" alt="Run Ultralytics on Gradient"></a>
166
+ <a href="https://colab.research.google.com/github/ultralytics/ultralytics/blob/main/examples/tutorial.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open Ultralytics In Colab"></a>
167
+ <a href="https://www.kaggle.com/models/ultralytics/yolo11"><img src="https://kaggle.com/static/images/open-in-kaggle.svg" alt="Open Ultralytics In Kaggle"></a>
168
+ <a href="https://mybinder.org/v2/gh/ultralytics/ultralytics/HEAD?labpath=examples%2Ftutorial.ipynb"><img src="https://mybinder.org/badge_logo.svg" alt="Open Ultralytics In Binder"></a>
169
+ </div>
170
+ </div>
171
+
172
+ [Ultralytics](https://www.ultralytics.com/?utm_source=huggingface&utm_medium=referral&utm_campaign=yolo11&utm_content=contextual) [YOLO11](https://docs.ultralytics.com/models/yolo11/?utm_source=huggingface&utm_medium=referral&utm_campaign=yolo11&utm_content=contextual_model_link) is a state-of-the-art real-time computer vision model that delivers leading accuracy, speed, and efficiency across object detection, instance segmentation, image classification, pose estimation, and oriented bounding box (OBB) tasks. Select a model below and upload an image or video, or use your webcam, to try it live.
173
+ """
174
+ )
175
+
176
+ with gr.Tabs():
177
+ # Image Tab
178
+ with gr.TabItem("📷 Image"):
179
+ with gr.Row():
180
+ with gr.Column():
181
+ img_input = gr.Image(type="pil", label="Upload Image")
182
+ img_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
183
+ img_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
184
+ img_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo11n")
185
+ img_labels = gr.Checkbox(value=True, label="Show Labels")
186
+ img_conf_show = gr.Checkbox(value=True, label="Show Confidence")
187
+ img_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
188
+ img_btn = gr.Button("Detect Objects", variant="primary")
189
+ with gr.Column():
190
+ img_output = gr.Image(type="pil", label="Result")
191
+
192
+ img_btn.click(
193
+ predict_image,
194
+ inputs=[img_input, img_conf, img_iou, img_model, img_labels, img_conf_show, img_size],
195
+ outputs=img_output,
196
+ )
197
+
198
+ gr.Examples(
199
+ examples=[
200
+ ["https://ultralytics.com/images/bus.jpg", 0.25, 0.7, "yolo11n", True, True, 640],
201
+ ["https://ultralytics.com/images/zidane.jpg", 0.25, 0.7, "yolo11n-seg", True, True, 640],
202
+ ["https://ultralytics.com/images/boats.jpg", 0.25, 0.7, "yolo11n-obb", True, True, 1024],
203
+ ],
204
+ inputs=[img_input, img_conf, img_iou, img_model, img_labels, img_conf_show, img_size],
205
+ )
206
+
207
+ # Video Tab
208
+ with gr.TabItem("🎬 Video"):
209
+ with gr.Row():
210
+ with gr.Column():
211
+ vid_input = gr.Video(label="Upload Video")
212
+ vid_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
213
+ vid_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
214
+ vid_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo11n")
215
+ vid_labels = gr.Checkbox(value=True, label="Show Labels")
216
+ vid_conf_show = gr.Checkbox(value=True, label="Show Confidence")
217
+ vid_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
218
+ vid_btn = gr.Button("Process Video", variant="primary")
219
+ with gr.Column():
220
+ vid_output = gr.Video(label="Result")
221
+
222
+ vid_btn.click(
223
+ predict_video,
224
+ inputs=[vid_input, vid_conf, vid_iou, vid_model, vid_labels, vid_conf_show, vid_size],
225
+ outputs=vid_output,
226
+ )
227
+
228
+ # Webcam Tab - Real-time streaming
229
+ with gr.TabItem("📹 Webcam"):
230
+ gr.Markdown("### Real-time Webcam Detection")
231
+ gr.Markdown("Enable streaming for live detection as you move!")
232
+ with gr.Row():
233
+ with gr.Column():
234
+ webcam_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
235
+ webcam_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
236
+ webcam_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo11n")
237
+ webcam_labels = gr.Checkbox(value=True, label="Show Labels")
238
+ webcam_conf_show = gr.Checkbox(value=True, label="Show Confidence")
239
+ webcam_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
240
+ with gr.Column():
241
+ # Streaming webcam input with real-time output
242
+ webcam_input = gr.Image(
243
+ sources=["webcam"],
244
+ type="numpy",
245
+ label="Webcam (streaming)",
246
+ streaming=True,
247
+ )
248
+ webcam_output = gr.Image(type="numpy", label="Detection Result")
249
+
250
+ # Stream event for real-time detection
251
+ webcam_input.stream(
252
+ predict_webcam,
253
+ inputs=[
254
+ webcam_input,
255
+ webcam_conf,
256
+ webcam_iou,
257
+ webcam_model,
258
+ webcam_labels,
259
+ webcam_conf_show,
260
+ webcam_size,
261
+ ],
262
+ outputs=webcam_output,
263
+ )
264
+
265
+ demo.launch(css=CUSTOM_CSS, ssr_mode=False)