febrero 13, 2020 10:00 am

Jesús

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:

  • Cómo funciona template matching de manera intuitiva.
  • Cómo funciona template matching de forma más técnica.
  • Cómo implementar y aplicar template matching en OpenCV.
  • Por qué template matching es bueno.
  • Por qué template matching es malo.

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:

wally-chile

Detectar objetos con plantillas es como jugar "¿Dónde está Wally?"

Template matching es, básicamente, un juego de “¿Dónde está Wally?” donde:

  • Wally → La plantilla, es decir, el objeto que queremos encontrar.
  • Escenario → La foto.

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

1

Deslizaremos de izquierda a derecha y de arriba a abajo la plantilla sobre la fuente

2

En cada ubicación (x, y), calcularemos la métrica de similitud mencionada anteriormente.

3

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:

  • -s/--source: Es la ruta a la imagen fuente, es decir, en la que queremos detectar el objeto.
  • -t/--template: Ruta a la  plantilla.

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:

  • La imagen fuente (source).
  • La plantilla (template).
  • El tipo de algoritmo usado para cuantificar qué tan bueno es un match (cv2.TM_CCOEFF).

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:

  • El mínimo en la matriz.
  • El máximo en la matriz.
  • La posición (x, y) del mínimo.
  • La posición (x, y) del máximo.

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:

template-matching-exitoso

Ubicamos correctamente la botella (izquierda) en la imagen objetivo (derecha)

¡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:

template-matching-falla-en-una-botella-diferente

Template matching falló porque la imagen objetivo es ligeramente diferente. Sólo hizo match parcial con la etiqueta

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:

template-falla-por-cambio-de-perspectiva

Template matching otra vez, aunque se trata de la misma botella, pero con una perspectiva diferente

¡¿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

  • Es muy fácil de implementar.
  • Es extremadamente intuitivo y sencillo de entender.
  • No requiere machine learning ni algoritmos complicados.
  • No hace falta un conjunto de datos.

Cons

  • Es muy simplista para ser usado en la vida real.
  • Es extremadamente sensible a variaciones en el color.
  • Es extremadamente sensible a variaciones en la perspectiva.
  • Es extremadamente sensible a variaciones en la rotación.
  • Es extremadamente sensible a variaciones en general.

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!

Sobre el Autor

Jesús Martínez es el creador de DataSmarts, un lugar para los apasionados por computer vision y machine learning. Cuando no se encuentra bloggeando, jugando con algún algoritmo o trabajando en un proyecto (muy) cool, disfruta escuchar a The Beatles, leer o viajar por carretera.