Движение камеры из соответствующих изображений

Я пытаюсь рассчитать новую позицию камеры на основе движения соответствующих изображений. Изображения соответствуют модели камеры-обскуры.

На самом деле, я не получаю полезных результатов, поэтому я пытаюсь описать свою процедуру и надеюсь, что кто-нибудь может мне помочь.

Я сопоставляю свойства соответствующих изображений с 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 - новые рассчитанные поворот и перемещение камеры, а лямбда - масштабный коэффициент.

Другие вопросы по тегам