En el artículo anterior aprendimos que uno de los problemas más importantes que computer vision busca resolver es la detección de objetos.
¡Ojo! Detectar objetos en una imagen digital es sustancialmente más difícil que clasificarlos. Y es que no son lo mismo, ya que clasificar responde a la pregunta “¿qué hay?”, mientras que detectar se enfoca en decir “¿dónde está?”
Clasificar objetos responde "¿Qué hay en la imagen?", mientras que detectar objetos se refiere a "¿En qué parte de la imagen se encuentra?"
Ahora bien, algo que no hicimos fue estudiar algoritmo alguno de detección de objetos.
En consecuencia, en este artículo nos centraremos en el análisis de nuestra primera herramienta para hallar objetos en fotos: coincidencia de plantilla o, en inglés, template matching.
Al final de este artículo aprenderás:
SPOILER ALERT:
Buena noticia: Es increíblemente intuitivo y sencillo de implementar.
Mala noticia: Funciona únicamente bajo condiciones muy estrictas y específicas.
¡Empecemos!
Template Matching para Dummies
No sé tú, pero para que un concepto entre en mi cabeza, tienen que explicármelo con peras y manzanas. Si alguien intenta irse directamente a las fórmulas y al código, me desmayo.
La mejor manera que he encontrado, hasta los momentos, de entender template matching es con “¿Dónde está Wally?”.
¿Conoces ese juego? Si no, pues, te lo explico: Consiste en buscar a Wally (Waldo en EE.UU. y Canadá), un personaje que siempre lleva la misma ropa, en un escenario sobrecargado de otros elementos. A continuación puedes ver un ejemplo:
Template matching es, básicamente, un juego de “¿Dónde está Wally?” donde:
Al final, se trata de ir escaneando la foto, comparando cada objeto o sección de la misma con nuestro “Wally” de interés. Fácil, ¿no?
Template Matching para los No tan Dummies
Si tu apellido es Musk o Hawkins, o no te gusta “¿Dónde está Wally?”, no temáis, te tengo la explicación técnica.
El algoritmo es muy sencillo. Como su nombre sugiere, consiste en tomar una fotografía de referencia, la cual denominamos plantilla, con el fin de buscar la región más similar a dicha plantilla en una imagen objetivo, a la que conocemos como fuente.
¿Cómo evaluamos la similitud de dos regiones? Usualmente mediante una función matemática que produce un valor real que representa qué tan buena o mala es la coincidencia entre un parche de la fuente con respecto a la plantilla.
Esta comparación se hace únicamente con base al valor de los píxeles.
En definitiva, el proceso se resume así:
Template matching
Deslizaremos de izquierda a derecha y de arriba a abajo la plantilla sobre la fuente
En cada ubicación (x, y), calcularemos la métrica de similitud mencionada anteriormente.
El resultado será una matriz con tantas filas y columnas como parches quepan en la imagen fuente. Por consiguiente, tendrá dimensiones más pequeñas que la imagen original. Cada elemento (x, y) en esta matriz corresponde a la similitud de dicho parche con la plantilla.
Configuración del Entorno de Programación para Template Matching
La mejor manera de entender el template matching es viéndolo en acción. Para ello, nos apoyaremos en OpenCV. No obstante, debemos configurar nuestro ambiente antes que nada:
La lista de paquetes que vamos a instalar es bastante ligera (sólo NumPy y OpenCV):
Con el siguiente comando podemos instalar las librerías:
pip install -r requirements.txt
Para finalizar, crea la siguiente estructura para el proyecto:
datasmarts
├── __init__.py
└── template_matching.py
Si realmente quieres ahorrar tiempo, te puedes descargar el código completo y las imágenes de prueba abajo.
Implementación de Template Matching en OpenCV
Abre el archivo datasmarts/template_matching.py e importa las librerías pertinentes:
Ahora, definamos los parámetros de entrada del programa:
El menú de nuestro script es muy sencillo:
Luego, cargamos en memoria ambas imágenes:
Necesitamos extraer las dimensiones de la plantilla, para luego dibujar un rectángulo alrededor del “match” o coincidencia:
En el bloque anterior buscamos las coincidencias en la imagen fuente, apoyándonos en cv2.matchTemplate(). Los parámetros que recibe esta función son:
El resultado de cv2.matchTemplate() es una matriz, donde cada posición (x, y) contiene un número que indica qué tan bueno o malo es el match allí.
Sin embargo, sólo nos interesan los siguientes valores:
Afortunadamente, en el siguiente bloque de código estamos extrayendo estas cantidades:
¡Ya pasó lo más difícil! Lo que nos queda es pintar un rectángulo alrededor del mejor match y mostrar el resultado en pantalla:
Fíjate que en el código de arriba usamos la ubicación del valor más grande en la matriz. ¡Esto es importante!
Ejecución del Script: Camino Feliz
¿Listo? Bien. Ahora pongamos a trabajar a este bebé. Con el siguiente comando bastará:
PYTHONPATH=. python datasmarts/template_matching.py -s coke.jpg -t coke_template.jpg
Al cabo de unos segundos, veremos lo siguiente:
¡Una coincidencia perfecta! ¿Acaso no es poderosa nuestra solución? A la primera pudimos localizar sin error alguna la botella de Coca-Cola, valiéndonos únicamente de una imagen de referencia.
Pues… Más allá de la incontestable eficacia de template matching en este escenario, sus limitaciones son más que evidentes. Saltemos a la siguiente sección, ¿sí?
Template Matching es MUY Sensible a los Cambios
Intentemos con otra imagen:
PYTHONPATH=. python datasmarts/template_matching.py -s coke2.jpg -t coke_template.jpg
Nuestra plantilla es la misma, pero la fuente cambia. Tristemente, el resultado en esta ocasión no es nada alentador:
Esta vez sólo hicimos un match parcial con una porción de la botella. La principal causa es que las dimensiones del objeto en esta imagen son más grandes que en el ejemplo anterior y, por tanto, la plantilla es incapaz de abarcarlo completamente.
El diseño y orientación de esta botella, así como el fondo de la imagen son ligeramente diferentes, reduciendo así la utilidad de nuestra plantilla.
Template Matching es MUY Sensible a la Escala
Intentemos una última vez con otra fotografía:
PYTHONPATH=. python datasmarts/template_matching.py -s coke3.jpg -t coke_template.jpg
Una vez más, la plantilla es la misma, pero no la fuente, aunque se trata de la misma botella de la primera imagen. Quizás tengamos mejor suerte en esta oportunidad. Veamos:
¡¿Qué?! ¿Ni siquiera pudimos localizar la botella? ¿Por qué?
El cambio de perspectiva, orientación, ubicación y profundidad afectaron fuertemente el desempeño de nuestro detector.
El principal problema de template matching es que el método no es lo suficientemente robusto para detectar objetos que se desvíen visualmente de la plantilla, puesto que trabaja con los valores de los píxeles, en vez de usar una representación abstracta, como los vectores de features.
Resumen
Hoy aprendimos a implementar el detector de objetos más básico e ingenuo posible.
A pesar de sus notables falencias, su utilidad bajo condiciones controladas ha quedado patente. Más aún, sirve como una gentil introducción a la familia de algoritmos de detección de objetos, una cualidad definitivamente valiosa.
Pros y contras de template matching
Pros
Cons
Conclusión:
Template matching es genial para dar tus primeros pasos en la detección de objetos, pero en el 99% de los casos, no te dará la mejor solución posible.
¿Te resultó útil el artículo de hoy? Si es así, por favor compártelo con alguien que se pueda beneficiar de él… O a quien le guste “¿Dónde está Wally?” 😉
Cuídate. ¡Un abrazo!