Перепроецирование пикселей с одного изображения на другое
У меня есть несколько откалиброванных камер, снимающих плоскую сцену. Для простоты предположим, что есть 3 камеры. Эти камеры подвергаются общему движению, но, в основном, переводу и небольшому вращению. Пример положения камер
Задача состоит в том, чтобы их вообще прошить. Я не знаю о трехмерных координатах, просто набор изображений, сделанных с помощью откалиброванных камер.
Что я делаю:
Я обнаруживаю особенности с реализациями SURF/SIFT в OpenCV, чтобы получить начальные гомографии, используя findHomography между каждой парой изображений (1->2, 2->3, 1->3). Из этих гомографий я получаю первоначальную оценку поз каждой камеры (подобная процедура для этого)
Затем я пытаюсь использовать технику настройки связки, чтобы минимизировать ошибку перепроецирования для каждой подходящей пары. Оптимизированные параметры - это три значения перевода и три значения вращения (полученные из формулы вращения Родригеса), хотя я могу добавить внутренние параметры позже (фокусы, главные точки и т. Д.).
Предполагая, что изображение № 2 будет опорным кадром (имея наибольшее количество совпадений с двумя другими изображениями), его матрицы поворота и перемещения будут единичной и нулевой матрицами соответственно.
Я рассчитываю перепроецирование ключевой точки (видимой как на изображении № 2, так и на изображении № 1) с изображения № 2 на изображение № 1 как (псевдокод)
[x1_; y1_; z1_] = K1*R1*inv(K2)*[x2; y2; 1] + K1*T1/Z2;
x1 = x1_/z1_;
y1 = y1_/z1_;
или же
x1 = ((f1/f2)*r11*x2 + (f1/f2)*r12*y2 + f1*r13 + f1*tx/Z2) / ((1/f2)*r31*x2 + (1/f2)*r32*y2 + r33 + tx/Z2)
y1 = ((f1/f2)*r21*x2 + (f1/f2)*r22*y2 + f1*r23 + f1*ty/Z2) / ((1/f2)*r31*x2 + (1/f2)*r32*y2 + r33 + ty/Z2)
где r__ являются элементами матрицы R1, и обе внутренние матрицы имеют вид
[f 0 0]
[0 f 0]
[0 0 1]
Я предполагаю, что координата Z2 системы отсчета равна 1.
Следующим этапом является деформирование изображений № 1 и № 3 в общую систему координат изображения № 2 с использованием полученных матриц камеры (K1,R1,T1,K3,R3,T3).
Проблема в том, что у меня нет знаний о Z1 и Z3, необходимых для правильного перепроецирования в систему отсчета изображения #2, потому что обратное перепроецирование из изображения #1->#2 выглядит следующим образом:
x2 = ((f2/f1)*R11*x1 + (f2/f1)*R12*y1 + f2*R13 - f0/Z1*(R11*tx + R12*ty + R13*tz)) / ((1/f1)*R31*x1 + (1/f1)*R32*y1 + R33 - 1/Z1*(R31*tx + R32*ty + R33*tz))
y2 = ((f2/f1)*R21*x1 + (f2/f1)*R22*y1 + f2*R23 - f0/Z1*(R21*tx + R22*ty + R23*tz)) / ((1/f1)*R31*x1 + (1/f1)*R32*y1 + R33 - 1/Z1*(R31*tx + R32*ty + R33*tz))
где R__ - элементы матрицы inv(R1).
Есть ли лучший способ вычисления ошибки репроекции для настройки пучка (2d->2d), а затем деформировать изображения в общую систему координат? Я заметил, что OpenCV имеет очень похожую структуру в их модуле сшивания, но он работает в предположении чисто вращательного движения, что здесь не так.
2 ответа
Я автоматически ответил на этот вопрос в своем посте Как получить очки в стереоизображении по внешним параметрам
Обратите внимание, что метод, который я использую (протестировано и работает!), Действителен только в том случае, если объект в трехмерных координатах (реальный мир!) Является плоским и находится при Z=0 (точке, в которой вы калибровали внешние параметры камер). В этом случае этот метод так же точен, как и ваша калибровка. Примечание: для лучшей проверки калибровки круга openCVs, у него есть ошибка перепроверки 0,018 пикселей (проверено аспирантом, работающим в моем университете).
Вы, вероятно, обнаружили ошибку в ошибке повторного проецирования. Это связано с этой строкой:
[x1_; y1_; z1_] = K1*R1*inv(K2)*[x2; y2; 1] + K1*T1/Z2;
Точка [х2; у2; 1] неоднозначно с точностью до постоянной масштаба, C*[x2; у2; 1] и здесь вы устанавливаете C=1, когда оно вообще неизвестно. На первый взгляд локус возможностей проявляется как эпиполярная линия. Вы можете использовать триангуляцию наименьших квадратов, чтобы найти наиболее вероятную точку вдоль этой линии, в которой существует 3D-точка, а затем вычислить повторно спроецированную точку следующим образом:
[x1_; y1_; z1_] = K1*(R1*X + T1);
и продолжайте оттуда, как у вас есть выше. Трехмерные координаты каждой такой точки X в вашем облаке точек можно вычислить, используя соответствующие нормализованные координаты (x1,y1), (x2,y2),..., а также соответствующие матрицы вращения и векторы переноса, отформатировав их в матричной задаче:
A X = b
и затем решение наименьших квадратов:
min |A X - b|_2
что показано на страницах 3 и 4 здесь.