Движение камеры из соответствующих изображений
Я пытаюсь рассчитать новую позицию камеры на основе движения соответствующих изображений. Изображения соответствуют модели камеры-обскуры.
На самом деле, я не получаю полезных результатов, поэтому я пытаюсь описать свою процедуру и надеюсь, что кто-нибудь может мне помочь.
Я сопоставляю свойства соответствующих изображений с SIFT, сопоставляю их с FlannBasedMatcher OpenCV и вычисляю фундаментальную матрицу с помощью findFundamentalMat OpenCV (метод RANSAC).
Затем я вычисляю основную матрицу по внутренней матрице камеры (K):
Mat E = K.t() * F * K;
Я разлагаю основную матрицу на вращение и перевод с разложением по сингулярному значению:
SVD decomp = SVD(E);
Matx33d W(0,-1,0,
1,0,0,
0,0,1);
Matx33d Wt(0,1,0,
-1,0,0,
0,0,1);
R1 = decomp.u * Mat(W) * decomp.vt;
R2 = decomp.u * Mat(Wt) * decomp.vt;
t1 = decomp.u.col(2); //u3
t2 = -decomp.u.col(2); //u3
Затем я пытаюсь найти правильное решение с помощью триангуляции. (эта часть от http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/ поэтому я думаю, что это должно работать правильно).
Новая позиция затем рассчитывается с помощью:
new_pos = old_pos + -R.t()*t;
где new_pos & old_pos - векторы (3x1), R - матрица вращения (3x3) и t - вектор трансляции (3x1).
К сожалению, я не получил никаких полезных результатов, поэтому, возможно, у кого-нибудь есть идея, что может быть не так.
Вот некоторые результаты (на тот случай, если кто-то может подтвердить, что любой из них определенно не прав):
F = [8.093827077399547e-07, 1.102681999632987e-06, -0.0007939604310854831;
1.29246107737264e-06, 1.492629957878578e-06, -0.001211264339006535;
-0.001052930954975217, -0.001278667878010564, 1]
K = [150, 0, 300;
0, 150, 400;
0, 0, 1]
E = [0.01821111092414898, 0.02481034499174221, -0.01651092283654529;
0.02908037424088439, 0.03358417405226801, -0.03397110489649674;
-0.04396975675562629, -0.05262169424538553, 0.04904210357279387]
t = [0.2970648246214448; 0.7352053067682792; 0.6092828956013705]
R = [0.2048034356172475, 0.4709818957303019, -0.858039396912323;
-0.8690270040802598, -0.3158728880490416, -0.3808101689488421;
-0.4503860776474556, 0.8236506374002566, 0.3446041331317597]
2 ответа
Прежде всего вы должны проверить, если
x' * F * x = 0
для ваших точечных соответствий x'
а также x
, Это должно быть, конечно, только в случае с оценками фундаментальной матрицы с помощью RANSAC.
После этого вы должны преобразовать ваши точечные соответствия в нормализованные координаты изображения (NCC), как это
xn = inv(K) * x
xn' = inv(K') * x'
где K'
матрица внутренней камеры второго изображения и x'
точки второго изображения. Я думаю, что в вашем случае это K = K'
,
С помощью этих NCC вы можете разложить свою основную матрицу, как вы описали. Вы триангулируете нормализованные координаты камеры и проверяете глубину ваших триангулированных точек. Но будьте осторожны, в литературе говорится, что одной точки достаточно, чтобы получить правильное вращение и перевод. Исходя из моего опыта, вы должны проверить несколько баллов, так как один балл может быть выбросом даже после RANSAC.
Прежде чем разложить основную матрицу, убедитесь, что E=U*diag(1,1,0)*Vt
, Это условие необходимо для получения правильных результатов для четырех возможных вариантов матрицы проекции.
Когда у вас есть правильное вращение и перемещение, вы можете триангулировать все ваши точечные соответствия (составляющие оценки фундаментальной матрицы с помощью RANSAC). Затем вы должны вычислить ошибку перепроецирования. Во-первых, вы вычисляете перепроектированную позицию следующим образом
xp = K * P * X
xp' = K' * P' * X
где X
вычисленная (однородная) трехмерная позиция. P
а также P'
являются матрицами проекции 3x4. Матрица проекции P
обычно дается личность. P' = [R, t]
задается матрицей вращения в первых 3 столбцах и строках и переводом в четвертом столбце, так что P
матрица 3х4 Это работает, только если вы преобразуете свою трехмерную позицию в однородные координаты, то есть векторы 4x1 вместо 3x1. Затем, xp
а также xp'
также являются однородными координатами, представляющими ваши (перепроецированные) 2D-позиции ваших соответствующих точек.
я думаю
new_pos = old_pos + -R.t()*t;
неверно, так как во-первых, вы переводите только old_pos
и вы не вращаете его, а во-вторых, вы переводите его с неправильным вектором. Правильный путь приведен выше.
Итак, после того, как вы вычислили перепроецированные точки, вы можете вычислить ошибку репроекции. Так как вы работаете с однородными координатами, вы должны их нормализовать (xp = xp / xp(2)
, разделите по последней координате). Это дано
error = (x(0)-xp(0))^2 + (x(1)-xp(1))^2
Если ошибка велика, например, 10^2, ваша внутренняя калибровка камеры или ваш поворот / перемещение неверны (возможно, оба). В зависимости от вашей системы координат вы можете попробовать инвертировать матрицы проекций. Для этого вам необходимо преобразовать их в однородные координаты, так как вы не можете инвертировать матрицу 3х4 (без псевдообращения). Таким образом, добавьте четвертую строку [0 0 0 1], вычислите обратную и удалите четвертую строку.
Есть еще одна вещь с ошибкой перепроецирования. В общем случае ошибка репроекции - это квадрат расстояния между исходным точечным соответствием (на каждом изображении) и репроецированной позицией. Вы можете взять квадратный корень, чтобы получить евклидово расстояние между обеими точками.
Чтобы обновить положение вашей камеры, вы должны сначала обновить перевод, а затем обновить матрицу вращения.
t_ref += lambda * (R_ref * t);
R_ref = R * R_ref;
где t_ref и R_ref - состояние вашей камеры, R и t - новые рассчитанные поворот и перемещение камеры, а лямбда - масштабный коэффициент.