Marcus Vinicius Zerbini Canhaço commited on
Commit
346e896
·
1 Parent(s): a83ece3

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

Browse files
.env.example CHANGED
@@ -29,7 +29,6 @@ NOTIFICATION_EMAIL="" # E-mail para envio de notificações
29
  HUGGING_FACE_TOKEN="" # Token do Hugging Face para acesso aos modelos
30
  TOKENIZERS_PARALLELISM=false
31
  MODEL_CACHE_DIR=./.model_cache
32
- BATCH_SIZE=16
33
  MAX_WORKERS=2
34
  USE_HALF_PRECISION=true
35
  DETECTION_CONFIDENCE_THRESHOLD=0.5
@@ -50,3 +49,42 @@ CUDA_VISIBLE_DEVICES=0
50
  TORCH_CUDA_ARCH_LIST="7.5"
51
  NVIDIA_VISIBLE_DEVICES=all
52
  NVIDIA_DRIVER_CAPABILITIES=compute,utility
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  HUGGING_FACE_TOKEN="" # Token do Hugging Face para acesso aos modelos
30
  TOKENIZERS_PARALLELISM=false
31
  MODEL_CACHE_DIR=./.model_cache
 
32
  MAX_WORKERS=2
33
  USE_HALF_PRECISION=true
34
  DETECTION_CONFIDENCE_THRESHOLD=0.5
 
49
  TORCH_CUDA_ARCH_LIST="7.5"
50
  NVIDIA_VISIBLE_DEVICES=all
51
  NVIDIA_DRIVER_CAPABILITIES=compute,utility
52
+
53
+ # Configurações do modelo
54
+ MODEL_NAME=google/owlv2-base-patch16
55
+ DEVICE=cuda:0
56
+ THRESHOLD=0.3
57
+ FPS=2
58
+ RESOLUTION=640
59
+
60
+ # Configurações de logging
61
+ LOG_LEVEL=INFO
62
+ LOG_FORMAT=%(asctime)s - %(name)s - %(levelname)s - %(message)s
63
+
64
+ # Configurações de memória
65
+ MAX_MEMORY=8GB
66
+ OFFLOAD_FOLDER=offload
67
+
68
+ # Configurações de otimização
69
+ TORCH_COMPILE=false
70
+ HALF_PRECISION=true
71
+
72
+ # Configurações de interface
73
+ THEME=default
74
+ ALLOW_FLAGGING=false
75
+ ALLOW_SCREENSHOT=true
76
+ SHOW_API=true
77
+
78
+ # Configurações de segurança
79
+ AUTHENTICATION=false
80
+ USERNAME=admin
81
+ PASSWORD=admin
82
+
83
+ # Configurações de monitoramento
84
+ ENABLE_QUEUE=true
85
+ MAX_THREADS=4
86
+ CONCURRENCY_COUNT=1
87
+
88
+ # Configurações de armazenamento
89
+ SAVE_OUTPUTS=false
90
+ OUTPUT_DIR=outputs
.env.huggingface CHANGED
@@ -1,7 +1,9 @@
1
  # Configurações do Modelo
2
- MODEL_CACHE_DIR=./.model_cache
3
- BATCH_SIZE=16
4
  USE_HALF_PRECISION=true
 
 
 
5
  DETECTION_CONFIDENCE_THRESHOLD=0.5
6
 
7
  # Configurações de Cache
 
1
  # Configurações do Modelo
2
+ MODEL_NAME=google/owlv2-base-patch16
 
3
  USE_HALF_PRECISION=true
4
+ MAX_WORKERS=2
5
+ TOKENIZERS_PARALLELISM=false
6
+ MODEL_CACHE_DIR=./.model_cache
7
  DETECTION_CONFIDENCE_THRESHOLD=0.5
8
 
9
  # Configurações de Cache
docs/architecture/overview.md CHANGED
@@ -232,6 +232,7 @@ sequenceDiagram
232
  Det->>Det: Extrai Frames
233
  loop Cada Frame
234
  Det->>Det: Detecta Objetos
 
235
  end
236
  Det->>App: Retorna Resultados
237
  App->>Not: Envia Notificação
@@ -251,7 +252,7 @@ sequenceDiagram
251
  - Fácil localização de problemas
252
 
253
  3. **Escalabilidade**
254
- - Novos detectores sem mudanças no core
255
  - Múltiplos backends de processamento
256
  - Sistemas de notificação plugáveis
257
 
@@ -317,15 +318,18 @@ sequenceDiagram
317
 
318
  ### GPU
319
 
320
- - Detecção automática de hardware
321
- - Configurações específicas para T4 e Zero-GPU
322
- - Gerenciamento de memória otimizado
 
 
323
 
324
  ### CPU
325
 
326
- - Fallback automático
327
- - Otimizações para processamento em CPU
328
  - Cache de resultados
 
329
 
330
  ## Diagrama de Componentes
331
 
 
232
  Det->>Det: Extrai Frames
233
  loop Cada Frame
234
  Det->>Det: Detecta Objetos
235
+ Det->>Det: Limpa Memória
236
  end
237
  Det->>App: Retorna Resultados
238
  App->>Not: Envia Notificação
 
252
  - Fácil localização de problemas
253
 
254
  3. **Escalabilidade**
255
+ - Processamento frame a frame confiável
256
  - Múltiplos backends de processamento
257
  - Sistemas de notificação plugáveis
258
 
 
318
 
319
  ### GPU
320
 
321
+ - Processamento frame a frame otimizado
322
+ - Memória pinned
323
+ - Async data loading
324
+ - Cache de modelos e frames
325
+ - Gerenciamento eficiente de memória
326
 
327
  ### CPU
328
 
329
+ - Processamento sequencial otimizado
330
+ - NumPy vectorization
331
  - Cache de resultados
332
+ - Otimização de memória
333
 
334
  ## Diagrama de Componentes
335
 
docs/faq.md CHANGED
@@ -5,7 +5,7 @@
5
  ### Como o sistema funciona?
6
 
7
  O sistema utiliza um modelo de IA (OWL-ViT) para detectar objetos de risco em vídeos.
8
- O processamento pode ser feito em GPU ou CPU, com otimizações específicas para cada caso.
9
 
10
  ### O que é o OWL-ViT?
11
 
@@ -41,17 +41,73 @@ O modelo `owlv2-base-patch16-ensemble` apresenta incompatibilidades com processa
41
  model = model.to(device='cuda', dtype=torch.float16)
42
  ```
43
 
44
- #### Comparação de Versões
45
-
46
- 1. **Modelo Base**
47
- - Mais estável
48
- - Menor consumo de memória
49
- - Compatível com mais GPUs
50
-
51
- 2. **Modelo Ensemble**
52
- - Maior precisão
53
- - Requer mais recursos
54
- - Melhor para CPU
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
  ### Como fazer queries efetivas para o OWL-ViT?
57
 
@@ -129,8 +185,8 @@ pip install torch torchvision --extra-index-url https://download.pytorch.org/whl
129
 
130
  **Solução**:
131
 
132
- - Reduza o tamanho do batch
133
- - Diminua a resolução
134
  - Ajuste `GPU_MEMORY_FRACTION` no `.env`
135
 
136
  ## Performance
@@ -139,13 +195,14 @@ pip install torch torchvision --extra-index-url https://download.pytorch.org/whl
139
 
140
  #### Ajustes GPU
141
 
142
- - Use batch processing
143
  - Ative half precision
144
- - Otimize o cache de modelos
 
145
 
146
  #### Ajustes CPU
147
 
148
- - Ative multiprocessing
149
  - Use vetorização NumPy
150
  - Implemente cache de resultados
151
 
@@ -154,7 +211,7 @@ pip install torch torchvision --extra-index-url https://download.pytorch.org/whl
154
  ```plaintext
155
  // Configurações para GPU T4
156
  GPU_MEMORY_FRACTION=0.9
157
- BATCH_SIZE=16
158
  USE_HALF_PRECISION=true
159
 
160
  // Configurações para CPU
@@ -163,6 +220,13 @@ CACHE_SIZE=1000
163
  USE_MULTIPROCESSING=true
164
  ```
165
 
 
 
 
 
 
 
 
166
  ## Deployment
167
 
168
  ### Processo de Deploy no Hugging Face
 
5
  ### Como o sistema funciona?
6
 
7
  O sistema utiliza um modelo de IA (OWL-ViT) para detectar objetos de risco em vídeos.
8
+ O processamento é feito frame a frame em GPU ou CPU, com otimizações específicas para cada caso.
9
 
10
  ### O que é o OWL-ViT?
11
 
 
41
  model = model.to(device='cuda', dtype=torch.float16)
42
  ```
43
 
44
+ #### Problemas com Batch Processing
45
+
46
+ O processamento em batch apresenta instabilidades conhecidas:
47
+
48
+ 1. **Erros de Shape**
49
+ ```
50
+ ERROR: shape '[4, 21, 512]' is invalid for input of size 44544
51
+ ERROR: shape '[2, 43, 512]' is invalid for input of size 44544
52
+ ```
53
+
54
+ 2. **Causas Identificadas**
55
+ - Inconsistência no padding de imagens em batch
56
+ - Variações no tamanho dos tensores de entrada
57
+ - Incompatibilidade com certas configurações de GPU
58
+
59
+ 3. **Solução Recomendada**
60
+ ```python
61
+ # Processamento seguro frame a frame
62
+ batch_size = 1 # Processa um frame por vez
63
+ ```
64
+
65
+ 4. **Benefícios do Processamento Individual**
66
+ - Maior estabilidade
67
+ - Melhor gerenciamento de memória
68
+ - Resultados mais consistentes
69
+ - Facilidade de debug
70
+ - Menor chance de OOM (Out of Memory)
71
+
72
+ 5. **Trade-offs**
73
+ - Performance levemente reduzida
74
+ - Processamento mais serializado
75
+ - Maior tempo total de execução
76
+
77
+ #### Comparação de Abordagens
78
+
79
+ | Aspecto | Batch Processing | Frame a Frame |
80
+ |---------|------------------|---------------|
81
+ | Velocidade | Mais rápido (quando funciona) | Mais lento |
82
+ | Estabilidade | Baixa | Alta |
83
+ | Uso de Memória | Alto/Imprevisível | Baixo/Consistente |
84
+ | Confiabilidade | Baixa | Alta |
85
+ | Debug | Difícil | Fácil |
86
+
87
+ #### Recomendações de Uso
88
+
89
+ 1. **Produção**
90
+ ```python
91
+ # Configuração recomendada para produção
92
+ batch_size = 1
93
+ resolution = 640
94
+ fps = 2
95
+ ```
96
+
97
+ 2. **Desenvolvimento**
98
+ ```python
99
+ # Configuração para testes
100
+ batch_size = 1
101
+ resolution = 480
102
+ fps = 1
103
+ ```
104
+
105
+ 3. **Monitoramento**
106
+ ```python
107
+ # Log de progresso a cada 10 frames
108
+ if i % 10 == 0:
109
+ logger.info(f"Processados {i}/{len(frames)} frames")
110
+ ```
111
 
112
  ### Como fazer queries efetivas para o OWL-ViT?
113
 
 
185
 
186
  **Solução**:
187
 
188
+ - Use processamento frame a frame (padrão)
189
+ - Diminua a resolução se necessário
190
  - Ajuste `GPU_MEMORY_FRACTION` no `.env`
191
 
192
  ## Performance
 
195
 
196
  #### Ajustes GPU
197
 
198
+ - Processamento frame a frame otimizado
199
  - Ative half precision
200
+ - Otimize o cache de modelos e frames
201
+ - Gerenciamento eficiente de memória
202
 
203
  #### Ajustes CPU
204
 
205
+ - Processamento sequencial otimizado
206
  - Use vetorização NumPy
207
  - Implemente cache de resultados
208
 
 
211
  ```plaintext
212
  // Configurações para GPU T4
213
  GPU_MEMORY_FRACTION=0.9
214
+ BATCH_SIZE=1 # Processamento frame a frame
215
  USE_HALF_PRECISION=true
216
 
217
  // Configurações para CPU
 
220
  USE_MULTIPROCESSING=true
221
  ```
222
 
223
+ ### Sistema de Monitoramento
224
+
225
+ - Use os logs em `logs/app.log` para acompanhar o processamento frame a frame
226
+ - Monitore GPU com `nvidia-smi`
227
+ - Verifique métricas no Hugging Face
228
+ - Acompanhe logs de progresso a cada 10 frames
229
+
230
  ## Deployment
231
 
232
  ### Processo de Deploy no Hugging Face
src/domain/detectors/gpu.py CHANGED
@@ -166,24 +166,19 @@ class WeaponDetectorGPU(BaseDetector):
166
  # Calcular duração do vídeo
167
  metrics["video_duration"] = len(frames) / (fps or 2)
168
 
169
- # Processar frames em batch
170
  t0 = time.time()
171
- batch_size = 1 # Processar um frame por vez para garantir compatibilidade
172
  detections_by_frame = []
173
 
174
  # Pré-alocar tensores para evitar alocações frequentes
175
  with torch.cuda.device(self.device):
176
- torch.cuda.empty_cache() # Limpar memória antes de começar
177
 
178
- for i in range(0, len(frames)):
179
  try:
180
- # Preparar frame com otimização de memória
181
- frame = frames[i]
182
- if isinstance(frame, np.ndarray):
183
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
184
- frame_pil = Image.fromarray(frame_rgb)
185
- else:
186
- frame_pil = frame
187
  frame_pil = self._preprocess_image(frame_pil)
188
 
189
  # Processar frame
@@ -206,13 +201,13 @@ class WeaponDetectorGPU(BaseDetector):
206
  outputs=outputs,
207
  target_sizes=target_sizes,
208
  threshold=threshold
209
- )
210
 
211
  # Processar resultados
212
- if len(results[0]["scores"]) > 0:
213
- scores = results[0]["scores"]
214
- boxes = results[0]["boxes"]
215
- labels = results[0]["labels"]
216
 
217
  frame_detections = []
218
  for score, box, label in zip(scores, boxes, labels):
@@ -231,7 +226,7 @@ class WeaponDetectorGPU(BaseDetector):
231
  if frame_detections:
232
  frame_detections = self._apply_nms(frame_detections)
233
  detections_by_frame.extend(frame_detections)
234
-
235
  except Exception as e:
236
  logger.error(f"Erro ao processar frame {i}: {str(e)}")
237
  continue
@@ -259,28 +254,6 @@ class WeaponDetectorGPU(BaseDetector):
259
  logger.error(f"Erro ao processar vídeo: {str(e)}")
260
  return video_path, metrics
261
 
262
- def _validate_batch_shapes(self, batch_inputs: Dict) -> bool:
263
- """Valida os shapes dos tensores do batch."""
264
- try:
265
- pixel_values = batch_inputs.get("pixel_values")
266
- if pixel_values is None:
267
- return False
268
-
269
- batch_size = pixel_values.shape[0]
270
- if batch_size == 0:
271
- return False
272
-
273
- # Validar dimensões esperadas
274
- expected_dims = 4 # [batch_size, channels, height, width]
275
- if len(pixel_values.shape) != expected_dims:
276
- return False
277
-
278
- return True
279
-
280
- except Exception as e:
281
- logger.error(f"Erro ao validar shapes do batch: {str(e)}")
282
- return False
283
-
284
  def _preprocess_image(self, image: Image.Image) -> Image.Image:
285
  """Pré-processa a imagem para o formato esperado pelo modelo."""
286
  try:
 
166
  # Calcular duração do vídeo
167
  metrics["video_duration"] = len(frames) / (fps or 2)
168
 
169
+ # Processar frames individualmente
170
  t0 = time.time()
 
171
  detections_by_frame = []
172
 
173
  # Pré-alocar tensores para evitar alocações frequentes
174
  with torch.cuda.device(self.device):
175
+ torch.cuda.empty_cache()
176
 
177
+ for i, frame in enumerate(frames):
178
  try:
179
+ # Preparar frame
180
+ frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
181
+ frame_pil = Image.fromarray(frame_rgb)
 
 
 
 
182
  frame_pil = self._preprocess_image(frame_pil)
183
 
184
  # Processar frame
 
201
  outputs=outputs,
202
  target_sizes=target_sizes,
203
  threshold=threshold
204
+ )[0]
205
 
206
  # Processar resultados
207
+ if len(results["scores"]) > 0:
208
+ scores = results["scores"]
209
+ boxes = results["boxes"]
210
+ labels = results["labels"]
211
 
212
  frame_detections = []
213
  for score, box, label in zip(scores, boxes, labels):
 
226
  if frame_detections:
227
  frame_detections = self._apply_nms(frame_detections)
228
  detections_by_frame.extend(frame_detections)
229
+
230
  except Exception as e:
231
  logger.error(f"Erro ao processar frame {i}: {str(e)}")
232
  continue
 
254
  logger.error(f"Erro ao processar vídeo: {str(e)}")
255
  return video_path, metrics
256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  def _preprocess_image(self, image: Image.Image) -> Image.Image:
258
  """Pré-processa a imagem para o formato esperado pelo modelo."""
259
  try: