Introducción: por qué reconocer una lata de Coca-Cola es más difícil de lo que parece
Imagine: está programando un robot que debe clasificar basura automáticamente. O un sistema que cuenta la cantidad de productos en un estante. Una de las tareas más populares en entrevistas y proyectos educativos es el reconocimiento de una lata de Coca-Cola. Parece sencillo, ¿verdad? Un cilindro rojo brillante con una inscripción blanca. Pero en la práctica, todo resulta diferente.
En Stack Overflow, la pregunta "Image Processing: Algorithm Improvement for 'Coca-Cola Can' Recognition" ha acumulado miles de visitas y decenas de respuestas. Los programadores luchaban con el problema: ¿cómo distinguir de manera fiable la lata de otros objetos rojos (extintor, taza roja, trozo de plástico) en diferentes condiciones de iluminación?
En este artículo, no solo proporcionaremos código listo en C++ usando OpenCV. Analizaremos paso a paso los algoritmos de procesamiento de imágenes que transforman un flujo de video en bruto en un reconocimiento confiable. Aprenderá cómo mejorar la precisión de la detección, evitar falsos positivos y escribir código que funcione en tiempo real.
El problema: por qué los métodos simples no funcionan
El error típico de un principiante es intentar encontrar un objeto solo por el color. Por ejemplo, resaltar todos los píxeles rojos y encontrar el contorno más grande entre ellos. Pero:
- La iluminación cambia — el color rojo bajo una lámpara fluorescente y bajo el sol se ve diferente.
- Reflejos en el metal — la lata refleja la luz y su color puede parecer blanco o naranja.
- El fondo tiene ruido — camisetas rojas, sillas, vallas publicitarias confunden al detector.
- La forma se distorsiona — la lata puede estar girada, parcialmente oculta o deformada.
Por lo tanto, la mejora del algoritmo de reconocimiento no es solo ajustar umbrales, sino una combinación de métodos: filtrado de color, búsqueda de contornos, análisis de forma y texturas.
Arquitectura de la solución: de píxeles a decisión
Construiremos un pipeline de tres etapas:
- Preprocesamiento — desenfoque, conversión a HSV, morfología.
- Segmentación — extracción de candidatos por color y contornos.
- Verificación — filtrado por relación de aspecto, área, características de textura.
Este enfoque se utiliza en la visión por computadora en C++ para tareas industriales, desde clasificación de piezas hasta control de calidad.
Paso 1: Filtrado de color en HSV
El primer y más importante paso es convertir la imagen de RGB a HSV (Tono, Saturación, Valor). ¿Por qué? Porque HSV separa el color (tono) del brillo. Esto permite definir un rango para el color rojo que funcione bajo diferentes condiciones de iluminación.
#include <opencv2/opencv.hpp>using namespace cv;
Mat hsv, mask;cvtColor(src, hsv, COLOR_BGR2HSV);
// Rango para el color rojo (dos intervalos debido a la naturaleza cíclica de HSV)Scalar lower_red1 = Scalar(0, 70, 50);Scalar upper_red1 = Scalar(10, 255, 255);Scalar lower_red2 = Scalar(170, 70, 50);Scalar upper_red2 = Scalar(180, 255, 255);
Mat mask1, mask2;inRange(hsv, lower_red1, upper_red1, mask1);inRange(hsv, lower_red2, upper_red2, mask2);mask = mask1 | mask2;Tenga en cuenta: el color rojo se encuentra en el límite de HSV (0 y 180 grados), por lo que necesitamos dos rangos. Los parámetros de Saturación (70) y Valor (50) eliminan los píxeles demasiado pálidos o demasiado oscuros.
Paso 2: Morfología y búsqueda de contornos
Después de la máscara, obtenemos una imagen binaria, pero contiene ruido. Aplicamos un cierre morfológico (closing) para rellenar los agujeros dentro de la lata, y una apertura (opening) para eliminar puntos pequeños.
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));morphologyEx(mask, mask, MORPH_CLOSE, kernel);morphologyEx(mask, mask, MORPH_OPEN, kernel);