Marcus Vinicius Zerbini Canhaço commited on
Commit
ea56678
·
1 Parent(s): 87bc3e0

feat: atualização do detector com otimizações para GPU T4

Browse files
README.md CHANGED
@@ -19,7 +19,7 @@ app_port: 7860
19
 
20
  <div align="center">
21
 
22
- # FIAP VisionGuard - Weapon Detection
23
 
24
  *Sistema de Detecção de Armas e Objetos Perigosos*
25
 
 
19
 
20
  <div align="center">
21
 
22
+ # FIAP VisionGuard - Risk Detection - Hackatoon 1IADT
23
 
24
  *Sistema de Detecção de Armas e Objetos Perigosos*
25
 
src/domain/detectors/gpu.py CHANGED
@@ -164,21 +164,21 @@ class WeaponDetectorGPU(BaseDetector):
164
 
165
  # Processar frames em batch
166
  t0 = time.time()
167
- batch_size = 8 # Reduzido para evitar erros de memória
168
  detections_by_frame = []
169
 
170
  for i in range(0, len(frames), batch_size):
171
- batch_frames = frames[i:i + batch_size]
172
- batch_pil_frames = []
173
-
174
- # Preparar batch
175
- for frame in batch_frames:
176
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
177
- frame_pil = Image.fromarray(frame_rgb)
178
- frame_pil = self._preprocess_image(frame_pil)
179
- batch_pil_frames.append(frame_pil)
180
-
181
  try:
 
 
 
 
 
 
 
 
 
 
182
  # Processar batch
183
  batch_inputs = self.owlv2_processor(
184
  images=batch_pil_frames,
@@ -190,6 +190,11 @@ class WeaponDetectorGPU(BaseDetector):
190
  for key, val in batch_inputs.items()
191
  }
192
 
 
 
 
 
 
193
  # Inferência em batch
194
  with torch.no_grad():
195
  inputs = {**batch_inputs, **self.processed_text}
@@ -222,18 +227,16 @@ class WeaponDetectorGPU(BaseDetector):
222
  "confidence": round(score_val * 100, 2),
223
  "box": [int(x) for x in box.tolist()],
224
  "label": label_text,
 
225
  "timestamp": (i + frame_idx) / (fps or 2)
226
  })
227
 
228
  if frame_detections:
229
  frame_detections = self._apply_nms(frame_detections)
230
- detections_by_frame.append({
231
- "frame": i + frame_idx,
232
- "detections": frame_detections
233
- })
234
 
235
  except RuntimeError as e:
236
- logger.error(f"Erro no processamento do batch: {str(e)}")
237
  if "out of memory" in str(e):
238
  torch.cuda.empty_cache()
239
  gc.collect()
@@ -257,6 +260,28 @@ class WeaponDetectorGPU(BaseDetector):
257
  logger.error(f"Erro ao processar vídeo: {str(e)}")
258
  return video_path, metrics
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  def _preprocess_image(self, image: Image.Image) -> Image.Image:
261
  """Pré-processa a imagem para o formato esperado pelo modelo."""
262
  try:
 
164
 
165
  # Processar frames em batch
166
  t0 = time.time()
167
+ batch_size = 4 # Reduzido para evitar erros de shape
168
  detections_by_frame = []
169
 
170
  for i in range(0, len(frames), batch_size):
 
 
 
 
 
 
 
 
 
 
171
  try:
172
+ batch_frames = frames[i:i + batch_size]
173
+ batch_pil_frames = []
174
+
175
+ # Preparar batch
176
+ for frame in batch_frames:
177
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
178
+ frame_pil = Image.fromarray(frame_rgb)
179
+ frame_pil = self._preprocess_image(frame_pil)
180
+ batch_pil_frames.append(frame_pil)
181
+
182
  # Processar batch
183
  batch_inputs = self.owlv2_processor(
184
  images=batch_pil_frames,
 
190
  for key, val in batch_inputs.items()
191
  }
192
 
193
+ # Validar shapes antes da inferência
194
+ if not self._validate_batch_shapes(batch_inputs):
195
+ logger.warning(f"Shape inválido detectado no batch {i}, pulando...")
196
+ continue
197
+
198
  # Inferência em batch
199
  with torch.no_grad():
200
  inputs = {**batch_inputs, **self.processed_text}
 
227
  "confidence": round(score_val * 100, 2),
228
  "box": [int(x) for x in box.tolist()],
229
  "label": label_text,
230
+ "frame": i + frame_idx,
231
  "timestamp": (i + frame_idx) / (fps or 2)
232
  })
233
 
234
  if frame_detections:
235
  frame_detections = self._apply_nms(frame_detections)
236
+ detections_by_frame.extend(frame_detections)
 
 
 
237
 
238
  except RuntimeError as e:
239
+ logger.error(f"Erro no processamento do batch {i}: {str(e)}")
240
  if "out of memory" in str(e):
241
  torch.cuda.empty_cache()
242
  gc.collect()
 
260
  logger.error(f"Erro ao processar vídeo: {str(e)}")
261
  return video_path, metrics
262
 
263
+ def _validate_batch_shapes(self, batch_inputs: Dict) -> bool:
264
+ """Valida os shapes dos tensores do batch."""
265
+ try:
266
+ pixel_values = batch_inputs.get("pixel_values")
267
+ if pixel_values is None:
268
+ return False
269
+
270
+ batch_size = pixel_values.shape[0]
271
+ if batch_size == 0:
272
+ return False
273
+
274
+ # Validar dimensões esperadas
275
+ expected_dims = 4 # [batch_size, channels, height, width]
276
+ if len(pixel_values.shape) != expected_dims:
277
+ return False
278
+
279
+ return True
280
+
281
+ except Exception as e:
282
+ logger.error(f"Erro ao validar shapes do batch: {str(e)}")
283
+ return False
284
+
285
  def _preprocess_image(self, image: Image.Image) -> Image.Image:
286
  """Pré-processa a imagem para o formato esperado pelo modelo."""
287
  try:
src/presentation/web/gradio_interface.py CHANGED
@@ -127,7 +127,7 @@ class GradioInterface:
127
 
128
  def create_interface(self) -> gr.Blocks:
129
  """Cria a interface Gradio."""
130
- title = "Detector de Riscos em Vídeos"
131
  sample_videos = self.list_sample_videos()
132
 
133
  with gr.Blocks(
@@ -135,7 +135,7 @@ class GradioInterface:
135
  theme=gr.themes.Ocean(),
136
  css="footer {display: none !important}"
137
  ) as demo:
138
- gr.Markdown(f"""# 🚨 {title}
139
 
140
  Faça upload de um vídeo para detectar objetos perigosos.
141
  Opcionalmente, configure notificações para receber alertas em caso de detecções.
@@ -309,7 +309,24 @@ class GradioInterface:
309
  status_html += f"<li>... e mais {len(response.detection_result.detections) - 5} detecção(ões)</li>"
310
  status_html += "</ul></div>"
311
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  return (
313
  response.status_message,
314
- status_html
315
  )
 
127
 
128
  def create_interface(self) -> gr.Blocks:
129
  """Cria a interface Gradio."""
130
+ title = "FIAP VisionGuard - Risk Detection - Hackatoon 1IADT"
131
  sample_videos = self.list_sample_videos()
132
 
133
  with gr.Blocks(
 
135
  theme=gr.themes.Ocean(),
136
  css="footer {display: none !important}"
137
  ) as demo:
138
+ gr.Markdown(f"""# 🎯 {title} 🔪🔫
139
 
140
  Faça upload de um vídeo para detectar objetos perigosos.
141
  Opcionalmente, configure notificações para receber alertas em caso de detecções.
 
309
  status_html += f"<li>... e mais {len(response.detection_result.detections) - 5} detecção(ões)</li>"
310
  status_html += "</ul></div>"
311
 
312
+ # Preparar JSON técnico
313
+ technical_data = {
314
+ "device_type": response.detection_result.device_type,
315
+ "total_detections": len(response.detection_result.detections),
316
+ "frames_analyzed": response.detection_result.frames_analyzed,
317
+ "total_time": round(response.detection_result.total_time, 2),
318
+ "detections": [
319
+ {
320
+ "label": det.label,
321
+ "confidence": round(det.confidence * 100 if det.confidence <= 1.0 else det.confidence, 2),
322
+ "frame": det.frame,
323
+ "timestamp": round(det.timestamp, 2) if hasattr(det, "timestamp") else None
324
+ }
325
+ for det in response.detection_result.detections[:10] # Limitar a 10 detecções no JSON
326
+ ]
327
+ }
328
+
329
  return (
330
  response.status_message,
331
+ technical_data # Retorna dicionário Python em vez de HTML
332
  )