Uno de los proyectos más interesantes en los que he trabajado en los últimos años fue un proyecto sobre procesamiento de imágenes . El objetivo era desarrollar un sistema para poder reconocer las 'latas' de Coca-Cola (tenga en cuenta que estoy haciendo hincapié en la palabra 'latas', verá por qué en un minuto). Puede ver una muestra a continuación, con la lata reconocida en el rectángulo verde con escala y rotación.
Algunas limitaciones en el proyecto:
- El fondo puede ser muy ruidoso.
- La lata podría tener cualquier escala o rotación o incluso orientación (dentro de límites razonables).
- La imagen podría tener cierto grado de borrosidad (los contornos podrían no ser completamente rectos).
- ¡Podría haber botellas de Coca-Cola en la imagen, y el algoritmo solo debería detectar la lata !
- El brillo de la imagen puede variar mucho (por lo que no puede confiar "demasiado" en la detección de color).
- La lata podría estar parcialmente oculta en los lados o en el medio y posiblemente parcialmente oculta detrás de una botella.
- No podría haber ninguna lata en la imagen, en cuyo caso no tenía que encontrar nada y escribir un mensaje que lo dijera.
Así que podrías terminar con cosas difíciles como esta (que en este caso mi algoritmo falló por completo):
Hice este proyecto hace un tiempo, y me divertí mucho haciéndolo, y tuve una implementación decente. Aquí hay algunos detalles sobre mi implementación:
Lenguaje : Hecho en C ++ usando la biblioteca OpenCV .
Preprocesamiento : para el preprocesamiento de la imagen, es decir, transformar la imagen en una forma más cruda para darle al algoritmo, utilicé 2 métodos:
- Cambiar el dominio de color de RGB a HSV y el filtrado basado en el tono "rojo", la saturación por encima de cierto umbral para evitar colores naranjas y el filtrado de bajo valor para evitar tonos oscuros. El resultado final fue una imagen binaria en blanco y negro, donde todos los píxeles blancos representarían los píxeles que coinciden con este umbral. Obviamente, todavía hay mucha basura en la imagen, pero esto reduce la cantidad de dimensiones con las que tiene que trabajar.
- Filtrado de ruido utilizando el filtrado medio (tomando el valor de píxel medio de todos los vecinos y reemplazando el píxel por este valor) para reducir el ruido.
- Uso del filtro de detección de bordes Canny para obtener los contornos de todos los elementos después de 2 pasos precedentes.
Algoritmo : el algoritmo en sí que elegí para esta tarea fue tomado de este impresionante libro sobre extracción de características y se llamó Transformación Hough Generalizada (bastante diferente de la Transformación Hough regular). Básicamente dice algunas cosas:
- Puede describir un objeto en el espacio sin conocer su ecuación analítica (que es el caso aquí).
- Es resistente a las deformaciones de la imagen, como la escala y la rotación, ya que básicamente probará su imagen para cada combinación de factor de escala y factor de rotación.
- Utiliza un modelo base (una plantilla) que el algoritmo "aprenderá".
- Cada píxel restante en la imagen de contorno votará por otro píxel que supuestamente será el centro (en términos de gravedad) de su objeto, en función de lo que aprendió del modelo.
Al final, terminas con un mapa de calor de los votos, por ejemplo, aquí todos los píxeles del contorno de la lata votarán por su centro gravitacional, por lo que tendrás muchos votos en el mismo píxel correspondiente al centro, y verá un pico en el mapa de calor de la siguiente manera:
Una vez que tenga eso, una simple heurística basada en el umbral puede darle la ubicación del píxel central, desde el cual puede derivar la escala y la rotación y luego trazar su pequeño rectángulo a su alrededor (la escala final y el factor de rotación obviamente serán relativos a su plantilla original). En teoría al menos ...
Resultados : ahora, aunque este enfoque funcionó en los casos básicos, carecía severamente en algunas áreas:
- ¡Es extremadamente lento ! No estoy haciendo suficiente hincapié en esto. Se necesitó casi un día completo para procesar las 30 imágenes de prueba, obviamente porque tenía un factor de escala muy alto para la rotación y la traducción, ya que algunas de las latas eran muy pequeñas.
- Se perdió por completo cuando las botellas estaban en la imagen, y por alguna razón casi siempre encontró la botella en lugar de la lata (tal vez porque las botellas eran más grandes, por lo tanto, tenían más píxeles, por lo tanto, más votos)
- Las imágenes borrosas tampoco fueron buenas, ya que los votos terminaron en píxeles en ubicaciones aleatorias alrededor del centro, lo que terminó con un mapa de calor muy ruidoso.
- Se logró una variación en la traslación y la rotación, pero no en la orientación, lo que significa que no se reconoció una lata que no estaba directamente orientada al objetivo de la cámara.
¿Pueden ayudarme a mejorar mi algoritmo específico , utilizando exclusivamente las funciones de OpenCV , para resolver los cuatro problemas específicos mencionados?
Espero que algunas personas también aprendan algo de eso, después de todo, creo que no solo las personas que hacen preguntas deberían aprender. :)