Ответ 1
cv::Stitcher
довольно медленный. Если ваши камеры определенно не перемещаются относительно друг друга, и преобразование так же просто, как вы говорите, вы должны иметь возможность накладывать изображения на пустой холст просто путем цепочки homographies.
Следующее несколько математическое - если это не ясно, я могу правильно записать его с помощью LaTeX, но SO не поддерживает симпатичную математику:)
У вас есть набор из 4-х камер слева направо, (C_1, C_2, C_3, C_4)
, что дает набор из 4 изображений (I_1, I_2, I_3, I_4)
.
Чтобы преобразовать из I_1
в I_2
, у вас есть матрица преобразования 3x3, называемая гомографией. Мы назовем это H_12
. Аналогично для I_2
to I_3
имеем H_23
, а для I_3
- I_4
у вас будет H_34
.
Вы можете предварительно откалибровать эти гомологии заранее, используя стандартный метод (совпадение точек между перекрывающимися камерами).
Вам нужно будет создать пустую матрицу, чтобы действовать как холст. Вы можете догадаться, размер этого (4 * image_size будет достаточным), или вы можете взять верхний правый угол (назовите это P1_tr
) и преобразовать его тремя гомологиями, указав новую точку в правом верхнем углу панорамы, PP_tr
(предполагается, что P1_tr
преобразован в матрицу):
PP_tr = H_34 * H_23 * H_12 * P1_tr'
Что это делает, принимает P1_tr
и сначала преобразует его в камеру 2, затем от C_2
до C_3
и, наконец, от C_3
до C_4
Вам понадобится создать один из них для объединения изображений 1 и 2, изображений 1,2 и 3 и, наконец, изображений 1-4, я буду называть их V_12
, V_123
и V_1234
соответственно.
Используйте следующее, чтобы преобразовать изображение на холст:
cv::warpAffine(I_2, V_12, H_12, V_12.size( ));
Затем сделайте то же самое со следующими изображениями:
cv::warpAffine(I_3, V_123, H_23*H_12, V_123.size( ));
cv::warpAffine(I_4, V_1234, H_34*H_23*H_12, V_1234.size( ));
Теперь у вас есть четыре холста, каждая из которых представляет собой ширину 4 комбинированных изображений, и с одним из изображений, преобразованных в соответствующее место на каждом.
Все, что остается, - объединить преобразованные изображения друг на друга. Это легко достигается с помощью интересующих регионов.
Создание масок ROI может выполняться заранее, прежде чем начнется захват кадра.
Начните с пустого (нулевого) изображения того же размера, что и ваши холсты. Установите крайний левый прямоугольник размером I_1
на белый. Это маска для вашего первого изображения. Мы назовем его M_1
.
Затем, чтобы получить маску для второго преобразованного изображения, сделаем
cv::warpAffine(M_1, M_2, H_12, M_1.size( ));
cv::warpAffine(M_2, M_3, H_23*H_12, M_1.size( ));
cv::warpAffine(M_3, M_4, H_34*H_23*H_12, M_1.size( ));
Чтобы объединить все изображения в одну панораму, выполните следующие действия:
cv::Mat pano = zeros(M_1.size( ), CV_8UC3);
I_1.copyTo(pano, M_1);
V_12.copyTo(pano, M_2):
V_123.copyTo(pano, M_3):
V_1234.copyTo(pano, M_4):
Что вы здесь делаете, копирование соответствующей области каждого холста на выходное изображение, pano - быстрая операция.
Вы можете сделать все это на графическом процессоре, заменив cv::gpu::Mat
на cv::Mats
и cv::gpu::warpAffine
для своего не-графического экземпляра.