Blog
Aprenderemos lo básico de la geometría multiview
Veremos el epipole, las líneas epipolares, la restricción epipolar etc.
Conceptos básicos
Cuando tomamos una imagen con la cámara, perdemos una información importante, es decir, la profundidad de la imagen. O qué tan lejos está cada punto de la imagen de la cámara porque es una conversión de 3D a 2D. Así que es una pregunta importante si podemos encontrar la información de profundidad usando estas cámaras. Y la respuesta es usar más de una cámara. Nuestros ojos funcionan de la misma manera que cuando usamos dos cámaras (dos ojos) que se llama visión estéreo. Veamos lo que ofrece OpenCV en este campo.
Antes de ir a las imágenes de profundidad, vamos a entender primero algunos conceptos básicos en geometría multiview. En esta sección trataremos la geometría epipolar. Vea la imagen de abajo que muestra una configuración básica con dos cámaras tomando la imagen de la misma escena.
Geometría epipolar
Si estamos usando sólo la cámara izquierda, no podemos encontrar el punto 3D correspondiente al punto x en la imagen porque cada punto de la línea OX se proyecta al mismo punto en el plano de la imagen. Pero considere también la imagen correcta. Ahora diferentes puntos de la línea OX se proyectan a diferentes puntos (x’) en el plano derecho. Así que con estas dos imágenes podemos triangular el punto 3D correcto. Esta es toda la idea.
La proyección de los diferentes puntos en OX forman una línea en el plano derecho (línea l’). Lo llamamos epilina correspondiente al punto x. Significa, para encontrar el punto x en la imagen derecha, buscar a lo largo de esta epilina. Debería estar en algún lugar de esta línea (Piensa de esta manera, para encontrar el punto de coincidencia en otra imagen, no necesitas buscar la imagen completa, sólo buscar a lo largo de la epilina. Por lo tanto, proporciona un mejor rendimiento y precisión). Esto se llama Restricción Epipolar. Del mismo modo, todos los puntos tendrán sus correspondientes epilíneas en la otra imagen. El avión XOO’ se llama Epipolar Plane.
O y O’ son los centros de la cámara. A partir de la configuración dada anteriormente, se puede ver que la proyección de la cámara derecha O’ se ve en la imagen izquierda en el punto, e. Se llama epípolo. Epipole es el punto de intersección de la línea a través de los centros de la cámara y los planos de la imagen. Similarmente e’ es el epípolo de la cámara izquierda. En algunos casos, no podrá localizar el epípolo en la imagen, puede que esté fuera de la imagen (lo que significa que una cámara no ve la otra).
Todas las epilinas pasan por su epipolo. Así que para encontrar la ubicación de epipole, podemos encontrar muchas epilinas y encontrar su punto de intersección.
Así que en esta sesión, nos enfocamos en encontrar líneas epipolares y epípoles. Pero para encontrarlos, necesitamos dos ingredientes más, la Matriz Fundamental (F) y la Matriz Esencial (E). Essential Matrix contiene la información sobre traslación y rotación, que describe la ubicación de la segunda cámara en relación con la primera en coordenadas globales. Vea la imagen de abajo:
Matriz esencial
Pero preferimos que las mediciones se hagan en coordenadas de píxeles, ¿no? Fundamental Matrix contiene la misma información que Essential Matrix además de la información sobre los intrínsecos de ambas cámaras para que podamos relacionar las dos cámaras en coordenadas de píxeles. (Si estamos utilizando imágenes rectificadas y normalizamos el punto dividiendo las distancias focales, F=E). En palabras simples, la Matriz Fundamental F, asigna un punto en una imagen a una línea (epilínea) en la otra imagen. Esto se calcula a partir de los puntos de coincidencia de ambas imágenes. Se requieren un mínimo de 8 puntos de este tipo para encontrar la matriz fundamental (utilizando un algoritmo de 8 puntos). Se prefieren más puntos y utilice RANSAC para obtener un resultado más sólido.
Código de Geometría Epipolar
Así que primero necesitamos encontrar la mayor cantidad posible de coincidencias entre dos imágenes para encontrar la matriz fundamental. Para ello, utilizamos descriptores SIFT con un matcher basado en FLANN y una prueba de ratio.
import cv2 import numpy as np from matplotlib import pyplot as plt img1 = cv2.imread('myleft.jpg',0) #queryimage # left image img2 = cv2.imread('myright.jpg',0) #trainimage # right image sift = cv2.SIFT() #Encuentra los puntos clave y descriptores con SIFT kp1, des1 = sift.detectAndCompute(img1,None) kp2, des2 = sift.detectAndCompute(img2,None) # FLANN parametros FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params,search_params) matches = flann.knnMatch(des1,des2,k=2) good = [] pts1 = [] pts2 = [] # prueba de proporción según el paper de Lowe' s for i,(m,n) in enumerate(matches): if m.distance < 0.8*n.distance: good.append(m) pts2.append(kp2[m.trainIdx].pt) pts1.append(kp1[m.queryIdx].pt)
Ahora tenemos la lista de las mejores coincidencias de ambas imágenes. Busquemos la Matriz Fundamental.
pts1 = np.int32(pts1) pts2 = np.int32(pts2) F, mask = cv2.findFundamentalMat(pts1,pts2,cv2.FM_LMEDS) # We select only inlier points pts1 = pts1[mask.ravel()==1] pts2 = pts2[mask.ravel()==1]
Luego encontramos las epilinas. Las epilíneas correspondientes a los puntos de la primera imagen se dibujan en la segunda imagen. Así que mencionar las imágenes correctas es importante aquí. Tenemos un arsenal de líneas. Así que definimos una nueva función para dibujar estas líneas en las imágenes.
def drawlines(img1,img2,lines,pts1,pts2): ''' img1 - image on which we draw the epilines for the points in img2 lines - corresponding epilines ''' r,c = img1.shape img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR) img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR) for r,pt1,pt2 in zip(lines,pts1,pts2): color = tuple(np.random.randint(0,255,3).tolist()) x0,y0 = map(int, [0, -r[2]/r[1] ]) x1,y1 = map(int, [c, -(r[2]+r[0]*c)/r[1] ]) img1 = cv2.line(img1, (x0,y0), (x1,y1), color,1) img1 = cv2.circle(img1,tuple(pt1),5,color,-1) img2 = cv2.circle(img2,tuple(pt2),5,color,-1) return img1,img2
Ahora encontramos las epilinas en ambas imágenes y las dibujamos.
#Encuentra epilíneas correspondientes a puntos en la imagen derecha (segunda imagen) y # dibujando sus líneas en la imagen de la izquierda lines1 = cv2.computeCorrespondEpilines(pts2.reshape(-1,1,2), 2,F) lines1 = lines1.reshape(-1,3) img5,img6 = drawlines(img1,img2,lines1,pts1,pts2) # Encuentra epilíneas correspondientes a puntos en la imagen de la izquierda (primera imagen) y # dibujando sus líneas en la imagen derecha lines2 = cv2.computeCorrespondEpilines(pts1.reshape(-1,1,2), 1,F) lines2 = lines2.reshape(-1,3) img3,img4 = drawlines(img2,img1,lines2,pts2,pts1) plt.subplot(121),plt.imshow(img5) plt.subplot(122),plt.imshow(img3) plt.show()
Abajo está el resultado que obtenemos:
Usted puede ver en la imagen de la izquierda que todas las epilíneas convergen en un punto fuera de la imagen del lado derecho. Ese punto de encuentro es el epípolo.
Para obtener mejores resultados, se deben utilizar imágenes con buena resolución y muchos puntos no planares.
Conociendo la geometría epipolar se pueden realizar efectos cada vez más complejos.
Aprende técnicas mas complejas y útiles en nuestro Curso Python de OpenCV:
[…] ➡ Geometría Epipolar […]