Предположим, у меня есть хорошее соответствие между двумя изображениями и попытка восстановить движение камеры между ними.
Я могу использовать для этого новые возможности OpenCV 3, например:
Mat E = findEssentialMat(imgpts1, imgpts2, focal, principalPoint, RANSAC, 0.999, 1, mask);
int inliers = recoverPose(E, imgpts1, imgpts2, R, t, focal, principalPoint, mask);
Mat mtxR, mtxQ;
Mat Qx, Qy, Qz;
Vec3d angles = RQDecomp3x3(R, mtxR, mtxQ, Qx, Qy, Qz);
cout << "Translation: " << t.t() << endl;
cout << "Euler angles [x y z] in degrees: " << angles.t() << endl;
Теперь у меня есть проблемы, оборачиваясь вокруг того, что R
а также t
на самом деле значит. Являются ли они преобразованием, необходимым для отображения координат из пространства 1 камеры в пространство 2 камеры, как в p_2 = R * p_1 + t
?
Рассмотрим этот пример с помеченными вручную соответствиями
Вывод, который я получаю это:
Translation: [-0.9661243151855488, -0.04921320381132761, 0.253341406362796]
Euler angles [x y z] in degrees: [9.780449804801876, 46.49315494782735, 15.66510133665445]
Я пытаюсь сопоставить это с тем, что вижу на изображении, и придумываю [-0.96,-0.04,0.25]
говорит мне, что я сдвинулся вправо, так как координаты сместились вдоль отрицательной оси X, но также сказал бы, что я сдвинулся дальше, поскольку координаты сместились вдоль положительной оси Z.
Я также повернул камеру вокруг оси Y (влево, который, я думаю, будет вращаться против часовой стрелки вокруг отрицательной оси Y, потому что в OpenCV, ось Y направлена вниз, не так ли?)
Вопрос: Верна ли моя интерпретация, и если нет, то какая?
Оказывается, моя интерпретация верна, отношение p2 = R * p1 + t
действительно имеет место. В этом можно убедиться, используя cv::triangulatePoints()
а также cv::convertPointsFromHomogeneous
получить трехмерные координаты из соответствующих точек (относительно камеры 1) и затем применить вышеупомянутое уравнение. Умножение на матрицу камеры камеры 2 дает p2
координаты изображения.
Твоя интерпретация звучит как раз для меня. Я не на 100% об ориентации оси в OpenCV, но я верю, что вы правы относительно оси Y.
Вывод также имеет смысл, не только с точки зрения кода, но если вы посмотрите на эти два изображения, вы можете приблизительно представить, куда будет направлен полный поворот на 90 градусов (по сути, это будет тот же угол, но на противоположной стороне автомобиля). )
Это довольно приличное объяснение концепции с помощью механики Rigid Body Motion:
http://nghiaho.com/?page_id=671
На самом деле ваша интерпретация верна.
Прежде всего, вы правы насчет ориентации оси Y. Для иллюстрации системы координат камеры OpenCV см. Вот.
Ваш код вернет R и T со второй камеры на первую. Это означает, что если x1 — это точка на первом изображении, а x2 — это точка на втором изображении, выполняется следующее уравнение x1 = R*x2 + t
,
Теперь в вашем случае правое изображение (вид спереди) с камеры 1, а левое изображение (вид сбоку) автомобиля с камеры 2.
Глядя на это уравнение, мы видим, что в первую очередь применяется вращение. Таким образом, изображение вашей камеры в настоящее время снимает левую рамку. Теперь ваш R задает угол поворота около 46 градусов вокруг оси y. Поскольку точки поворота на угол альфа совпадают с вращением оси координат на этот угол, ваш R говорит вам повернуть налево. Как вы сами указываете, это кажется правильным, если смотреть на фотографии. Поскольку повороты вокруг других осей малы и их трудно отобразить, давайте здесь их опустить.
Таким образом, после применения поворота вы все еще стоите в том же положении, из которого была снята левая рамка, но ваша камера более или менее указывает на заднюю часть автомобиля или пространство непосредственно за автомобилем.
Теперь давайте посмотрим на вектор перевода. Ваша интерпретация движения вправо и дальше также верна. Позвольте мне попытаться объяснить, почему. Представьте себе с вашей текущей позиции, с новым направлением камеры вы двигаетесь только вправо. Вы бы непосредственно столкнулись с автомобилем или вам нужно было держать камеру над капотом двигателя. Поэтому после перемещения вправо вам также нужно отойти еще дальше, чтобы достичь положения, из которого вы сделали правильный снимок.
Я надеюсь, что это объяснение помогло вам представить движение, которое описывают ваши R и T.
Посмотрим. Координатная рамка камеры OpenCV имеет вид «X к изображению справа, Y к изображению снизу, Z = X x Y к сцене». Q = [R | t] — это преобразование координат от камеры2 к камере1, так что t — это вектор, укорененный в камере1, с наконечником в камере2, выраженный в кадре камеры1. Таким образом, ваш вектор перевода подразумевает, что camera2 находится слева от камеры 1, что, учитывая ваши изображения, возможно только в том случае, если вид сбоку автомобиля находится в camera2, а вид спереди автомобиля находится в camera 1. Это согласуется с положительным Z-компонентом перевода, так как при виде сбоку автомобиль появляется дальше от камеры.
Эта идентификация также согласуется с углами Эйлера, которые вы вычислили: они возвращаются в соглашении OpenGL, таким образом выражая поворот от источника к месту назначения. В вашем случае вращение на 46 градусов вокруг вертикальной оси камеры1, против часовой стрелки w.r.t. направленная вниз ось Y, приближает вас к боковому виду.