【问题标题】:OpenCV Stitcher Class with Overlapping Stationary Cameras具有重叠固定相机的 OpenCV Stitcher 类
【发布时间】:2013-04-23 10:37:30
【问题描述】:

我正在尝试使用 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
}

遗憾的是,似乎有一个错误 (documented here) 导致两个视图以一种非常奇怪的方式分开,如下图所示:

第 1 帧:

第 2 帧:

...

第 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; 

结果:

有人知道我该如何解决这个问题吗?基本上我需要计算出转换一次,然后在剩余的帧上使用它(我们说的是 30 分钟的视频)。

理想情况下,我正在寻找一些关于修补缝合器类的建议,但我愿意尝试手动编写不同的解决方案。与缝合器类相比,早期的尝试涉及查找 SURF 点、关联它们和查找单应性,结果相当差,所以如果可能的话,我宁愿使用它。

【问题讨论】:

    标签: c++ opencv image-stitching


    【解决方案1】:

    所以最后,我使用了stitcher.cpp 代码并得到了一些接近解决方案的东西(但并不完美,因为缝合接缝仍然会移动很多,因此您的里程可能会有所不同)。

    更改为stitcher.hpp

    在第 136 行添加了一个新函数 setCameras()

    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 代码的破解,这将使更新到新版本变得很痛苦。不幸的是,我的时间不多了,所以我只能做一个讨厌的黑客攻击!

    【讨论】:

    • 你知道这在新版本的openCV中是否仍然存在问题吗?您还有共享结果的存储库吗?
    • 我不知道我害怕 - 自从这篇文章以来我不需要使用它。也担心这对存储库来说是一个不,我正在从事一个非公共资助的项目,所以代码被保留在内部。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多