jueves, 3 de mayo de 2018

Práctica 2: 3D Reconstruction (Puntos homólogos y triangulación)

En la entrada anterior encontramos la recta epipolar, por lo que ya podemos buscar los puntos homólogos. Para ello emplearemos la correlación para ver cuales son los puntos más parecidos entre ellos.
En primer lugar se probó a realizar la búsqueda del punto más parecido recorriendo la epipolar y en un margen respecto a ella, ya que puede haber errores de calibración. Esta búsqueda se hacia mediante parches y comprobando la correlación que había entre ellos. Cuanto mayor correlación mayor parecido existe. Es decir, se realizaba SAD (Sum of Absolute Differences), pero se ha comprobado que se introduce bastante ruido en la reconstrucción. 
Por este motivo, se ha decidido emplear SAD, pero empleando puntuación. Es decir, se hace la diferencia absoluta y si supera un umbral se da un voto. Una vez tengamos la suma de los votos de cada parche nos quedaremos con el que mayor puntuación tenga. Hay que mencionar que la correlación se hace en el espacio de color HSV y el tamaño de parches que se ha empleado es de 23x23.
En la siguiente imagen podemos observar la epipolar en color rojo, y los márgenes hasta los cuales se busca el punto homólogo en azul.
En la siguiente imagen se puede ver un punto de interés marcado con un círculo azul y tras esta una imagen del punto homólogo de dicho punto pintado en rojo.




Una vez hemos encontrado los homólogos y tenemos emparejados los puntos, ya podemos realizar la reconstrucción 3D. La reconstrucción consistirá en calcular los rayos de retroproyección de cada punto emparejado y con ellos el punto donde intersectan. Debido a que puede haber errores en la calibración de las cámaras puede que los rayos no intersecten por lo que se busca el punto de mínima distancia.

Los rayos de retroproyección se obtienen de la siguiente forma:

1. Retroproyectamos los puntos al espacio 3D. Para ello convertimos los puntos al sistema de la cámara mediante:
 
pointInOpt = self.camRightP.graficToOptical(pointIn)

Se obtiene el punto 3D correspondiente al 2D:

p3d = self.camRightP.backproject(pointInOpt)
 
 
2. Una vez que tenemos los puntos en el espacio 3D y la posición de las cámaras, ya podemos calcular los rayos de retroproyección. El rayo de retroproyección será la recta que pase por el punto y la posición de la cámara.
Una vez tenemos los rayos de retroproyección, el punto 3D debería situarse donde intersectan ambos rayos de retroproyección. Esto como hemos comentado anteriormente, solamente ocurrirá en una situación ideal en la que la calibración de las cámaras sea perfecta, pero en la realidad no es así. Por lo que se busca el punto que minimiza la distancia entre ambas rectas. Para realizar esta búsqueda me he basado en la solución que se plantea en la siguiente página: http://www.homer.com.au/webdoc/geometry/lineline3d.htm
En la siguiente imagen se puede ver un esquema de la situación que tendríamos entre nuestros dos rayos de retroproyección.

Donde P1 es la posición de la cámara izquierda, P3 es la posición de la cámara derecha, P2 es la posición del punto 3d detectado de la cámara izquierda, y P4 es el punto 3d correspondiente al homólogo.
Tras obtener los puntos pa y pb, que se mencionan en el enlace anterior, se puede calcular nuestro punto tridimensional, ya que se encontrará entre ambos puntos. Además, cuando buscamos la intersección de los rayos para calcular el punto 3d, se ha introducido una restricción para tratar de eliminar errores. La restricción es la siguiente: si la distancia entre pa y pb  es superior a un umbral, el punto será descartado. 
El siguiente punto que se ha llevado a cabo es el pintado de los puntos. Si se pinta cada punto cada vez que vamos realizando el proceso anterior, el tiempo de cómputo es bastante elevado. Por lo que se ha decidido guardar todos los puntos en un array y pintar dichos puntos al final. Esto agiliza bastante el cómputo.
En la siguiente imagen se puede ver la reconstrucción que se ha obtenido como resultado final: 


En la reconstrucción se puede ver que existe un poco de ruido, pero es bastante complicado realizar una reconstrucción sin ruido. Además, se puede ver que los puntos tienen diferentes profundidades, esto se debe a que en la escena 3D del mundo unos puntos están más alejados que otros de la cámara.

Además, se ha probado a fijar la posición de la profundidad de los puntos para ver cómo sería el resultado, ya que en la anterior imagen algunos puntos tienen diferente profundidad y es más complicado apreciar la reconstrucción. Esto lo podemos ver a continuación.


En la reconstrucción que se ve en las imágenes anteriores se hace una normalización del color entre 0 y 1. Pero está normalización se ha realizado dividiendo por el máximo valor del color del punto en la imagen para realzar ciertos tonos. Este color no es realista, por lo que se ha realizado una normalización por 255, que se puede ver en la siguiente imagen.

 

No hay comentarios:

Publicar un comentario