Подтвердить что ты не робот

Ручная работа с треугольными точками OpenCV

У меня две камеры, прикрепленные жестко бок о бок, глядя в параллельных направлениях.

Матрица проекции для камеры слева Матрица проецирования для левой камеры

Матрица проекции для правой камеры Матрица проекции для правой камеры

Когда я выполняю triangulatePoints на двух векторах соответствующих точек, я получаю набор точек в трехмерном пространстве. Все точки в трехмерном пространстве имеют отрицательную координату Z.

Итак, чтобы разобраться в этом...

Мое предположение заключалось в том, что OpenCV использует правую систему координат.

Напоминание о руке: Напоминание о Handedness

Я предполагаю, что начальная ориентация каждой камеры направлена ​​ в положительном направлении оси Z.

Итак, используя проекционные матрицы, подобные тем, которые я представил в начале, я бы предположил, что камеры расположены в пространстве следующим образом:

Как я полагаю, камеры расположены и ориентированы в пространстве

Это предположение противоречит тому, что я наблюдаю, когда получаю отрицательные Z corrdinates для трассирующих точек. Единственное объяснение, о котором я могу думать, это то, что OpenCV фактически использует систему координат левой руки. Итак, с проекционными матрицами, которые я изложил вначале, это то, как камеры расположены в пространстве:

Камеры в левой системе координат

Это означало бы, что моя левая камера в этой ситуации не находится на левой стороне. И именно поэтому я получаю отрицательную глубину для очков.

Кроме того, если я пытаюсь объединить triangulatePoints с solvePnP, я сталкиваюсь с проблемами.

Я использую вывод triangulatePoints в качестве входа в solvePnP. Я ожидаю получить координаты камеры вблизи начала координат трехмерной системы координат. Я ожидаю, что рассчитанное положение камеры будет соответствовать проекционным матрицам, используемым в начале. Но этого не происходит. Я получаю некоторые совершенно дикие результаты, пропуская ожидаемые значения более чем в 10 раз от базовой длины.

Пример

Этот пример является более полным представлением проблемы, чем указано выше.

points3D введите описание изображения здесь

Здесь - код для создания этих точек.

Двигайтесь дальше, настраивая камеру 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.

4b9b3361

Ответ 1

Система координат OpenCV правша, ответ здесь дает иллюстративный пример о системе камеры OpenCV. Я думаю, что путаница - это rvec и tvec, последняя не дает перевода камеры, но указывает на мировое происхождение. Первый ответ здесь объясняет это на примере. Вы можете получить фактическую матрицу проекции из вывода solvePnP простым умножением матрицы, детали здесь в первом ответе.