>>> Descarga el código de este post aquí <<<
Anteriormente hablamos del detector Harris, el cual se fundamenta en conceptos propios del álgebra lineal, como el cálculo del determinante y la traza de una matriz, con el objeto de medir la “esquinosidad” de una región.
En particular, la ecuación usada para calcular este atributo, conocido como R, es la siguiente:
R = determinante(M) – k * (traza(M) ^ 2)
Una forma alternativa de expresarla, basada en los autovalores (también conocidos como valores propios o Eigen) de la matriz M, es esta:
R = A1 * A2 – k * ((A1 + A2) ^ 2)
No obstante, según Shi y Tomasi, autores del detector GFTT (cuyas iniciales significan, en inglés, Good Features to Track o Buenas Características a Trazar) llegaron a la realización de que hay una mejor forma de cuantificar la “esquinosidad”:
R = min(A1, A2)
Dada esta versión simplificada de la ecuación, para determinar si una región es una esquina, basta con que se cumpla que R sea mayor o igual a un determinado umbral (T). Puesto de otra forma, R>= T.
¡Suficiente teoría! Pongámonos manos a la obra.
Código
>>> Descarga el código de este post aquí <<<
Empecemos como siempre: creando el entorno virtual, e instalando las librerías necesarias.
1 2 3 |
virtualenv -p python3 venv source venv/bin/activate pip install -r requirements.txt |
Las dependencias de este proyecto son:
1 2 |
numpy==1.18.2 opencv-contrib-python-headless==4.2.0.34 |
El programa de abajo hace uso de la implementación del detector GFTT incorporado en OpenCV para encontrar las esquinas en la foto de ejemplo. Mi recomendación es que leas con detenimiento los comentarios que acompañan a la implementación antes de ejecutar el script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
# Importamos las librerías necesarias import cv2 import numpy as np def gftt(gray, max_corners=0, quality_level=0.01, min_distance=1, mask=None, block_size=3, use_harris_detector=False, k=0.04): # Usa la implementación de GFTT para computar los puntos clave con los parámetros proporcionados. keypoints = cv2.goodFeaturesToTrack(gray, max_corners, quality_level, min_distance, mask=mask, blockSize=block_size, useHarrisDetector=use_harris_detector, k=k) # Tenemos que crear objetos de tipo KeyPoint, los cuales en OpenCV son tridimensionales return [cv2.KeyPoint(point[0][0], point[0][1], 3) for point in keypoints] image = cv2.imread('./photos.jpg') # Cargamos la imagen de entrada. original = image.copy() # Hacemos una copia de la imagen, puesto que haremos cambios en la original gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Convertimos la imagen a escala de grises. # Aplicamos el detector GFTT keypoints = gftt(gray) print(f'Número de puntos clave: {len(keypoints):,}') # Dibujaremos todos los puntos clave detectados en la foto. for keypoint in keypoints: radius = int(0.5 * keypoint.size) x, y = np.int64(keypoint.pt) cv2.circle(image, (x, y), radius, (0, 255, 255), 2) # Mostramos la imagen original junto con la copia con los puntos clave dibujados en ella. cv2.imshow('Imágenes', np.hstack([original, image])) cv2.waitKey(0) |
Con el siguiente comando podemos correr el programa:
1 |
PYTHONPATH=. python datasmarts/gftt.py |
El resultado será el siguiente (la imagen de la derecha contiene 2351 puntos clave, aunque es probable que muchos de ellos se solapen entre sí).
El día de hoy estudiamos una pequeña mejora al ya competente detector de Harris. Aunque el método propuesto por Shin y Tomasi es más compacto y sencillo de entender, en la práctica no hay un claro ganador entre Harris y GFTT. Si bien es cierto que GFTT tiende a ser más estable, un aspecto a recalcar es que, sin importar qué tan bueno sea un detector en la teoría, siempre debemos probarlos todos para poder tomar una decisión respaldada por datos, por experimentos, no por corazonadas.
>>> Descarga el código de este post aquí <<<
Descarga el proyecto de ejemplo, altéralo a tu gusto y comparte tus descubrimientos en los comentarios.
¡Nos vemos!