Skip to content

Repository files navigation

NeuralBottlesCBN: Sistema de Inspección Visual Industrial

Descripción del Proyecto

NeuralBottlesCBN es un pipeline de visión artificial de alto rendimiento diseñado para el control de calidad en líneas de empaque de la Cervecería Boliviana Nacional (CBN). Su objetivo singular es la validación binaria ("pasa/no pasa") de casilleros de 12 botellas, determinando su completitud mediante arquitecturas de detección de objetos (YOLO).

Este repositorio está arquitectónicamente dividido para aislar el entorno de entrenamiento profundo (basado en Python/PyTorch) del motor de inferencia determinista (basado en C++/OpenVINO), garantizando una ejecución óptima y de baja latencia sobre hardware industrial heredado (Legacy Edge Computing).

Cambios recientes relevantes:

Restricciones de Hardware y Despliegue (Edge Node)

El nodo de inferencia final está sujeto a restricciones computacionales severas que dictan la arquitectura de este repositorio:

  • Procesador: Intel Celeron J1900 (Microarquitectura Silvermont, 4 núcleos @ 2.41 GHz).
  • Limitaciones Críticas: Ausencia total de instrucciones vectoriales AVX/AVX2/AVX-512. Soporte máximo para SSE4.2.

Topología del Monorepositorio

La arquitectura del repositorio segrega las responsabilidades lógicas y procedimentales:

NeuralBottlesCBN/
├── ws_py/               # Entorno de Entrenamiento y Cuantización (Python)
│   ├── train.py         # Script de entrenamiento de arquitectura YOLO
│   └── export_int8.py   # Congelación de grafo y conversión a OpenVINO IR (.xml / .bin)
├── ws_cpp/              # Entorno de Inferencia y Despliegue (C++)
│   ├── CMakeLists.txt   # Manifiesto de compilación (OpenCV, OpenVINO, ImGui, GLFW)
│   ├── config/          # Configuraciones YAML y layouts de ImGui (imgui.ini)
│   ├── src/             # Fuentes C++ (laboratorio_cbn.cpp, pipeline.cpp)
│   ├── include/         # Cabeceras C++ (pipeline.h)
│   ├── test/            # Scripts de validación de hardware
│   └── models/          # Directorio receptor para la Representación Intermedia INT8
├── docker-compose.yaml  # Orquestador local para compilación y desarrollo
└── Dockerfile           # Receta multi-etapa para compilación C++ y despliegue

Fase de Entrenamiento y MLOps (Python)

El flujo de Machine Learning se ejecuta estrictamente dentro del contenedor cbn_train, el cual empaqueta PyTorch, Ultralytics (YOLO) y las herramientas de OpenVINO en un entorno Debian aislado. ¡No instales dependencias localmente!

Selección de GPU (Build Time)

El contenedor soporta tres backends de aceleración. Selecciona el que corresponda a tu hardware editando GPU_BACKEND en docker-compose.yaml o pasándolo como build arg:

# AMD ROCm (RX 580, Vega, RDNA) — default en docker-compose.yaml
podman-compose build --build-arg GPU_BACKEND=rocm cbn_train

# NVIDIA CUDA (GTX/RTX)
podman-compose build --build-arg GPU_BACKEND=cuda cbn_train

# CPU solamente (sin GPU)
podman-compose build --build-arg GPU_BACKEND=cpu cbn_train

⚠️ Nota AMD RX 580: Esta GPU (gfx803) es hardware legacy para ROCm. Se usa HSA_OVERRIDE_GFX_VERSION=8.0.3 para forzar compatibilidad. Para GPUs Vega/RDNA más nuevas, esta variable no es necesaria.

⚠️ Nota NVIDIA: Requiere nvidia-container-toolkit instalado y CDI generado: sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml. Además, descomentar la sección NVIDIA en docker-compose.yaml.

Comandos del Pipeline:

  1. Construir el entorno de entrenamiento:

    podman-compose build cbn_train
  2. Verificar detección de GPU:

    podman-compose run --rm cbn_train python3 test/test_env.py
  3. Preparar y Aumentar el Dataset: Toma las imágenes de la cámara (crudos + txt), hace un split de entrenamiento/validación y genera el YAML. El flag --offline-aug aplica transformaciones extremas (blur, ruido, giros) simulando el entorno de la fábrica.

    podman-compose run --rm cbn_train python3 prepare_dataset.py --input-dir dataset/lote_1 --offline-aug
  4. Ejecutar el Entrenamiento: Inicia el ajuste fino de la arquitectura YOLO. La GPU se detecta automáticamente (--device auto es el default).

    podman-compose run --rm cbn_train python3 train.py --data dataset/lote_1_done/cbn_dataset.yaml --epochs 50 --batch 16
  5. Exportar y Cuantizar a Producción (OpenVINO INT8): Toma los mejores pesos del entrenamiento (best.pt), los cuantiza a enteros de 8-bits para máxima aceleración en el procesador Celeron J1900, y auto-copia el modelo resultante a la carpeta C++ (ws_cpp/models/).

    podman-compose run --rm cbn_train python3 export_int8.py --data dataset/lote_1_done/cbn_dataset.yaml

Ejecución del Laboratorio C++ (Desarrollo)

El entorno C++ local (cbn_test_cpp) integra una interfaz gráfica basada en Dear ImGui para configurar parámetros, inspeccionar visualmente los casilleros de botellas y operar las cámaras en tiempo real.

Debido a que el contenedor debe comunicarse con la pantalla principal, es obligatorio habilitar el acceso al servidor gráfico X11 antes de arrancarlo.

Pasos:

  1. Permitir la conexión de la interfaz gráfica local:

    xhost +local:
  2. Construir la imagen de contenedor C++:

    podman-compose build cbn_test_cpp
  3. Lanzar la interfaz visual (Laboratorio CBN):

    podman-compose run --rm cbn_test_cpp
  4. Probar el nodo de inferencia puro (solo modelo):

    podman-compose run --rm cbn_test_cpp /bin/bash -lc "cd build && cmake .. -G Ninja && ninja cbn_inference_node && cd .. && ./build/cbn_inference_node"
  5. Ejecutar la Inferencia Principal con la lógica de negocio (Botellas y Casilleros): Este comando compilará (vía Ninja por velocidad extrema) el binario final main y lo ejecutará, abriendo la cámara y aplicando la validación (PASA/RECHAZADO) si se detectan los 12 espacios:

    podman-compose run --rm cbn_test_cpp /bin/bash -lc "cd build && cmake .. -G Ninja && ninja main && ./main --show"

Nota: En caso de fallos de descarga al compilar (DNS en Podman), el contenedor usa por defecto network_mode: host para resolver conexiones.


Fase de Inferencia en Producción (Edge Deployment)

El entorno final se compila utilizando un método de cross-compiling optimizado para el procesador Celeron J1900. No se necesitan compiladores en la máquina destino.

1. Generar la imagen para producción (En la máquina de desarrollo)

Este comando compila el binario con soporte SSE4.2 y lo aísla en una micro-imagen limpia:

podman build --target edge_runtime -t localhost/neuralbottles_edge:latest .

Luego, empaqueta la imagen para transferirla a un USB/red:

podman save -o neuralbottles_edge.tar localhost/neuralbottles_edge:latest

2. Despliegue en la máquina industrial (Celeron J1900)

Transfiere el .tar, la carpeta ws_cpp/models y ws_cpp/config al equipo final, y carga la imagen:

podman load -i neuralbottles_edge.tar

Finalmente, levanta el contenedor mapeando la cámara industrial y los modelos. Podman debe correr como tu usuario normal, pero se elimina el cambio de usuario interno para no perder el mapeo de permisos de /dev/video0:

podman run -d \
  --name neuralbottles_inference \
  --device /dev/video0:/dev/video0 \
  --group-add video \
  -v ./ws_cpp/models:/app/models:ro \
  -v ./ws_cpp/config:/app/config:ro \
  --restart unless-stopped \
  localhost/neuralbottles_edge:latest

Para consultar detalles a fondo sobre resolución de problemas (Gaps resueltos) y decisiones arquitectónicas, revisa el archivo context.md.


Auditoría de Código (Resumen rápido - 2026-08-01)

Hallazgos principales:

  • Throttle único de captura: La única fuente de verdad para el control de tasa de captura es capture_interval_ms en ws_cpp/src/cbn_camera.cpp. El pipeline descarta buffers en cámara si el intervalo no ha transcurrido.
  • Redimensionado único: La tubería está diseñada para realizar un solo resize al tamaño de entrada del modelo. ws_cpp/src/pipeline.cpp efectúa el resize y ws_cpp/src/cbn_detector_inference.cpp evita re-redimensionar si la imagen ya tiene el tamaño del modelo.
  • Operaciones costosas detectadas (y su ubicación):
    • Compresión JPEG en vivo: ws_cpp/src/cbn_web_server.cpp usa cv::imencode() con un throttle a ~5 FPS (200 ms). Esto es intencional para ahorrar CPU en presencia de clientes web.
    • Non-Maximum Suppression (NMS): ws_cpp/src/cbn_detector_inference.cpp invoca cv::dnn::NMSBoxes() una vez por inferencia (sync y async paths). Es costosa pero necesaria para eliminar duplicados.
    • Escritura de imágenes (cv::imwrite) usada en modos laboratorio/depuración (ws_cpp/src/laboratorio_cbn.cpp, ws_cpp/src/pipeline.cpp) — no forma parte del flujo de producción.
  • Usos de sleep intencionales: Varias rutas de prueba y simulación usan std::this_thread::sleep_for() (tests, simuladores y el servidor web). En producción, solo cbn_camera.cpp aplica el throttling de captura; los sleeps en test/lab son esperados.

Recomendaciones inmediatas:

  • Re-exportar el IR a una resolución menor (ej. 384×384 o 320×320) y preferiblemente FP16 o INT8 calibrado para reducir la latencia de inferencia en el J1900.
  • Ejecutar benchmark_app de OpenVINO sobre ws_cpp/models/cbn_model.xml para validar latencias y probar -nstreams/-nireq.
  • Si la carga por compresión JPEG sigue siendo un problema, mover cv::imencode() a un hilo consumidor dedicado o reducir la calidad JPEG aún más.

Archivos clave revisados (puntos de interés):

  • ws_cpp/src/cbn_camera.cpp
  • ws_cpp/src/pipeline.cpp
  • ws_cpp/src/cbn_detector_inference.cpp
  • ws_cpp/src/cbn_web_server.cpp

Si quieres que ejecute la exportación del modelo a FP16/384 o prepare un benchmark_app con flags recomendados, indícame y lo preparo.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages