julio 28, 2021 10:00 am

Jesús

Dependiendo del tipo de problema que se nos presente en computer vision, tendremos que optar por métricas específicas que nos digan qué tan buena es una solución con base en las características propias del dominio de dicho problema.

Así, por ejemplo, si estamos entrenando un clasificador, el accuracy es, con frecuencia, la medida de calidad del nuestro algoritmo.

Si, por otro lado, nuestro problema es de regresión, el accuracy no tiene sentido, ya que una coincidencia exacta entre dos cantidades continuas es prácticamente imposible. En este caso, métricas como MSE, MAE o R^2 son más apropiadas.

Cuando hablamos de detectores de objetos, ¿qué métrica usamos? 

Si pensaste en accuracy, piénsalo de nuevo.

No, usamos una métrica conocida como Intersection Over Union (IoU), o Intersección sobre Unión, en español, y en este artículo aprenderemos todo lo necesario al respecto.

Al final de este post sabrás:

  • Qué es el Intersection Over Union (IoU).
  • Cómo calcular el Intersection Over Union (IoU).
  • Cómo implementar un programa en Python para calcular el Intersection Over Union (IoU).

¡Empecemos!

¿Qué es el Intersection Over Union (IoU)?

IoU no es más que una métrica de evaluación que usamos para medir la efectividad de un detector de objetos, independientemente de la naturaleza del mismo. 

En otras palabras, aunque nuestro detector esté basado en YOLO, RetinaNet, HOG + LinearSVM o cualquier otro algoritmo, IoU nos servirá para determinar qué tan preciso es dicho detector.

La definición formal de IoU es la siguiente:

Dados dos rectángulos A y B, correspondientes a detecciones de objetos, IoU será el cociente entre el área de la intersección de A y B, y el área de la unión de A con B.

Gráficamente, esta sería la ecuación:

¿Por Qué Usamos IoU en la Detección de Objetos?

Ahora bien, la pregunta lógica es: ¿por qué usar IoU en la detección de objetos?

En tareas más comunes de machine learning, como en la clasificación, típicamente lo que buscamos es predecir un único valor, correspondiente a una clase de entre muchas. Por ejemplo, gato, perro, caballo, etcétera.

En ese caso, es fácil saber si el clasificador está haciendo bien su trabajo: ¿la clase predicha es igual a la clase real? 

Sin embargo, en la detección de objetos las cosas no son tan sencillas, ya que en vez de predecir un valor, queremos generar una serie de coordenadas para ubicar un objeto en una imagen.

Cabe mencionar que es extremadamente improbable que las coordenadas producidas por el modelo sean exactamente iguales a las coordenadas reales, escogidas a mano por alguien.

Entonces, si la exactitud no es una opción, la mejor alternativa es una métrica que premie al modelo por producir coordenadas de rectángulos que se solapen lo más posible con su contraparte real, y es por eso que usamos IoU.

Otra pregunta que vale la pena hacerse llegados a este punto es, ¿qué valor de IoU se considera bueno?

Como siempre, la escogencia de un valor como tal depende mucho del problema a resolver, pero un buen punto de partida es 0.5. Una posible escala de evaluación se vería así:

  • IoU < 0.5: Malo.
  • 0.5 <= IoU < 0.85: Bueno.
  • IoU >= 0.85: Excelente.

Con la teoría cubierta, pasemos a la práctica.

Creación del Entorno de Desarrollo con Anaconda

Primero, veamos la estructura del proyecto:

Estructura del proyecto

Estructura del proyecto

En la carpeta resources tenemos las imágenes de ejemplo que usaremos para demostrar el funcionamiento de nuestra función de cálculo de IoU, que se encuentra implementada en el archivo datasmarts/iou.py.

Para crear el ambiente de Anaconda, ejecuta el siguiente comando:

conda env create -f env.yml

Dicha instrucción habrá creado un ambiente llamado opencv-iou, correspondiente a este archivo de configuración:

Activa el ambiente así:

conda activate opencv-iou

¡Sigamos!

Implementando IoU en Python

Puesto que nuestro objetivo es implementar y entender la métrica IoU, usaremos una serie de imágenes de ejemplo que tienen coordenadas asociadas tanto para la ubicación real del objeto, como para la arrojada por un hipotético algoritmo. Puedes ver la estructura del archivo resources/detections.json a continuación:

En cada objeto tenemos las siguientes claves:

  • path: Ruta a la imagen de ejemplo.
  • ground_truth: Coordenadas reales del objeto.
  • predicted: Coordenadas predichas del objeto.

Abre el archivo datasmarts/iou.py e inserta estas líneas para importar las dependencias:

Para facilitarnos la vida, implementamos la clase Detection, la cual agrupa una imagen con las coordenadas reales y predichas:

Como podemos ver, en el constructor almacenamos todos los elementos presentes en los objetos en el archivo resources/detections.json, y también leemos la imagen asociada al path. 

El siguiente bloque es la estrella del show, puesto que en él definimos la función intersection_over_union(), que como su nombre indica, calcula el IoU entre dos series de coordenadas:

De la línea 8 a la 12 extraemos las coordenadas del rectángulo correspondiente a la intersección entre gt y pred.

Después, calculamos el área de la intersección (líneas 15-16).

El siguiente paso es calcular las coordenadas de los rectángulos gt y pred por separado (líneas 19-23).

Por último dividimos el área de la intersección entre el área de la unión (a la cual tenemos que restarle el área de la intersección para no considerarla dos veces), justo como dice la ecuación que estudiamos en las secciones previas.

Definimos el menú del programa, compuesto por sólo un parámetro, -e/--examples, la ruta al JSON con las detecciones de ejemplo. Por supuesto, el valor por defecto nos dirige a resources/detections.json:

Leemos la data en detections.json, y las usamos para instanciar objetos de tipo Detection:

Finalmente, iteramos sobre cada ejemplo, siguiendo este proceso:

  1. 1
    Dibujamos las coordenadas de la ubicación real del objeto (en color verde).
  2. 2
    Dibujamos las coordenadas de la ubicación predicha del objeto (en color rojo).
  3. 3
    Calculamos el IoU entre el par de coordenadas.
  4. 4
    Mostramos el IoU tanto en la foto como en la consola.
  5. 5
    Mostramos la imagen.

¡Eso es todo!

Para ejecutar el programa, corre este comando:

python datasmarts/iou.py

En la pantalla verás las siguientes imágenes, donde vemos en color verde la ubicación etiquetada del objeto, y en rojo la detectada. También notamos el coeficiente de IoU asociado a cada detección:

Si nos fijamos en la terminal, tendremos el IoU asociado a cada imagen

./resources/image_0002.jpg: 0.6629
./resources/image_0016.jpg: 0.7899
./resources/image_0075.jpg: 0.6125
./resources/image_0090.jpg: 0.9472
./resources/image_0120.jpg: 0.7310

En todos los casos el valor del IoU está por encima de 0.5, lo que se traduce en detecciones aceptables.

En particular, el IoU de la imagen resources/image_0090.jpg es excelente, ya que se acerca considerablemente a 1 (lo cual sería una coincidencia exacta entre las coordenadas reales y las predichas):

Resumen

El día de hoy aprendimos que IoU es una métrica especializada en la evaluación de detectores de objetos, puesto que en vez de considerar coincidencias exactas entre las coordenadas reales y predichas (lo cual es una situación que se da en muy raras ocasiones), premia aquellos detectores que producen detecciones que se solapen lo suficiente con las reales como para considerar que pertenecen al mismo objeto.

Posteriormente, implementamos una función en Python para, dadas las coordenadas de dos rectángulos, conocer su coeficiente de IoU y, en consecuencia, determinar qué tan buenas son las predicciones de un detector de objeto.

¿Qué te pareció el artículo de hoy? ¿Por qué no te descargas el código y lo usas para evaluar alguno de los muchos detectores de objetos que hemos estudiado hasta la fecha?

¡Hasta pronto!

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.

Paso 2/2: Celebra tu NUEVO EMPLEO en Machine Learning ?

A %d blogueros les gusta esto: