У меня две камеры, прикрепленные жестко бок о бок, глядя в параллельных направлениях.
Матрица проекции для камеры слева
Матрица проекции для правой камеры
Когда я выполняю triangulatePoints
на двух векторах соответствующих точек, я получаю набор точек в трехмерном пространстве. Все точки в трехмерном пространстве имеют отрицательную координату Z.
Итак, чтобы разобраться в этом...
Мое предположение заключалось в том, что OpenCV использует правую систему координат.
Я предполагаю, что начальная ориентация каждой камеры направлена в положительном направлении оси Z.
Итак, используя проекционные матрицы, подобные тем, которые я представил в начале, я бы предположил, что камеры расположены в пространстве следующим образом:
Это предположение противоречит тому, что я наблюдаю, когда получаю отрицательные Z corrdinates для трассирующих точек. Единственное объяснение, о котором я могу думать, это то, что OpenCV фактически использует систему координат левой руки. Итак, с проекционными матрицами, которые я изложил вначале, это то, как камеры расположены в пространстве:
Это означало бы, что моя левая камера в этой ситуации не находится на левой стороне. И именно поэтому я получаю отрицательную глубину для очков.
Кроме того, если я пытаюсь объединить triangulatePoints
с solvePnP
, я сталкиваюсь с проблемами.
Я использую вывод triangulatePoints
в качестве входа в solvePnP
. Я ожидаю получить координаты камеры вблизи начала координат трехмерной системы координат. Я ожидаю, что рассчитанное положение камеры будет соответствовать проекционным матрицам, используемым в начале. Но этого не происходит. Я получаю некоторые совершенно дикие результаты, пропуская ожидаемые значения более чем в 10 раз от базовой длины.
Пример
Этот пример является более полным представлением проблемы, чем указано выше.
Здесь - код для создания этих точек.
Двигайтесь дальше, настраивая камеру A и камеру 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;
Каковы пиксельные координаты points3D
при наблюдении проекциями A и D.
Mat points2D_a = projectionMatrix_a * points3D;
Mat points2D_d = projectionMatrix_d * points3D;
Я помещаю их в векторы:
vector<Point2f> points2Dvector_a, points2Dvector_d;
После этого я снова создаю 3D-точки.
Mat points3DHomogeneous;
triangulatePoints(projectionMatrix_a, projectionMatrix_d, points2Dvector_a, points2Dvector_d, points3DHomogeneous);
Mat triangulatedPoints3D;
transpose(points3DHomogeneous, triangulatedPoints3D);
convertPointsFromHomogeneous(triangulatedPoints3D, triangulatedPoints3D);
Теперь triangulatedPoints3D
начинаются следующим образом:
и они идентичны points3D
.
И затем последний шаг.
Mat rvec, tvec;
solvePnP(triangulatedPoints3D, points2Dvector_d, cameraMatrix, distCoeffs, rvec, tvec);
Результат rvec
и tvec
:
Я надеялся получить нечто более похожее на преобразования, используемые при создании projectionMatrix_d
, т.е. перевод (100, 0, 0) и поворот на 30 ° вокруг оси Y.
Если я использую инвертированные преобразования при создании матрицы проецирования, например:
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;
то я получаю rvec
и tvec
:
И это имеет смысл. Но затем я меняю начальное преобразование так, что вращение отрицательно CV_PI / 6.0
→ -CV_PI / 6.0
, а полученные rvec
и tvec
:
Я хотел бы найти объяснение, почему это происходит. Почему я получаю такие странные результаты от solvePnP
.