martes, 16 de agosto de 2011

Imágenes panorámicas

La fotografía digital está presente en el quehacer de la gente desde hace ya buen tiempo. La cámara digital ha facilitado la generación de cantidades gigantescas de imágenes almacenadas en repositorios, redes sociales, etc. Tanto ha sido el impacto de estos dispositivos en la vida cotidiana, que ahora se ha empezado a introducir muchas herramientas al vuelo para procesamiento de fotografías digitales (detección de rostros, eliminación de ojos rojos, maquetación, eliminación del efecto de movimiento, etc). Recientemente, una aplicación interesante permite tomar fotografías panorámicas, algo que no estaba disponible hasta hace un par de años. En esta entrada les muestro una aplicación que desarrollé para un curso de Visión Computacional que permite reconstruir una fotografía panorámica partiendo de un conjunto de imágenes.

La idea es que uno tome varias fotografías y el programa reconstruya la vista que componen todas las imágenes. En este caso, el método que detallo más adelante, sirve para imágenes en escala de grises con la condición de que las imágenes deben contener cierto nivel de superposición de la vista original. La solución está basada en el uso de características locales extraídas desde las imágenes.

Para empezar, tenemos un conjunto de imágenes (para el ejemplo, el pan de azúcar, Rio de Janeiro - Brasil):

Para hacer el método lo más general posible, nosotros asumimos que las imágenes no están en orden. Por lo que el primer paso es determinar cómo las imágenes estarán dispuestas en la reconstrucción final. 

Nosotros calculamos los puntos de interés y los descriptores SIFT de cada imagen. Luego, para cada par de imágenes, hallamos el número de puntos de interés que se corresponden entre sí. Este paso se realiza en varios procesos:
  • Para cada punto de interés de la primera imagen, hallamos su vecino más cercano en la colección de puntos de interés de la segunda imagen. En realidad, se analiza la proporción entre la distancia al primer vecino y al segundo vecino más cercano. Si la proporción entre estas distancias es mayor a 0.8, no se considera dicha correspondencia.
  • Escogemos aleatoriamente un conjunto de correspondencias. Luego, empleando el método de mínimos cuadrados, calculamos la matriz de transformación homogénea que minimice el error de localización entre los puntos de las correspondencias. Esta transformación es validada empleando el conjunto entero de correspondencias. Se considera un "inlier", los puntos cuya versión transformada no difiere en 3 píxeles de sus correspondientes.  Este proceso de realiza muchas veces para garantizar una convergencia adecuada. Comúnmente se le conoce a esta método como RANSAC.
  • Finalmente, nos quedamos con el conjunto de inliers de mayor número.
Con la información sobre las correspondencias, es posible determinar cómo deberían ir las imágenes. Por ejemplo, la imagen de más a la izquierda, sólo tendrá correspondencias hacia la derecha. De la misma forma, para la imagen de más a la derecha. Además, la relación de correspondencia puede representarse como un grafo dirigido, sobre el que es posible encontrar una ordenación topológica a partir del nodo más a la izquierda. Esta ordenación define el orden  de las imágenes en la composición final. 


Para la composición final, empleamos el conjunto de correspondencias previamente calculado. Dadas dos imágenes, sus correspondencias, y la transformación entre puntos correspondientes, creamos una imagen que sea capaz de albergar todos los píxeles de ambas imágenes. A continuación, la primera imagen es copiada en alguna posición fija de la imagen destino y la segunda imagen es transformada de acuerdo a la transformación hallada. Para componer adecuadamente ambas imágenes y evitar la generación de artefactos, nosotros creamos dos máscaras rectangulares de pesos lineales (del mismo tamaño que las imágenes), de manera que al centro de la máscara haya un 1 y a los extremos de la máscara hayan 0's. De esta forma, la composición se realiza haciendo un promedio ponderado de los valores de los píxeles conforme sus pesos en las máscaras.

El resultado final fue: