Siguiendo donde terminé en la publicación anterior. Ahora quedaba recorrer toda la imagen izquierda(gradiente) con el tamaño de ventana (30x30 píxeles) y calcular la linea epipolar.
Para ello, se han utilizado las funciones internas de self.camLeftP y self.camRightP:
point2d = graficToOptical(point2d)
&
point3d = backProject(point2d)
&
point3d = getCameraPosition(self)
&
point2d = project(point3d)
&
point2d = opticalToGraphic(point2d)
&
point3d = getCameraPosition(self)
&
point2d = project(point3d)
&
point2d = opticalToGraphic(point2d)
Con la función graficToOptical(point2d) se transforma el punto 2D de la imagen izquierda (el centro de la ventana creada) en el punto 2D óptico y a través de la función backProject(point2d) se obtiene la retro-proyección del punto 2D óptico en el punto 3D de la escena.
Con las función getCameraPosition(self) de la cámara izquierda se puede obtener la posición en 3 dimensiones de la cámara. Esta posición, junto con el punto 3D de la escena servirán para calcular el punto en la imagen(Graphic) de la cámara derecha, para ello se utiliza esta función:
point3d = B + ((A - B) * 4)
Siendo A y B la posición 3D de la cámara izquierda y el punto 3D retro-proyectado del centro de la la ventana izquierda.
Para ello, se utilizan las funciones project(point2d) y opticalToGraphic(point2d). Primero para obtener el primer punto, con el punto 3D retro-proyectado del centro de la la ventana izquierda, y el segundo punto3d (point3d) de la anterior fórmula.
Después con el primer punto y restando y sumando el doble de la diferencia de ambos respectivamente, se obtienen los dos puntos para calcular la línea epipolar (P1 y P2 en el código).
Para calcular los puntos de la línea se utiliza la biblioteca bresenham que dado dos puntos te da todos los puntos que unen ambos en línea recta. Pero viendo los resultados que se obtenían, aparecían puntos negativos y decidí hacer un filtrado de estos puntos, eliminando aquellos que no se encontraban dentro de la imagen.
Con esto se conseguiría saber cuales son los puntos de la línea epipolar y ahora solo quedaría buscar en la imagen de la derecha para saber que ventana se parece más a la actual de la imagen izquierda.
Primeramente, se ha utilizado el sumatorio de la diferencia absoluta de los píxeles entre estas ventanas y encontrando el mínimo valor:
min(Σ((WindowL - WindowLMean) - (WindowR - WindowRMean)))
Pero al ver los resultados obtenidos no eran muy buenos, y viendo los blogs de los ex-compañeros decidí cambiarlo por la correlación(equality en el código) entre ambas ventanas. Calculando la siguiente fórmula:
max(Σ((WindowL - WindowLMean) * (WindowR - WindowRMean)))
Con esto, ya daba buenos resultados.
Se han intentado visualizar ambas ventanas, para comprobar que eran iguales, en las imageFiltered del GUI pero internamente como se modifica el tamaño y aparecen cortadas por arriba, abajo y a los lados, se ha optado por mostrar con OpenCV.
Como estas imágenes filtradas quedaban vacías se ha utilizado la imagen de la izquierda para mostrar el avance de la línea actual en verde sobre la imageLeft. Aunque como también aparece recortada, tarda un rato en aparecer en pantalla, en el siguiente vídeo se puede observar:
Como se puede ver en el vídeo, son muy similares ambas ventanas(Si va muy rápido se puede pausar el vídeo para comprobarlo).
Todo esto se ha realizado con los píxeles de la imagen que tienen un gradiente mayor a 0,3 para saber que hay un borde en esa zona y no realizar ninguna comprobación en el fondo o las zonas homogéneas.
Ahora tan solo quedaría con los dos píxeles centrales, encontrar el punto 3D de la escena y dibujarlo en el 3D Viewer-web.
No hay comentarios:
Publicar un comentario