Práctica 2. Reconstrucción 3D: Obtención del Punto 3D

Teniendo ya ubicado cada punto de interés en ambas imágenes, podemos ya calcular las rectas de retroproyección de los dos puntos y obtener la posición 3D del punto, que será aquella donde ambas rectas se corten. No obstante, como suelen existir errores de calibración, no siempre se cruzarán las dos rectas, por se debe obtener el punto más cercano a ambas rectas y no la interseción como tal.

Para este cálculo se ha utilizado el algoritmo que referencia la compañera Jessica Fernández en su blog de la asignatura.

También se ha añadido la claúsula señalada por Julián Lamoso de no devolver aquellas distancias mayores de 1, consiguiendo con ello descartar puntos con correspondencias erróneas.

El resultado es bastante robusto (aunque como se puede ver hay algún error en alguno de los cálculos), pero existe un problema ìmportante de tiempos de ejecución del algoritmo. El cálculo de correspondencias de cada punto tarda en torno a un segundo de media, y para la ejecución del algoritmo con todos los puntos de interés obtenidos con Canny, la ejecución supera ampliamente la hora.

Todos los puntos

Para intentar bajar estos tiempos se ha añadido una condición para que sólo se traten la mitad de puntos de interés. El resultado es menos denso y detallado que tratando todos los puntos, pero se reducen de forma sensible los tiempos de ejecución totales de la reconstrucción 3D, aunque siguen siendo muy extensos: en torno a los 45 minutos.

Reconstrucción con la mitad de puntos

Como mejora se decide calcular primero los puntos, almacenarnos en una lista, y dibujarlos posteriormente todos de golpe en el 3DViewer. Según se aprecia, pasamos de tiempos de 45 minutos a en 15, por lo que se mejora altamente el algoritmo con este cambio.

No obstante, los tiempos siguen siendo muy altos, por lo que se deberían considerar otras mejoras como:

  • Hacer menos denso el resultado del cálculo de puntos de interes con Canny, perdiendo no obstante detalle en la reconstrucción.
  • Quitar iluminación, dejando una imagen a contraluz con la que sólo obtendríamos un contorno<(li>
  • Mejorar la búsqueda de parches actual. Aunque a la hora de recorrer la imagen derecha se tiene en cuenta la franja epipolar para optimizar la zona del cálculo de parches, el bucle en busca de esa franca recorre toda la imagen, una operación computacionalmente muy cara. Una mejora a tener en cuenta sería mejorar este recorrido de la franja epipolar.

Práctica 2. Reconstrucción 3D: Línea epipolar

El objetivo de la segunda práctica es dotar a un robot de la capacidad de reconstruir su entorno en 3D a través de dos cámaras estéreo.

Para conseguir este objetivo, seguiremos los pasos indicados en la teoría de Reconstrucción 3D de los apuntes de Visión Robótica:

  1. Obtención de Puntos de interés
  2. Búsqueda del punto homólogo
  3. Triangulación
  4. Representación

Así mismo, nos guiaremos a partir a la imagen de representación de funcionamiento de la Reconstrucción 3D mostrada en los apuntes y en los foros de ayuda:

Para el primer paso, aplicamos un filtro de Canny a la imagen izquierda de nuestra cámara, lo cual nos dará los bordes de la imagen. A partir de ahí recorremos la imagen binaria resultante, y los puntos que valgan 1 – sean parte de los bordes – serán nuestros puntos de interés. Lo siguiente, será buscar la línea epipolar del punto en la otra imagen.

Para cada punto de interés realizaremos los pasos indicados en los comentarios del código de la práctica:

  • opticalToGrafic: Convierte el punto de la imagen gráfico, en óptico. Toma como Origen de coordenadas la posición de la cámara.
  • backproject: Convierte el punto óptico en su representación 3D, sabiendo que esta conversión será parte de la recta de retroproyección.
  • project: Proyecta el punto 3D en el plano de la cámara derecha, en coordenadas ópticas.
  • graficToOptical: Convierte el punto óptico a coordenadas gráficas.

Así mismo, para poder obtener la recta epipolar necesitaremos dos puntos, por lo que deberemos obtener la recta de retroproyección de la cámara izquierda y proyectar otro de sus puntos sobre la cámara derecha. Sólo así podremos calcular la epipolar correctamente. Esto lo haremos de la siguiente forma:

p1 = Punto de interés
posCam = self.camLeftP.getCameraPosition
v = p1 – posCam (vector de proyección)
p2 = p1 + v * k (K será un desplazamiento cualquiera)

En mi caso tuve ciertos problemas con la coordenada homóloga, que vale 1 y sirve para el cálculo de la proyección a través de la matriz KRT, y que al tenerse en cuenta en las operaciones no mantenía ese valor de unidad, dando resultados incorrectos. Una vez se hicieron las operaciones sólo con las 3 coordenadas de posición se pudo obtener la recta epipolar correctamente, tal como se puede ver en la imagen (con varios ejemplos de K):

Con esto ya obtendremos un segundo punto que podremos proyectar sobre la cámara derecha y con el que podremos calcular la recta epipolar, siguiendo de nuevo la fórmula de la recta:

El siguiente paso será buscar a partir de esa recta una franja – con varios pixeles arriba y abajo para evitar errores de calibración de la cámara – y recorrerla buscando el parche más parecido al punto de interés de nuestra cámara izquierda. Así encontraremos el punto de interés en la segunda cámara y ya sí podremos obtener la posición 3D de dicho punto