Marcus Vinicius Zerbini Canhaço
commited on
Commit
·
37eeee3
1
Parent(s):
c09ca6f
feat: atualização do detector com otimizações para GPU T4
Browse files
src/presentation/web/gradio_interface.py
CHANGED
@@ -5,10 +5,8 @@ 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 |
-
from huggingface_hub import hf_hub_download, list_repo_files, snapshot_download
|
9 |
-
import tempfile
|
10 |
-
import shutil
|
11 |
import logging
|
|
|
12 |
|
13 |
logger = logging.getLogger(__name__)
|
14 |
|
@@ -20,74 +18,49 @@ class GradioInterface:
|
|
20 |
self.notification_factory = NotificationServiceFactory()
|
21 |
self.default_fps = 2 if self.detector.device_type == "GPU" else 1
|
22 |
self.default_resolution = "640" if self.detector.device_type == "GPU" else "480"
|
23 |
-
self.dataset_id = "marcuscanhaco/weapon-test" # ID do dataset de teste
|
24 |
-
self.videos_cache_dir = Path(tempfile.gettempdir()) / "weapon_detection_videos"
|
25 |
self.is_huggingface = os.getenv('SPACE_ID') is not None
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
self.use_case = ProcessVideoUseCase(
|
28 |
detector=self.detector,
|
29 |
notification_factory=self.notification_factory,
|
30 |
default_fps=self.default_fps,
|
31 |
default_resolution=int(self.default_resolution)
|
32 |
)
|
33 |
-
|
34 |
-
# Criar diretório de cache se não existir
|
35 |
-
if self.is_huggingface:
|
36 |
-
self.videos_cache_dir.mkdir(parents=True, exist_ok=True)
|
37 |
-
logger.info(f"Diretório de cache criado em: {self.videos_cache_dir}")
|
38 |
-
|
39 |
-
def _download_dataset_videos(self) -> bool:
|
40 |
-
"""Baixa os vídeos do dataset do Hugging Face."""
|
41 |
-
try:
|
42 |
-
logger.info(f"Iniciando download do dataset {self.dataset_id}")
|
43 |
-
|
44 |
-
# Listar arquivos disponíveis no dataset
|
45 |
-
files = list_repo_files(self.dataset_id, repo_type="dataset")
|
46 |
-
logger.info(f"Arquivos encontrados no dataset: {files}")
|
47 |
-
|
48 |
-
# Baixar cada arquivo de vídeo individualmente
|
49 |
-
for file in files:
|
50 |
-
if file.lower().endswith(('.mp4', '.avi', '.mov', '.mkv')):
|
51 |
-
try:
|
52 |
-
local_file = hf_hub_download(
|
53 |
-
repo_id=self.dataset_id,
|
54 |
-
filename=file,
|
55 |
-
repo_type="dataset",
|
56 |
-
local_dir=str(self.videos_cache_dir)
|
57 |
-
)
|
58 |
-
logger.info(f"Arquivo baixado com sucesso: {local_file}")
|
59 |
-
except Exception as e:
|
60 |
-
logger.error(f"Erro ao baixar arquivo {file}: {str(e)}")
|
61 |
-
|
62 |
-
return True
|
63 |
-
|
64 |
-
except Exception as e:
|
65 |
-
logger.error(f"Erro ao baixar dataset: {str(e)}")
|
66 |
-
return False
|
67 |
|
68 |
def list_sample_videos(self) -> list:
|
69 |
"""Lista os vídeos de exemplo do dataset ou da pasta local."""
|
70 |
try:
|
71 |
-
video_extensions = ['.mp4', '.avi', '.mov', '.mkv']
|
72 |
-
videos = []
|
73 |
-
|
74 |
if self.is_huggingface:
|
75 |
-
logger.info("Ambiente Hugging Face detectado, usando dataset")
|
76 |
-
|
77 |
-
logger.info(f"Procurando vídeos em: {self.videos_cache_dir}")
|
78 |
-
# Listar todos os vídeos no diretório de cache
|
79 |
-
for ext in video_extensions:
|
80 |
-
for video_path in Path(self.videos_cache_dir).rglob(f'*{ext}'):
|
81 |
-
logger.info(f"Vídeo encontrado: {video_path}")
|
82 |
-
videos.append({
|
83 |
-
'path': str(video_path),
|
84 |
-
'name': video_path.name,
|
85 |
-
'ground_truth': '📼 Vídeo de Teste'
|
86 |
-
})
|
87 |
-
else:
|
88 |
-
logger.error("Falha ao baixar dataset")
|
89 |
else:
|
90 |
logger.info("Ambiente local detectado, usando pasta videos")
|
|
|
|
|
91 |
base_dir = Path("videos")
|
92 |
if not base_dir.exists():
|
93 |
os.makedirs(base_dir)
|
@@ -98,25 +71,31 @@ class GradioInterface:
|
|
98 |
for video_path in base_dir.glob(f'**/*{ext}'):
|
99 |
logger.info(f"Vídeo local encontrado: {video_path}")
|
100 |
videos.append({
|
101 |
-
'
|
102 |
'name': video_path.name,
|
103 |
'ground_truth': '📼 Vídeo de Teste'
|
104 |
})
|
105 |
-
|
106 |
-
|
107 |
-
return videos
|
108 |
|
109 |
except Exception as e:
|
110 |
logger.error(f"Erro ao listar vídeos: {str(e)}")
|
111 |
return []
|
112 |
|
113 |
-
def load_sample_video(self,
|
114 |
-
"""Carrega um vídeo de exemplo do
|
115 |
try:
|
116 |
-
if
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
return ""
|
121 |
except Exception as e:
|
122 |
logger.error(f"Erro ao carregar vídeo: {str(e)}")
|
@@ -232,7 +211,7 @@ class GradioInterface:
|
|
232 |
with gr.Row():
|
233 |
with gr.Column(scale=4):
|
234 |
gr.Video(
|
235 |
-
value=video['
|
236 |
format="mp4",
|
237 |
height=150,
|
238 |
interactive=False,
|
@@ -244,11 +223,9 @@ class GradioInterface:
|
|
244 |
size="sm"
|
245 |
).click(
|
246 |
fn=self.load_sample_video,
|
247 |
-
inputs=[gr.State(video['
|
248 |
outputs=[input_video]
|
249 |
)
|
250 |
-
|
251 |
-
|
252 |
|
253 |
# Configurar callback do botão
|
254 |
submit_btn.click(
|
|
|
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 |
import logging
|
9 |
+
import requests
|
10 |
|
11 |
logger = logging.getLogger(__name__)
|
12 |
|
|
|
18 |
self.notification_factory = NotificationServiceFactory()
|
19 |
self.default_fps = 2 if self.detector.device_type == "GPU" else 1
|
20 |
self.default_resolution = "640" if self.detector.device_type == "GPU" else "480"
|
|
|
|
|
21 |
self.is_huggingface = os.getenv('SPACE_ID') is not None
|
22 |
|
23 |
+
# URLs dos vídeos de exemplo do dataset
|
24 |
+
self.sample_videos = [
|
25 |
+
{
|
26 |
+
'url': 'https://huggingface.co/datasets/marcuscanhaco/weapon-test/resolve/main/risco_detectado/video_risco_1.mp4',
|
27 |
+
'name': 'Vídeo com Risco 1',
|
28 |
+
'ground_truth': '🚨 Risco Detectado'
|
29 |
+
},
|
30 |
+
{
|
31 |
+
'url': 'https://huggingface.co/datasets/marcuscanhaco/weapon-test/resolve/main/risco_detectado/video_risco_2.mp4',
|
32 |
+
'name': 'Vídeo com Risco 2',
|
33 |
+
'ground_truth': '🚨 Risco Detectado'
|
34 |
+
},
|
35 |
+
{
|
36 |
+
'url': 'https://huggingface.co/datasets/marcuscanhaco/weapon-test/resolve/main/seguro/video_seguro_1.mp4',
|
37 |
+
'name': 'Vídeo Seguro 1',
|
38 |
+
'ground_truth': '✅ Seguro'
|
39 |
+
},
|
40 |
+
{
|
41 |
+
'url': 'https://huggingface.co/datasets/marcuscanhaco/weapon-test/resolve/main/seguro/video_seguro_2.mp4',
|
42 |
+
'name': 'Vídeo Seguro 2',
|
43 |
+
'ground_truth': '✅ Seguro'
|
44 |
+
}
|
45 |
+
]
|
46 |
+
|
47 |
self.use_case = ProcessVideoUseCase(
|
48 |
detector=self.detector,
|
49 |
notification_factory=self.notification_factory,
|
50 |
default_fps=self.default_fps,
|
51 |
default_resolution=int(self.default_resolution)
|
52 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
def list_sample_videos(self) -> list:
|
55 |
"""Lista os vídeos de exemplo do dataset ou da pasta local."""
|
56 |
try:
|
|
|
|
|
|
|
57 |
if self.is_huggingface:
|
58 |
+
logger.info("Ambiente Hugging Face detectado, usando URLs do dataset")
|
59 |
+
return self.sample_videos
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
else:
|
61 |
logger.info("Ambiente local detectado, usando pasta videos")
|
62 |
+
video_extensions = ['.mp4', '.avi', '.mov', '.mkv']
|
63 |
+
videos = []
|
64 |
base_dir = Path("videos")
|
65 |
if not base_dir.exists():
|
66 |
os.makedirs(base_dir)
|
|
|
71 |
for video_path in base_dir.glob(f'**/*{ext}'):
|
72 |
logger.info(f"Vídeo local encontrado: {video_path}")
|
73 |
videos.append({
|
74 |
+
'url': str(video_path),
|
75 |
'name': video_path.name,
|
76 |
'ground_truth': '📼 Vídeo de Teste'
|
77 |
})
|
78 |
+
|
79 |
+
return videos
|
|
|
80 |
|
81 |
except Exception as e:
|
82 |
logger.error(f"Erro ao listar vídeos: {str(e)}")
|
83 |
return []
|
84 |
|
85 |
+
def load_sample_video(self, video_url: str) -> str:
|
86 |
+
"""Carrega um vídeo de exemplo do dataset ou pasta local."""
|
87 |
try:
|
88 |
+
if not video_url:
|
89 |
+
return ""
|
90 |
+
|
91 |
+
if video_url.startswith('http'):
|
92 |
+
logger.info(f"Carregando vídeo da URL: {video_url}")
|
93 |
+
return video_url
|
94 |
+
elif os.path.exists(video_url):
|
95 |
+
logger.info(f"Carregando vídeo local: {video_url}")
|
96 |
+
return video_url
|
97 |
+
|
98 |
+
logger.warning(f"Vídeo não encontrado: {video_url}")
|
99 |
return ""
|
100 |
except Exception as e:
|
101 |
logger.error(f"Erro ao carregar vídeo: {str(e)}")
|
|
|
211 |
with gr.Row():
|
212 |
with gr.Column(scale=4):
|
213 |
gr.Video(
|
214 |
+
value=video['url'],
|
215 |
format="mp4",
|
216 |
height=150,
|
217 |
interactive=False,
|
|
|
223 |
size="sm"
|
224 |
).click(
|
225 |
fn=self.load_sample_video,
|
226 |
+
inputs=[gr.State(video['url'])],
|
227 |
outputs=[input_video]
|
228 |
)
|
|
|
|
|
229 |
|
230 |
# Configurar callback do botão
|
231 |
submit_btn.click(
|