Files
ia-gondola-engine/CLAUDE.md
T
teste.inabaandClaude Sonnet 5 3efdb08c9b fix: reduzir sobreposição de boxes em /detectar
Caixa grande "engolindo" uma caixa menor do mesmo produto continuava
aparecendo mesmo com sobreposição óbvia — IoU sozinho não resolve isso
porque a união fica dominada pela caixa maior, então o IoU continua baixo
mesmo com contenção quase total (ex.: caixa 1/5 da área da outra, 100%
contida, IoU ≈ 0.2).

- iou=0.5 explícito no NMS do YOLO (antes usava o default 0.7, permissivo
  demais)
- novo pós-filtro _suprimir_boxes_contidas(): entre duas boxes da mesma
  classe onde a intersecção cobre ≥90% da área da MENOR das duas, mantém
  só a de maior confiança

Afeta tanto as boxes da revisão quanto as do TrainingTab, já que ambas vêm
do mesmo /detectar.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-04 14:07:40 -03:00

3.4 KiB

IA Gôndola Engine

Serviço isolado de detecção YOLO e treinamento. Consumido exclusivamente pela ia-gondola-api via IA_MOTOR_URL.

Arquitetura

ia-gondola-api  →  POST /detectar  →  YOLO  →  [{box, conf, class}]
                →  POST /treinar   →  triagem + treino → modelo atualizado no S3

Estrutura

main.py          — todo o código (sem sub-módulos)
Dockerfile
requirements.txt

Endpoints

POST /detectar

Form-data: ambiente (str), file (imagem). Confidence threshold: 0.25, NMS iou=0.5. ia-gondola-api também manda um campo conf no form (ver gondola_service.py), mas esse endpoint não declara/lê esse campo — é ignorado, o threshold usado é sempre o 0.25 hardcoded aqui.

Depois do NMS do próprio YOLO, passa por _suprimir_boxes_contidas(): remove boxes da mesma classe quase totalmente contidas em outra (caixa grande "engolindo" uma caixa menor do mesmo produto — comum em prateleira lotada). IoU sozinho não resolve isso: quando uma caixa é muito maior que a outra, a união fica dominada pela caixa grande e o IoU continua baixo mesmo com contenção quase total (ex.: caixa pequena 1/5 da área da grande, 100% contida → IoU ≈ 0.2, seguiria sobrevivendo mesmo com iou threshold bem mais agressivo que o do NMS padrão). A métrica usada aqui é intersecção / área da MENOR caixa do par, limiar 0.90 — entre duas boxes da mesma classe acima desse limiar, fica só a de maior confiança.

{ "status": "sucesso", "deteccoes": [{ "box": [x1,y1,x2,y2], "conf": 0.87, "class": 0 }] }

POST /treinar

Body JSON: { "ambiente": "gondola", "pular_triagem": false }

  1. Lista treinamento/{ambiente}/novos-treinamentos/ no S3
  2. Triagem (salvo pular_triagem: true): conf média ≥ 0.15 → base-oficial, < 0.15 → descartados
  3. Baixa base-oficial, redimensiona imagens > 4096px
  4. Treina: 20 épocas fine-tuning / 30 épocas do zero, imgsz=640, batch=8, device=cpu
  5. Salva best.pt em modelos/{ambiente}/atual/cerebro.pt + histórico versionado

Retorna { "status": "iniciado", "ambiente": "..." } imediatamente — treino roda em background thread. Quando não há modelo base, usa yolov8n.pt e pula triagem automaticamente.

GET /treinar/status

Retorna estado do treino em andamento + últimas 30 linhas de log.

{ "status": "running|concluido|erro|vazio|idle", "ambiente": "gondola", "versao": "20260627_1430", "detalhe": null, "logs": ["[1/20] box=0.432 ..."] }

logs inclui tanto as métricas por época (_on_fit_epoch_end callback do YOLO) quanto mensagens de progresso de triagem/download via log_print().

Organização S3

modelos/{ambiente}/atual/cerebro.pt
modelos/{ambiente}/versionamento/cerebro_YYYYMMDD_HHMM.pt
treinamento/{ambiente}/novos-treinamentos/
treinamento/{ambiente}/base-oficial/
treinamento/{ambiente}/descartados/

Convenções

  • MODELOS_CARREGADOS = dict em memória {ambiente: YOLO} — cache local em /tmp/cerebro_{ambiente}.pt
  • Se S3 tiver versão mais nova (LastModified), descarta cache e baixa novamente
  • Após treino, remove o ambiente de MODELOS_CARREGADOS para forçar reload
  • Todo o código em main.py — não criar sub-módulos
  • log_print(msg) escreve no stdout e em _training_logs (buffer circular 60 linhas) — não usar print() diretamente

Como rodar

pip install -r requirements.txt
uvicorn main:app --reload --port 8001