Класс брошюровщиков OpenCV с перекрывающимися стационарными камерами

Я пытаюсь использовать класс брошюровщика OpenCV для сшивания нескольких кадров из стереофонической установки, в которой ни одна камера не двигается. Я получаю плохие результаты сшивания при работе через несколько кадров. Я пробовал несколько разных способов, которые я постараюсь объяснить здесь.

С помощью stitcher.stitch( )

Учитывая стереопару представлений, я запустил следующий код для некоторых кадров (VideoFile пользовательская оболочка для OpenCV VideoCapture объект):

VideoFile f1( ... );
VideoFile f2( ... );
cv::Mat output_frame;
cv::Stitcher stitcher = cv::Stitcher::createDefault(true);

for( int i = 0; i < num_frames; i++ ) {
currentFrames.push_back(f1.frame( ));
currentFrames.push_back(f2.frame( ));
stitcher.stitch( currentFrames, output_mat );

// Write output_mat, put it in a named window, etc...

f1.next_frame();
f2.next_frame();
currentFrames.clear();
}

Это дало действительно неплохие результаты для каждого кадра, но так как параметры оцениваются для каждого кадра, вставленного в видео, вы можете увидеть небольшие различия в строчке, где параметры немного различаются.

С помощью estimateTransform( ) & composePanorama( )

Чтобы обойти проблему вышеупомянутого метода, я решил попробовать оценить параметры только в первом кадре, а затем использовать composePanorama( ) прошивать все последующие кадры.

for( int i = 0; i < num_frames; i++ ) {
currentFrames.push_back(f1.frame( ));
currentFrames.push_back(f2.frame( ));

if( ! have_transform ) {
status = stitcher.estimateTransform( currentFrames );
}

status = stitcher.composePanorama(currentFrames, output_frame );

// ... as above
}

К сожалению, похоже, ошибказадокументировано здесь) что два вида разошлись очень странным образом, как на рисунках ниже:

Кадр 1:
Кадр 1

Кадр 2:
Кадр 2

Рамка 8:
Рамка 8

Очевидно, что это бесполезно, но я подумал, что это может быть только из-за ошибки, которая в основном продолжает умножать матрицу внутренних параметров на константу каждый раз composePanorama() называется. Поэтому я сделал небольшое исправление для ошибки, чтобы не допустить этого, но затем результаты сшивания были плохими. Патч ниже (modules/stitching/src/stitcher.cpp), результаты потом:

243             for (size_t i = 0; i < imgs_.size(); ++i)
244             {
245                 // Update intrinsics
246                // change following to *=1 to prevent scaling error, but messes up stitching.
247                 cameras_[i].focal *= compose_work_aspect;
248                 cameras_[i].ppx *= compose_work_aspect;
249                 cameras_[i].ppy *= compose_work_aspect;

Результаты:
Кадр 3
Рамка 4

Кто-нибудь знает, как я могу решить эту проблему? В основном мне нужно выработать преобразование один раз, затем используйте его на оставшихся кадрах (мы говорим 30 минут видео).

В идеале я ищу несколько советов по исправлению класса брошюровщика, но я бы хотел попробовать вручную написать другое решение. Более ранняя попытка, которая включала в себя поиск точек SURF, их корреляцию и обнаружение гомографии, дала довольно плохие результаты по сравнению с классом брошюровщиков, поэтому я предпочел бы использовать их, если это возможно.

16

Решение

Итак, в конце концов, я взломал код stitcher.cpp и получил что-то близкое к решению (но не идеальное, так как шов по-прежнему сильно меняется, поэтому ваш пробег может отличаться).

Изменения в stitcher.hpp

Добавлена ​​новая функция setCameras() в строке 136:

void setCameras( std::vector<detail::CameraParams> c ) {

this->cameras_ = c;
}`

Добавлена ​​новая закрытая переменная-член, чтобы отслеживать, является ли это нашей первой оценкой:

bool _not_first;

Изменения в stitcher.cpp

В estimateTransform() (строка ~ 100):

this->not_first = 0;
images.getMatVector(imgs_);
// ...

В composePanorama() (строка ~ 227):

// ...
compose_work_aspect = compose_scale / work_scale_;

// Update warped image scale
if( !this->not_first ) {
warped_image_scale_ *= static_cast<float>(compose_work_aspect);
this->not_first = 1;
}

w = warper_->create((float)warped_image_scale_);
// ...

Код вызова stitcher объект:

Таким образом, в основном, мы создаем объект брошюровщика, затем получаем преобразование в первом кадре (сохраняя матрицы камеры вне класс брошюровщика). Брошюровщик тогда сломает Внутреннюю Матрицу где-нибудь вдоль линии, вызывая перепутывание следующего кадра. Поэтому перед обработкой мы просто сбрасываем камеры, используя те, что были извлечены из класса.

Имейте в виду, мне нужно было проверить ошибки на случай, если брошюровщик не может произвести оценку с настройками по умолчанию — вам может понадобиться итеративно уменьшить порог достоверности, используя setPanoConfidenceThresh(...) прежде чем вы получите результат.

cv::Stitcher stitcher = cv::Stitcher::createDefault(true);
std::vector<cv::detail::CameraParams> cams;
bool have_transform = false;

for( int i = 0; i < num_frames; i++ ) {
currentFrames.push_back(f1.frame( ));
currentFrames.push_back(f2.frame( ));

if( ! have_transform ) {
status = stitcher.estimateTransform( currentFrames );
have_transform = true;
cams = stitcher.cameras();

// some code to check the status of the stitch and handle errors...
}

stitcher.setCameras( cams );
status = stitcher.composePanorama(currentFrames, output_frame );

// ... Doing stuff with the panorama
}

Помните, что это очень большой взлом кода OpenCV, из-за которого обновление до новой версии станет проблемой. К сожалению, у меня не хватило времени, так что мерзкий хак — это все, что я мог обойти!

5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]