Marcus Vinicius Zerbini Canhaço
commited on
Commit
·
4add9f7
1
Parent(s):
cd2dff3
feat: atualização do detector com otimizações para GPU T4
Browse files- requirements.txt +1 -1
- src/presentation/web/gradio_interface.py +57 -32
requirements.txt
CHANGED
@@ -18,7 +18,7 @@ gradio_client
|
|
18 |
h11
|
19 |
httpcore
|
20 |
httpx
|
21 |
-
huggingface-hub
|
22 |
idna
|
23 |
itsdangerous
|
24 |
Jinja2
|
|
|
18 |
h11
|
19 |
httpcore
|
20 |
httpx
|
21 |
+
huggingface-hub>=0.20.3
|
22 |
idna
|
23 |
itsdangerous
|
24 |
Jinja2
|
src/presentation/web/gradio_interface.py
CHANGED
@@ -5,6 +5,9 @@ from pathlib import Path
|
|
5 |
from src.application.use_cases.process_video import ProcessVideoUseCase, ProcessVideoRequest
|
6 |
from src.infrastructure.services.weapon_detector import WeaponDetectorService
|
7 |
from src.infrastructure.services.notification_services import NotificationServiceFactory
|
|
|
|
|
|
|
8 |
|
9 |
class GradioInterface:
|
10 |
"""Interface Gradio usando Clean Architecture."""
|
@@ -14,6 +17,9 @@ class GradioInterface:
|
|
14 |
self.notification_factory = NotificationServiceFactory()
|
15 |
self.default_fps = 2 if self.detector.device_type == "GPU" else 1
|
16 |
self.default_resolution = "640" if self.detector.device_type == "GPU" else "480"
|
|
|
|
|
|
|
17 |
|
18 |
self.use_case = ProcessVideoUseCase(
|
19 |
detector=self.detector,
|
@@ -21,37 +27,60 @@ class GradioInterface:
|
|
21 |
default_fps=self.default_fps,
|
22 |
default_resolution=int(self.default_resolution)
|
23 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
25 |
def list_sample_videos(self) -> list:
|
26 |
-
"""Lista os vídeos de exemplo
|
27 |
-
|
28 |
-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
return []
|
31 |
-
|
32 |
-
video_extensions = ['.mp4', '.avi', '.mov', '.mkv']
|
33 |
-
videos = []
|
34 |
-
|
35 |
-
# Procurar em subdiretórios específicos
|
36 |
-
for status_dir in ['seguro', 'risco_detectado']:
|
37 |
-
dir_path = video_dir / status_dir
|
38 |
-
if dir_path.exists():
|
39 |
-
for ext in video_extensions:
|
40 |
-
for video_path in dir_path.glob(f'*{ext}'):
|
41 |
-
videos.append({
|
42 |
-
'path': str(video_path),
|
43 |
-
'name': video_path.name,
|
44 |
-
'ground_truth': '✅ SEGURO (Ground Truth)' if status_dir == 'seguro' else '⚠️ RISCO DETECTADO (Ground Truth)'
|
45 |
-
})
|
46 |
-
|
47 |
-
return videos
|
48 |
-
|
49 |
def load_sample_video(self, video_path: str) -> str:
|
50 |
-
"""Carrega um vídeo de exemplo."""
|
51 |
-
|
52 |
return video_path
|
53 |
-
|
54 |
-
return None
|
55 |
|
56 |
def create_interface(self) -> gr.Blocks:
|
57 |
"""Cria a interface Gradio."""
|
@@ -154,16 +183,14 @@ class GradioInterface:
|
|
154 |
with gr.Group():
|
155 |
gr.Markdown("### Vídeos de Exemplo")
|
156 |
with gr.Row():
|
157 |
-
with gr.Column(scale=
|
158 |
gr.Markdown("#### Vídeo")
|
159 |
-
with gr.Column(scale=2):
|
160 |
-
gr.Markdown("#### Status Real")
|
161 |
with gr.Column(scale=1):
|
162 |
gr.Markdown("#### Ação")
|
163 |
|
164 |
for video in sample_videos:
|
165 |
with gr.Row():
|
166 |
-
with gr.Column(scale=
|
167 |
gr.Video(
|
168 |
value=video['path'],
|
169 |
format="mp4",
|
@@ -171,8 +198,6 @@ class GradioInterface:
|
|
171 |
interactive=False,
|
172 |
show_label=False
|
173 |
)
|
174 |
-
with gr.Column(scale=2, min_width=200):
|
175 |
-
gr.Markdown(video['ground_truth'])
|
176 |
with gr.Column(scale=1, min_width=100):
|
177 |
gr.Button(
|
178 |
"📥 Carregar",
|
|
|
5 |
from src.application.use_cases.process_video import ProcessVideoUseCase, ProcessVideoRequest
|
6 |
from src.infrastructure.services.weapon_detector import WeaponDetectorService
|
7 |
from src.infrastructure.services.notification_services import NotificationServiceFactory
|
8 |
+
from huggingface_hub import hf_hub_download, list_repo_files, snapshot_download
|
9 |
+
import tempfile
|
10 |
+
import shutil
|
11 |
|
12 |
class GradioInterface:
|
13 |
"""Interface Gradio usando Clean Architecture."""
|
|
|
17 |
self.notification_factory = NotificationServiceFactory()
|
18 |
self.default_fps = 2 if self.detector.device_type == "GPU" else 1
|
19 |
self.default_resolution = "640" if self.detector.device_type == "GPU" else "480"
|
20 |
+
self.dataset_id = "marcuscanhaco/weapon-test" # ID do dataset de teste
|
21 |
+
self.videos_cache_dir = Path(tempfile.gettempdir()) / "weapon_detection_videos"
|
22 |
+
self.is_huggingface = os.getenv('SPACE_ID') is not None
|
23 |
|
24 |
self.use_case = ProcessVideoUseCase(
|
25 |
detector=self.detector,
|
|
|
27 |
default_fps=self.default_fps,
|
28 |
default_resolution=int(self.default_resolution)
|
29 |
)
|
30 |
+
|
31 |
+
# Criar diretório de cache se não existir
|
32 |
+
if self.is_huggingface:
|
33 |
+
self.videos_cache_dir.mkdir(parents=True, exist_ok=True)
|
34 |
+
|
35 |
+
def _download_dataset_videos(self) -> None:
|
36 |
+
"""Baixa os vídeos do dataset do Hugging Face."""
|
37 |
+
try:
|
38 |
+
# Baixar todo o dataset para o diretório de cache
|
39 |
+
snapshot_download(
|
40 |
+
repo_id=self.dataset_id,
|
41 |
+
repo_type="dataset",
|
42 |
+
local_dir=str(self.videos_cache_dir),
|
43 |
+
ignore_patterns=["*.git*", "README.md"]
|
44 |
+
)
|
45 |
+
except Exception as e:
|
46 |
+
print(f"Erro ao baixar dataset: {str(e)}")
|
47 |
|
48 |
def list_sample_videos(self) -> list:
|
49 |
+
"""Lista os vídeos de exemplo do dataset ou da pasta local."""
|
50 |
+
try:
|
51 |
+
video_extensions = ['.mp4', '.avi', '.mov', '.mkv']
|
52 |
+
videos = []
|
53 |
+
|
54 |
+
if self.is_huggingface:
|
55 |
+
# No Hugging Face, usar o dataset
|
56 |
+
self._download_dataset_videos()
|
57 |
+
base_dir = self.videos_cache_dir
|
58 |
+
else:
|
59 |
+
# Localmente, usar a pasta videos
|
60 |
+
base_dir = Path("videos")
|
61 |
+
if not base_dir.exists():
|
62 |
+
os.makedirs(base_dir)
|
63 |
+
|
64 |
+
# Listar todos os vídeos diretamente
|
65 |
+
for ext in video_extensions:
|
66 |
+
for video_path in base_dir.glob(f'**/*{ext}'):
|
67 |
+
videos.append({
|
68 |
+
'path': str(video_path),
|
69 |
+
'name': video_path.name,
|
70 |
+
'ground_truth': '📼 Vídeo de Teste'
|
71 |
+
})
|
72 |
+
|
73 |
+
return videos
|
74 |
+
|
75 |
+
except Exception as e:
|
76 |
+
print(f"Erro ao listar vídeos: {str(e)}")
|
77 |
return []
|
78 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
def load_sample_video(self, video_path: str) -> str:
|
80 |
+
"""Carrega um vídeo de exemplo do cache ou pasta local."""
|
81 |
+
if video_path and os.path.exists(video_path):
|
82 |
return video_path
|
83 |
+
return ""
|
|
|
84 |
|
85 |
def create_interface(self) -> gr.Blocks:
|
86 |
"""Cria a interface Gradio."""
|
|
|
183 |
with gr.Group():
|
184 |
gr.Markdown("### Vídeos de Exemplo")
|
185 |
with gr.Row():
|
186 |
+
with gr.Column(scale=4):
|
187 |
gr.Markdown("#### Vídeo")
|
|
|
|
|
188 |
with gr.Column(scale=1):
|
189 |
gr.Markdown("#### Ação")
|
190 |
|
191 |
for video in sample_videos:
|
192 |
with gr.Row():
|
193 |
+
with gr.Column(scale=4):
|
194 |
gr.Video(
|
195 |
value=video['path'],
|
196 |
format="mp4",
|
|
|
198 |
interactive=False,
|
199 |
show_label=False
|
200 |
)
|
|
|
|
|
201 |
with gr.Column(scale=1, min_width=100):
|
202 |
gr.Button(
|
203 |
"📥 Carregar",
|