c++ - OpenCV triangulatePoints la destreza
triangulation (1)
El sistema de coordenadas OpenCV es diestro, la respuesta here brinda un ejemplo ilustrativo sobre el sistema de cámara OpenCV. Supongo que la confusión es sobre rvec
y tvec
, este último no da la traducción de la cámara, pero apunta al origen mundial. La primera respuesta here explica basado en un ejemplo. Puede obtener la matriz de proyección real a partir de la salida de solvePnP
mediante una simple multiplicación de matrices, los detalles están here en la primera respuesta.
Tengo dos cámaras unidas rígidamente una al lado de la otra mirando en direcciones paralelas.
Matriz de proyección para cámara izquierda
Matriz de proyección para la cámara derecha
Cuando realizo triangulatePoints
en los dos vectores de los puntos correspondientes, obtengo la colección de puntos en el espacio 3D. Todos los puntos en el espacio 3D tienen una coordenada Z negativa .
Entonces, para llegar al fondo de esto ...
Mi suposición era que OpenCV usa el sistema de coordenadas de la mano derecha.
El recordatorio de la destreza:
Supongo que la orientación inicial de cada cámara se dirige en la dirección positiva del eje Z.
Entonces, al usar las matrices de proyección como las que presenté al principio, supongo que las cámaras están posicionadas en el espacio así:
Esta suposición está en conflicto con lo que observo cuando obtengo valores negativos de Z para los puntos traingulados. La única explicación que puedo pensar es que OpenCV de hecho usa el sistema de coordenadas de la mano izquierda. Entonces, con las matrices de proyección que dije al principio, así es como las cámaras están posicionadas en el espacio:
Esto indicaría que mi cámara izquierda en esta situación no está en el lado izquierdo . Y es por eso que estoy obteniendo profundidad negativa para los puntos.
Además, si intento combinar triangulatePoints
con solvePnP
tengo problemas.
Uso la salida de triangulatePoints
como una entrada para solvePnP
. Espero obtener las coordenadas de la cámara cerca del origen del sistema de coordenadas 3D. Espero que la posición calculada de la cámara coincida con las matrices de proyección utilizadas al principio. Pero esto no está sucediendo. Obtengo algunos resultados totalmente desordenados, faltando los valores esperados por más de 10 veces la longitud de línea base.
Ejemplo
Este ejemplo es una representación más completa del problema que lo que se indicó anteriormente.
Here está el código para generar estos puntos.
Movin, configurando la cámara A y la cámara D ...
Mat cameraMatrix = (Mat_<double>(3, 3) <<
716.731, 0, 660.749,
0, 716.731, 360.754,
0, 0, 1);
Mat distCoeffs = (Mat_<double>(5, 1) << 0, 0, 0, 0, 0);
Mat rotation_a = Mat::eye(3, 3, CV_64F); // no rotation
Mat translation_a = (Mat_<double>(3, 1) << 0, 0, 0); // no translation
Mat rt_a;
hconcat(rotation_a, translation_a, rt_a);
Mat projectionMatrix_a = cameraMatrix * rt_a;
Mat rotation_d = (Mat_<double>(3, 1) << 0, CV_PI / 6.0, 0); // 30° rotation about Y axis
Rodrigues(rotation_d, rotation_d); // convert to 3x3 matrix
Mat translation_d = (Mat_<double>(3, 1) << 100, 0, 0);
Mat rt_d;
hconcat(rotation_d, translation_d, rt_d);
Mat projectionMatrix_d = cameraMatrix * rt_d;
¿Cuáles son las coordenadas de píxeles de los points3D
cuando se observan por las proyecciones A y D ?
Mat points2D_a = projectionMatrix_a * points3D;
Mat points2D_d = projectionMatrix_d * points3D;
Los puse en vectores:
vector<Point2f> points2Dvector_a, points2Dvector_d;
Después de eso, genero los puntos 3D nuevamente.
Mat points3DHomogeneous;
triangulatePoints(projectionMatrix_a, projectionMatrix_d, points2Dvector_a, points2Dvector_d, points3DHomogeneous);
Mat triangulatedPoints3D;
transpose(points3DHomogeneous, triangulatedPoints3D);
convertPointsFromHomogeneous(triangulatedPoints3D, triangulatedPoints3D);
Ahora, triangulatedPoints3D
comienza así:
y son idénticos a points3D
.
Y luego el último paso.
Mat rvec, tvec;
solvePnP(triangulatedPoints3D, points2Dvector_d, cameraMatrix, distCoeffs, rvec, tvec);
rvec
y tvec
resultantes:
Tenía la esperanza de obtener algo más similar a las transformaciones utilizadas en la creación de projectionMatrix_d
, es decir, la traducción de (100, 0, 0) y la rotación de 30 ° alrededor del eje Y.
Si uso transformaciones invertidas al crear una matriz de proyección, como esta:
Mat rotation_d = (Mat_<double>(3, 1) << 0, CV_PI / 6.0, 0); // 30° rotation about Y axis
Rodrigues(-rotation_d, rotation_d); // NEGATIVE ROTATION
Mat translation_d = (Mat_<double>(3, 1) << 100, 0, 0);
Mat rt_d;
hconcat(rotation_d, -translation_d, rt_d); // NEGATIVE TRANSLATION
Mat projectionMatrix_d = cameraMatrix * rt_d;
entonces obtengo rvec
y tvec
:
Y eso tiene mucho más sentido. Pero luego cambio la transformación de inicio para que la rotación sea negativa CV_PI / 6.0
-> -CV_PI / 6.0
y los rvec
y tvec
resultantes son:
Me gustaría encontrar una explicación de por qué está sucediendo esto. ¿Por qué estoy obteniendo resultados tan extraños de solvePnP
?