onuralpszr commited on
Commit
0443f48
Β·
verified Β·
1 Parent(s): 174949c

feat: πŸš€ Add YOLO26 Gradio app implementation

Browse files

Signed-off-by: Onuralp SEZER <onuralp@ultralytics.com>

Files changed (4) hide show
  1. README.md +1 -1
  2. app.py +262 -0
  3. requirements.txt +2 -0
  4. ultralytics.css +70 -0
README.md CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
  title: YOLO26
3
  emoji: πŸ’»
4
- colorFrom: gray
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 6.4.0
 
1
  ---
2
  title: YOLO26
3
  emoji: πŸ’»
4
+ colorFrom: blue
5
  colorTo: purple
6
  sdk: gradio
7
  sdk_version: 6.4.0
app.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Ultralytics πŸš€ AGPL-3.0 License - https://ultralytics.com/license
2
+
3
+ import tempfile
4
+ import cv2
5
+ import gradio as gr
6
+ import numpy as np
7
+ import PIL.Image as Image
8
+ from ultralytics import YOLO
9
+ from pathlib import Path
10
+
11
+
12
+ MODEL_CHOICES = [
13
+ "yolo26n",
14
+ "yolo26s",
15
+ "yolo26m",
16
+ "yolo26n-seg",
17
+ "yolo26s-seg",
18
+ "yolo26m-seg",
19
+ "yolo26n-pose",
20
+ "yolo26s-pose",
21
+ "yolo26m-pose",
22
+ "yolo26n-obb",
23
+ "yolo26s-obb",
24
+ "yolo26m-obb",
25
+ "yolo26n-cls",
26
+ "yolo26s-cls",
27
+ "yolo26m-cls",
28
+ ]
29
+
30
+ IMAGE_SIZE_CHOICES = [320, 640, 1024]
31
+ CUSTOM_CSS = (Path(__file__).parent / "ultralytics.css").read_text()
32
+
33
+ def predict_image(img, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
34
+ """Predicts objects in an image using a Ultralytics YOLO model with adjustable confidence and IOU thresholds."""
35
+ model = YOLO(model_name)
36
+ results = model.predict(
37
+ source=img,
38
+ conf=conf_threshold,
39
+ iou=iou_threshold,
40
+ imgsz=imgsz,
41
+ verbose=False,
42
+ )
43
+
44
+ for r in results:
45
+ im_array = r.plot(labels=show_labels, conf=show_conf)
46
+ im = Image.fromarray(im_array[..., ::-1])
47
+
48
+ return im
49
+
50
+
51
+ def predict_video(video_path, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
52
+ """Predicts objects in a video using a Ultralytics YOLO model and returns the annotated video."""
53
+ if video_path is None:
54
+ return None
55
+
56
+ model = YOLO(model_name)
57
+
58
+ # Open the video
59
+ cap = cv2.VideoCapture(video_path)
60
+ if not cap.isOpened():
61
+ return None
62
+
63
+ # Get video properties
64
+ fps = int(cap.get(cv2.CAP_PROP_FPS))
65
+ width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
66
+ height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
67
+
68
+ # Create temporary output file
69
+ temp_output = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False)
70
+ output_path = temp_output.name
71
+ temp_output.close()
72
+
73
+ # Initialize video writer
74
+ fourcc = cv2.VideoWriter_fourcc(*"mp4v")
75
+ out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
76
+
77
+ while True:
78
+ ret, frame = cap.read()
79
+ if not ret:
80
+ break
81
+
82
+ # Run inference on the frame
83
+ results = model.predict(
84
+ source=frame,
85
+ conf=conf_threshold,
86
+ iou=iou_threshold,
87
+ imgsz=imgsz,
88
+ verbose=False,
89
+ )
90
+
91
+ # Get the annotated frame
92
+ annotated_frame = results[0].plot(labels=show_labels, conf=show_conf)
93
+ out.write(annotated_frame)
94
+
95
+ cap.release()
96
+ out.release()
97
+
98
+ return output_path
99
+
100
+ # Cache model for streaming performance
101
+ _model_cache = {}
102
+
103
+ def get_model(model_name):
104
+ """Get or create a cached model instance."""
105
+ if model_name not in _model_cache:
106
+ _model_cache[model_name] = YOLO(model_name)
107
+ return _model_cache[model_name]
108
+
109
+
110
+ def predict_webcam(frame, conf_threshold, iou_threshold, model_name, show_labels, show_conf, imgsz):
111
+ """Predicts objects in a webcam frame using a Ultralytics YOLO model (optimized for streaming)."""
112
+ if frame is None:
113
+ return None
114
+
115
+ # Use cached model for better streaming performance
116
+ model = get_model(model_name)
117
+
118
+ if isinstance(frame, np.ndarray):
119
+ # Gradio webcam sends RGB, but Ultralytics YOLO expects BGR for OpenCV operations
120
+ # Convert RGB to BGR for YOLO
121
+ frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
122
+
123
+ # Run inference
124
+ results = model.predict(
125
+ source=frame_bgr,
126
+ conf=conf_threshold,
127
+ iou=iou_threshold,
128
+ imgsz=imgsz,
129
+ verbose=False,
130
+ )
131
+
132
+ # YOLO's plot() returns BGR, convert back to RGB for Gradio display
133
+ annotated_frame = results[0].plot(labels=show_labels, conf=show_conf)
134
+ # Convert BGR to RGB for Gradio
135
+ return cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB)
136
+
137
+ return None
138
+
139
+
140
+ # Create the Gradio app with tabs
141
+ with gr.Blocks(title="Ultralytics YOLO26 Inference πŸš€") as demo:
142
+ gr.Markdown(
143
+ """
144
+ <div align="center">
145
+ <p>
146
+ <a href="https://www.ultralytics.com/blog/ultralytics-yolo26-the-new-standard-for-edge-first-vision-ai" target="_blank">
147
+ <img width="50%" src="https://raw.githubusercontent.com/ultralytics/assets/main/yolov8/banner-yolov8.png" alt="Ultralytics YOLO banner"></a>
148
+ </p>
149
+ <p style="margin: 3px 0;">
150
+ <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>
151
+ </p>
152
+
153
+ <div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 3px; margin-top: 3px;">
154
+ <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>
155
+ <a href="https://pepy.tech/projects/ultralytics" style="position: relative; top: -3px;"><img src="https://static.pepy.tech/badge/ultralytics" alt="Ultralytics Downloads"></a>
156
+ <a href="https://zenodo.org/badge/latestdoi/264818686" style="position: relative; top: -3px;"><img src="https://zenodo.org/badge/264818686.svg" alt="Ultralytics YOLO Citation"></a>
157
+ <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>
158
+ <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>
159
+ <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>
160
+ </div>
161
+ <div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 3px; margin-top: 3px;">
162
+ <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>
163
+ <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>
164
+ <a href="https://www.kaggle.com/models/ultralytics/yolo26" style="position: relative; top: -3px;"><img src="https://kaggle.com/static/images/open-in-kaggle.svg" alt="Open Ultralytics In Kaggle"></a>
165
+ <a href="https://mybinder.org/v2/gh/ultralytics/ultralytics/HEAD?labpath=examples%2Ftutorial.ipynb" style="position: relative; top: -3px;"><img src="https://mybinder.org/badge_logo.svg" alt="Open Ultralytics In Binder"></a>
166
+ </div>
167
+ </div>
168
+
169
+ **[YOLO26](https://docs.ultralytics.com/models/yolo26/)** is the latest flagship model from [Ultralytics](https://www.ultralytics.com/) β€” setting a new standard for **edge-first vision AI**. Engineered for maximum efficiency on edge devices while maintaining exceptional accuracy, YOLO26 builds on years of pioneering research in real-time computer vision.
170
+ """
171
+ )
172
+
173
+ with gr.Tabs():
174
+ # Image Tab
175
+ with gr.TabItem("πŸ“· Image"):
176
+ with gr.Row():
177
+ with gr.Column():
178
+ img_input = gr.Image(type="pil", label="Upload Image")
179
+ img_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
180
+ img_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
181
+ img_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo26n")
182
+ img_labels = gr.Checkbox(value=True, label="Show Labels")
183
+ img_conf_show = gr.Checkbox(value=True, label="Show Confidence")
184
+ img_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
185
+ img_btn = gr.Button("Detect Objects", variant="primary")
186
+ with gr.Column():
187
+ img_output = gr.Image(type="pil", label="Result")
188
+
189
+ img_btn.click(
190
+ predict_image,
191
+ inputs=[img_input, img_conf, img_iou, img_model, img_labels, img_conf_show, img_size],
192
+ outputs=img_output,
193
+ )
194
+
195
+ gr.Examples(
196
+ examples=[
197
+ ["https://ultralytics.com/images/bus.jpg", 0.25, 0.7, "yolo26n", True, True, 640],
198
+ ["https://ultralytics.com/images/zidane.jpg", 0.25, 0.7, "yolo26n-seg", True, True, 640],
199
+ ["https://ultralytics.com/images/boats.jpg", 0.25, 0.7, "yolo26n-obb", True, True, 1024],
200
+ ],
201
+ inputs=[img_input, img_conf, img_iou, img_model, img_labels, img_conf_show, img_size],
202
+ )
203
+
204
+ # Video Tab
205
+ with gr.TabItem("🎬 Video"):
206
+ with gr.Row():
207
+ with gr.Column():
208
+ vid_input = gr.Video(label="Upload Video")
209
+ vid_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
210
+ vid_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
211
+ vid_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo26n")
212
+ vid_labels = gr.Checkbox(value=True, label="Show Labels")
213
+ vid_conf_show = gr.Checkbox(value=True, label="Show Confidence")
214
+ vid_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
215
+ vid_btn = gr.Button("Process Video", variant="primary")
216
+ with gr.Column():
217
+ vid_output = gr.Video(label="Result")
218
+
219
+ vid_btn.click(
220
+ predict_video,
221
+ inputs=[vid_input, vid_conf, vid_iou, vid_model, vid_labels, vid_conf_show, vid_size],
222
+ outputs=vid_output,
223
+ )
224
+
225
+ # Webcam Tab - Real-time streaming
226
+ with gr.TabItem("πŸ“Ή Webcam"):
227
+ gr.Markdown("### Real-time Webcam Detection")
228
+ gr.Markdown("Enable streaming for live detection as you move!")
229
+ with gr.Row():
230
+ with gr.Column():
231
+ webcam_conf = gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold")
232
+ webcam_iou = gr.Slider(minimum=0, maximum=1, value=0.7, label="IoU threshold")
233
+ webcam_model = gr.Radio(choices=MODEL_CHOICES, label="Model Name", value="yolo26n")
234
+ webcam_labels = gr.Checkbox(value=True, label="Show Labels")
235
+ webcam_conf_show = gr.Checkbox(value=True, label="Show Confidence")
236
+ webcam_size = gr.Radio(choices=IMAGE_SIZE_CHOICES, label="Image Size", value=640)
237
+ with gr.Column():
238
+ # Streaming webcam input with real-time output
239
+ webcam_input = gr.Image(
240
+ sources=["webcam"],
241
+ type="numpy",
242
+ label="Webcam (streaming)",
243
+ streaming=True,
244
+ )
245
+ webcam_output = gr.Image(type="numpy", label="Detection Result")
246
+
247
+ # Stream event for real-time detection
248
+ webcam_input.stream(
249
+ predict_webcam,
250
+ inputs=[
251
+ webcam_input,
252
+ webcam_conf,
253
+ webcam_iou,
254
+ webcam_model,
255
+ webcam_labels,
256
+ webcam_conf_show,
257
+ webcam_size,
258
+ ],
259
+ outputs=webcam_output,
260
+ )
261
+
262
+ demo.launch(share=True, css=CUSTOM_CSS)
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio
2
+ ultralytics
ultralytics.css ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Ultralytics πŸš€ AGPL-3.0 License - https://ultralytics.com/license
3
+ *
4
+ * Ultralytics Gradio Theme CSS
5
+ * Use this CSS file for consistent Ultralytics blue (#042AFF) styling across Gradio apps
6
+ * Compatible with Gradio 6.x
7
+ *
8
+ * Usage in app.py:
9
+ * from pathlib import Path
10
+ * custom_css = Path("ultralytics.css").read_text()
11
+ * demo.launch(css=custom_css)
12
+ */
13
+
14
+ /* Override Gradio CSS variables for Ultralytics blue */
15
+ .gradio-container {
16
+ --slider-color: #042AFF !important;
17
+ --checkbox-background-color-selected: #042AFF !important;
18
+ --checkbox-border-color-selected: #042AFF !important;
19
+ --checkbox-border-color-focus: #042AFF !important;
20
+ --button-primary-background-fill: #042AFF !important;
21
+ --button-primary-background-fill-hover: #0320CC !important;
22
+ --button-primary-border-color: #042AFF !important;
23
+ --color-accent: #042AFF !important;
24
+ --color-accent-soft: rgba(4, 42, 255, 0.15) !important;
25
+ }
26
+
27
+ /* Slider filled track */
28
+ input[type="range"]::-webkit-slider-runnable-track {
29
+ background: linear-gradient(to right, #042AFF var(--range_progress, 25%), var(--neutral-200, #e5e7eb) var(--range_progress, 25%)) !important;
30
+ }
31
+ input[type="range"]::-moz-range-progress {
32
+ background: #042AFF !important;
33
+ }
34
+
35
+ /* Radio and checkbox accent */
36
+ input[type="radio"],
37
+ input[type="checkbox"] {
38
+ accent-color: #042AFF !important;
39
+ }
40
+
41
+ /* Tab styling - remove orange, make blue */
42
+ button[role="tab"] {
43
+ border-bottom-color: transparent !important;
44
+ }
45
+ button[role="tab"].selected,
46
+ button[role="tab"][aria-selected="true"] {
47
+ background: transparent !important;
48
+ color: #042AFF !important;
49
+ border-bottom: 2px solid #042AFF !important;
50
+ }
51
+
52
+ /* Radio group selected item: blue background, white text */
53
+ .wrap.selected,
54
+ label.selected {
55
+ background: #042AFF !important;
56
+ border-color: #042AFF !important;
57
+ color: white !important;
58
+ }
59
+ label.selected span {
60
+ color: white !important;
61
+ }
62
+
63
+ /* Primary button */
64
+ button.primary {
65
+ background: #042AFF !important;
66
+ border-color: #042AFF !important;
67
+ }
68
+ button.primary:hover {
69
+ background: #0320CC !important;
70
+ }