sergey21000 commited on
Commit
f0d0031
1 Parent(s): 946fe5f

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +182 -182
  2. utils.py +3 -3
app.py CHANGED
@@ -1,183 +1,183 @@
1
- import shutil
2
- from pathlib import Path
3
- from typing import List, Dict, Union, Tuple, Literal, Optional
4
-
5
- import numpy as np
6
- import gradio as gr
7
- from gradio.components.base import Component
8
- from ultralytics import YOLO
9
-
10
- from utils import download_model, detect_image, detect_video, get_csv_annotate
11
-
12
-
13
- # ======================= MODEL ===================================
14
-
15
- MODELS_DIR = Path('models')
16
- MODELS_DIR.mkdir(exist_ok=True)
17
-
18
- MODELS = {
19
- 'yolov11n.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt',
20
- 'yolov11s.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11s.pt',
21
- 'yolov11m.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11m.pt',
22
- 'yolov11l.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11l.pt',
23
- 'yolov11x.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11x.pt',
24
- }
25
- MODEL_NAMES = list(MODELS.keys())
26
-
27
- model_path = download_model(MODEL_NAMES[0], MODELS_DIR, MODELS)
28
- default_model = YOLO(model_path)
29
-
30
- IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png']
31
- VIDEO_EXTENSIONS = ['.mp4', '.avi']
32
-
33
-
34
- # =================== ADDITIONAL INTERFACE FUNCTIONS ========================
35
-
36
- def change_model(model_state: Dict[str, YOLO], model_name: str):
37
- progress = gr.Progress()
38
- progress(0.3, desc='Downloading the model')
39
- model_path = download_model(model_name)
40
- progress(0.7, desc='Model initialization')
41
- model_state['model'] = YOLO(model_path)
42
- return f'Model {model_name} initialized'
43
-
44
-
45
- def detect(file_path: str, file_link: str, model_state: Dict[str, YOLO], conf: float, iou: float):
46
- model = model_state['model']
47
- if file_link:
48
- file_path = file_link
49
-
50
- file_ext = f'.{file_path.rsplit(".")[-1]}'
51
- if file_ext in IMAGE_EXTENSIONS:
52
- np_image = detect_image(file_path, model, conf, iou)
53
- return np_image, "Detection complete, opening image..."
54
- elif file_ext in VIDEO_EXTENSIONS or 'youtube.com' in file_link:
55
- video_path = detect_video(file_path, model, conf, iou)
56
- return video_path, "Detection complete, converting and opening video..."
57
- else:
58
- gr.Info('Invalid image or video format...')
59
- return None, None
60
-
61
- # =================== INTERFACE COMPONENTS ============================
62
-
63
- def get_output_media_components(detect_result: Optional[Union[np.ndarray, str, Path]] = None):
64
- visible = isinstance(detect_result, np.ndarray)
65
- image_output = gr.Image(
66
- value=detect_result if visible else None,
67
- type="numpy",
68
- width=640,
69
- height=480,
70
- visible=visible,
71
- label='Output',
72
- )
73
- visible = isinstance(detect_result, (str, Path))
74
- video_output = gr.Video(
75
- value=detect_result if visible else None,
76
- width=640,
77
- height=480,
78
- visible=visible,
79
- label='Output',
80
- )
81
- clear_btn = gr.Button(
82
- value='Clear',
83
- scale=0,
84
- visible=detect_result is not None,
85
- )
86
- return image_output, video_output, clear_btn
87
-
88
-
89
- def get_download_csv_btn(csv_annotations_path: Optional[Path] = None):
90
- download_csv_btn = gr.DownloadButton(
91
- label='Download csv annotations for video',
92
- value=csv_annotations_path,
93
- scale=0,
94
- visible=csv_annotations_path is not None,
95
- )
96
- return download_csv_btn
97
-
98
- # =================== APPINTERFACE ==========================
99
-
100
- css = '''
101
- .gradio-container { width: 70% !important }
102
- '''
103
- with gr.Blocks(css=css) as demo:
104
- gr.HTML("""<h3 style='text-align: center'>YOLOv11 Detector</h3>""")
105
-
106
- model_state = gr.State({'model': default_model})
107
- detect_result = gr.State(None)
108
- csv_annotations_path = gr.State(None)
109
-
110
- with gr.Row():
111
- with gr.Column():
112
- file_path = gr.File(file_types=['image', 'video'], file_count='single', label='Select an image or video')
113
- file_link = gr.Textbox(label='Direct link to image or YouTube link')
114
- model_name = gr.Radio(choices=MODEL_NAMES, value=MODEL_NAMES[0], label='Select YOLO model')
115
- conf = gr.Slider(0, 1, value=0.5, step=0.05, label='Confidence')
116
- iou = gr.Slider(0, 1, value=0.7, step=0.1, label='IOU')
117
- status_message = gr.Textbox(value='Ready to go', label='Status')
118
- detect_btn = gr.Button('Detect', interactive=True)
119
-
120
- with gr.Column():
121
- image_output, video_output, clear_btn = get_output_media_components()
122
- download_csv_btn = get_download_csv_btn()
123
-
124
- model_name.change(
125
- fn=lambda: gr.update(interactive=False),
126
- inputs=None,
127
- outputs=[detect_btn],
128
- ).then(
129
- fn=change_model,
130
- inputs=[model_state, model_name],
131
- outputs=[status_message],
132
- ).success(
133
- fn=lambda: gr.update(interactive=True),
134
- inputs=None,
135
- outputs=[detect_btn],
136
- )
137
-
138
- detect_btn.click(
139
- fn=detect,
140
- inputs=[file_path, file_link, model_state, conf, iou],
141
- outputs=[detect_result, status_message],
142
- ).success(
143
- fn=get_output_media_components,
144
- inputs=[detect_result],
145
- outputs=[image_output, video_output, clear_btn],
146
- ).then(
147
- fn=lambda: 'Ready to go',
148
- inputs=None,
149
- outputs=[status_message],
150
- ).then(
151
- fn=get_csv_annotate,
152
- inputs=[detect_result],
153
- outputs=[csv_annotations_path],
154
- ).success(
155
- fn=get_download_csv_btn,
156
- inputs=[csv_annotations_path],
157
- outputs=[download_csv_btn],
158
- )
159
-
160
- def clear_results_dir(detect_result):
161
- if isinstance(detect_result, Path):
162
- shutil.rmtree(detect_result.parent, ignore_errors=True)
163
-
164
- clear_components = [image_output, video_output, clear_btn, download_csv_btn]
165
- clear_btn.click(
166
- fn=lambda: [gr.update(visible=False) for _ in range(len(clear_components))],
167
- inputs=None,
168
- outputs=clear_components,
169
- ).then(
170
- fn=clear_results_dir,
171
- inputs=[detect_result],
172
- outputs=None,
173
- ).then(
174
- fn=lambda: (None, None),
175
- inputs=None,
176
- outputs=[detect_result, csv_annotations_path]
177
- )
178
-
179
- gr.HTML("""<h3 style='text-align: center'>
180
- <a href="https://github.com/sergey21000/yolo-detector" target='_blank'>GitHub Page</a></h3>
181
- """)
182
-
183
  demo.launch(server_name='0.0.0.0') # debug=True
 
1
+ import shutil
2
+ from pathlib import Path
3
+ from typing import List, Dict, Union, Tuple, Literal, Optional
4
+
5
+ import numpy as np
6
+ import gradio as gr
7
+ from gradio.components.base import Component
8
+ from ultralytics import YOLO
9
+
10
+ from utils import download_model, detect_image, detect_video, get_csv_annotate
11
+
12
+
13
+ # ======================= MODEL ===================================
14
+
15
+ MODELS_DIR = Path('models')
16
+ MODELS_DIR.mkdir(exist_ok=True)
17
+
18
+ MODELS = {
19
+ 'yolov11n.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11n.pt',
20
+ 'yolov11s.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11s.pt',
21
+ 'yolov11m.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11m.pt',
22
+ 'yolov11l.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11l.pt',
23
+ 'yolov11x.pt': 'https://github.com/ultralytics/assets/releases/download/v8.3.0/yolo11x.pt',
24
+ }
25
+ MODEL_NAMES = list(MODELS.keys())
26
+
27
+ model_path = download_model(MODEL_NAMES[0], MODELS_DIR, MODELS)
28
+ default_model = YOLO(model_path)
29
+
30
+ IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png']
31
+ VIDEO_EXTENSIONS = ['.mp4', '.avi']
32
+
33
+
34
+ # =================== ADDITIONAL INTERFACE FUNCTIONS ========================
35
+
36
+ def change_model(model_state: Dict[str, YOLO], model_name: str):
37
+ progress = gr.Progress()
38
+ progress(0.3, desc='Downloading the model')
39
+ model_path = download_model(model_name)
40
+ progress(0.7, desc='Model initialization')
41
+ model_state['model'] = YOLO(model_path)
42
+ return f'Model {model_name} initialized'
43
+
44
+
45
+ def detect(file_path: str, file_link: str, model_state: Dict[str, YOLO], conf: float, iou: float):
46
+ model = model_state['model']
47
+ if file_link:
48
+ file_path = file_link
49
+
50
+ file_ext = f'.{file_path.rsplit(".")[-1]}'
51
+ if file_ext in IMAGE_EXTENSIONS:
52
+ np_image = detect_image(file_path, model, conf, iou)
53
+ return np_image, "Detection complete, opening image..."
54
+ elif file_ext in VIDEO_EXTENSIONS or 'youtube.com' in file_link:
55
+ video_path = detect_video(file_path, model, conf, iou)
56
+ return video_path, "Detection complete, converting and opening video..."
57
+ else:
58
+ gr.Info('Invalid image or video format...')
59
+ return None, None
60
+
61
+ # =================== INTERFACE COMPONENTS ============================
62
+
63
+ def get_output_media_components(detect_result: Optional[Union[np.ndarray, str, Path]] = None):
64
+ visible = isinstance(detect_result, np.ndarray)
65
+ image_output = gr.Image(
66
+ value=detect_result if visible else None,
67
+ type="numpy",
68
+ width=640,
69
+ height=480,
70
+ visible=visible,
71
+ label='Output',
72
+ )
73
+ visible = isinstance(detect_result, (str, Path))
74
+ video_output = gr.Video(
75
+ value=detect_result if visible else None,
76
+ width=640,
77
+ height=480,
78
+ visible=visible,
79
+ label='Output',
80
+ )
81
+ clear_btn = gr.Button(
82
+ value='Clear',
83
+ scale=0,
84
+ visible=detect_result is not None,
85
+ )
86
+ return image_output, video_output, clear_btn
87
+
88
+
89
+ def get_download_csv_btn(csv_annotations_path: Optional[Path] = None):
90
+ download_csv_btn = gr.DownloadButton(
91
+ label='Download csv annotations for video',
92
+ value=csv_annotations_path,
93
+ scale=0,
94
+ visible=csv_annotations_path is not None,
95
+ )
96
+ return download_csv_btn
97
+
98
+ # =================== APPINTERFACE ==========================
99
+
100
+ css = '''
101
+ .gradio-container { width: 70% !important }
102
+ '''
103
+ with gr.Blocks(css=css) as demo:
104
+ gr.HTML("""<h3 style='text-align: center'>YOLOv11 Detector</h3>""")
105
+
106
+ model_state = gr.State({'model': default_model})
107
+ detect_result = gr.State(None)
108
+ csv_annotations_path = gr.State(None)
109
+
110
+ with gr.Row():
111
+ with gr.Column():
112
+ file_path = gr.File(file_types=['image', 'video'], file_count='single', label='Select an image or video')
113
+ file_link = gr.Textbox(label='Direct link to image or YouTube link')
114
+ model_name = gr.Radio(choices=MODEL_NAMES, value=MODEL_NAMES[0], label='Select YOLO model')
115
+ conf = gr.Slider(0, 1, value=0.5, step=0.05, label='Confidence')
116
+ iou = gr.Slider(0, 1, value=0.7, step=0.1, label='IOU')
117
+ status_message = gr.Textbox(value='Ready to go', label='Status')
118
+ detect_btn = gr.Button('Detect', interactive=True)
119
+
120
+ with gr.Column():
121
+ image_output, video_output, clear_btn = get_output_media_components()
122
+ download_csv_btn = get_download_csv_btn()
123
+
124
+ model_name.change(
125
+ fn=lambda: gr.update(interactive=False),
126
+ inputs=None,
127
+ outputs=[detect_btn],
128
+ ).then(
129
+ fn=change_model,
130
+ inputs=[model_state, model_name],
131
+ outputs=[status_message],
132
+ ).success(
133
+ fn=lambda: gr.update(interactive=True),
134
+ inputs=None,
135
+ outputs=[detect_btn],
136
+ )
137
+
138
+ detect_btn.click(
139
+ fn=detect,
140
+ inputs=[file_path, file_link, model_state, conf, iou],
141
+ outputs=[detect_result, status_message],
142
+ ).success(
143
+ fn=get_output_media_components,
144
+ inputs=[detect_result],
145
+ outputs=[image_output, video_output, clear_btn],
146
+ ).then(
147
+ fn=lambda: 'Ready to go',
148
+ inputs=None,
149
+ outputs=[status_message],
150
+ ).then(
151
+ fn=get_csv_annotate,
152
+ inputs=[detect_result],
153
+ outputs=[csv_annotations_path],
154
+ ).success(
155
+ fn=get_download_csv_btn,
156
+ inputs=[csv_annotations_path],
157
+ outputs=[download_csv_btn],
158
+ )
159
+
160
+ def clear_results_dir(detect_result):
161
+ if isinstance(detect_result, Path):
162
+ shutil.rmtree(detect_result.parent, ignore_errors=True)
163
+
164
+ clear_components = [image_output, video_output, clear_btn, download_csv_btn]
165
+ clear_btn.click(
166
+ fn=lambda: [gr.update(visible=False) for _ in range(len(clear_components))],
167
+ inputs=None,
168
+ outputs=clear_components,
169
+ ).then(
170
+ fn=clear_results_dir,
171
+ inputs=[detect_result],
172
+ outputs=None,
173
+ ).then(
174
+ fn=lambda: (None, None),
175
+ inputs=None,
176
+ outputs=[detect_result, csv_annotations_path]
177
+ )
178
+
179
+ gr.HTML("""<h3 style='text-align: center'>
180
+ <a href="https://github.com/sergey21000/yolo-detector" target='_blank'>GitHub Page</a></h3>
181
+ """)
182
+
183
  demo.launch(server_name='0.0.0.0') # debug=True
utils.py CHANGED
@@ -25,7 +25,7 @@ def download_model(model_name: str, models_dir: Path, models: dict) -> str:
25
 
26
 
27
  def detect_image(image_path: str, model: YOLO, conf: float, iou: float) -> np.ndarray:
28
- gr.Progress()(0.5, desc='Детекция изображения...')
29
  detections = model.predict(source=image_path, conf=conf, iou=iou)
30
  np_image = detections[0].plot()
31
  np_image = cv2.cvtColor(np_image, cv2.COLOR_BGR2RGB)
@@ -36,7 +36,7 @@ def detect_video(video_path_or_url: str, model: YOLO, conf: float, iou: float) -
36
  progress = gr.Progress()
37
  video_path = video_path_or_url
38
  if 'youtube.com' in video_path_or_url or 'youtu.be' in video_path_or_url:
39
- progress(0.001, desc='Загрузка видео с YouTube...')
40
  ydl_opts = {'format': 'bestvideo[height<=720]'}
41
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
42
  video_info_dict = ydl.extract_info(video_path_or_url, download=True)
@@ -60,7 +60,7 @@ def detect_video(video_path_or_url: str, model: YOLO, conf: float, iou: float) -
60
  frames_count = 0
61
  for result in generator:
62
  frames_count += 1
63
- progress((frames_count, num_frames), desc=f'Детекция видео, шаг {frames_count}/{num_frames}')
64
 
65
  file_name = Path(result.path).with_suffix('.avi').name
66
  result_video_path = Path(result.save_dir) / file_name
 
25
 
26
 
27
  def detect_image(image_path: str, model: YOLO, conf: float, iou: float) -> np.ndarray:
28
+ gr.Progress()(0.5, desc='Image detection...')
29
  detections = model.predict(source=image_path, conf=conf, iou=iou)
30
  np_image = detections[0].plot()
31
  np_image = cv2.cvtColor(np_image, cv2.COLOR_BGR2RGB)
 
36
  progress = gr.Progress()
37
  video_path = video_path_or_url
38
  if 'youtube.com' in video_path_or_url or 'youtu.be' in video_path_or_url:
39
+ progress(0.001, desc='Downloading videos from YouTube...')
40
  ydl_opts = {'format': 'bestvideo[height<=720]'}
41
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
42
  video_info_dict = ydl.extract_info(video_path_or_url, download=True)
 
60
  frames_count = 0
61
  for result in generator:
62
  frames_count += 1
63
+ progress((frames_count, num_frames), desc=f'Video detection, step {frames_count}/{num_frames}')
64
 
65
  file_name = Path(result.path).with_suffix('.avi').name
66
  result_video_path = Path(result.save_dir) / file_name