上一个教程: 高动态范围成像

下一个教程: 如何使用背景减除法

Original author Jiri Horner
Compatibility OpenCV >= 3.2

目标

在本教程中,你将学习如何:

  • 使用cv::Stitcher提供的高级缝合API进行缝合。
  • 学习如何使用预先配置的Stitcher配置来缝合使用不同相机型号的图像。

代码

本教程的代码如下所示。你也可以从这里下载它。

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/stitching.hpp"
#include <iostream>
using namespace std;
using namespace cv;
bool divide_images = false;
Stitcher::Mode mode = Stitcher::PANORAMA;
vector<Mat> imgs;
string result_name = "result.jpg";
void printUsage(char** argv);
int parseCmdArgs(int argc, char** argv);
int main(int argc, char* argv[])
{
    int retval = parseCmdArgs(argc, argv);
    if (retval) return EXIT_FAILURE;
    Mat pano;
    Ptr<Stitcher> stitcher = Stitcher::create(mode);
    Stitcher::Status status = stitcher->stitch(imgs, pano);
    if (status != Stitcher::OK)
    {
        cout << "Can't stitch images, error code = " << int(status) << endl;
        return EXIT_FAILURE;
    }
    imwrite(result_name, pano);
    cout << "stitching completed successfully\n" << result_name << " saved!";
    return EXIT_SUCCESS;
}
void printUsage(char** argv)
{
    cout <<
         "Images stitcher.\n\n" << "Usage :\n" << argv[0] <<" [Flags] img1 img2 [...imgN]\n\n"
         "Flags:\n"
         "  --d3\n"
         "      internally creates three chunks of each image to increase stitching success\n"
         "  --mode (panorama|scans)\n"
         "      Determines configuration of stitcher. The default is 'panorama',\n"
         "      mode suitable for creating photo panoramas. Option 'scans' is suitable\n"
         "      for stitching materials under affine transformation, such as scans.\n"
         "  --output <result_img>\n"
         "      The default is 'result.jpg'.\n\n"
         "Example usage :\n" << argv[0] << " --d3 --mode scans img1.jpg img2.jpg\n";
}
int parseCmdArgs(int argc, char** argv)
{
    if (argc == 1)
    {
        printUsage(argv);
        return EXIT_FAILURE;
    }
    for (int i = 1; i < argc; ++i)
    {
        if (string(argv[i]) == "--help" || string(argv[i]) == "/?")
        {
            printUsage(argv);
            return EXIT_FAILURE;
        }
        else if (string(argv[i]) == "--d3")
        {
            divide_images = true;
        }
        else if (string(argv[i]) == "--output")
        {
            result_name = argv[i + 1];
            i++;
        }
        else if (string(argv[i]) == "--mode")
        {
            if (string(argv[i + 1]) == "panorama")
                mode = Stitcher::PANORAMA;
            else if (string(argv[i + 1]) == "scans")
                mode = Stitcher::SCANS;
            else
            {
                cout << "Bad --mode flag value\n";
                return EXIT_FAILURE;
            }
            i++;
        }
        else
        {
            Mat img = imread(samples::findFile(argv[i]));
            if (img.empty())
            {
                cout << "Can't read image '" << argv[i] << "'\n";
                return EXIT_FAILURE;
            }
            if (divide_images)
            {
                Rect rect(0, 0, img.cols / 2, img.rows);
                imgs.push_back(img(rect).clone());
                rect.x = img.cols / 3;
                imgs.push_back(img(rect).clone());
                rect.x = img.cols / 2;
                imgs.push_back(img(rect).clone());
            }
            else
                imgs.push_back(img);
        }
    }
    return EXIT_SUCCESS;
}

解释

最重要的代码部分是:

    Mat pano;
    Ptr<Stitcher> stitcher = Stitcher::create(mode);
    Stitcher::Status status = stitcher->stitch(imgs, pano);
    if (status != Stitcher::OK)
    {
        cout << "Can't stitch images, error code = " << int(status) << endl;
        return EXIT_FAILURE;
    }

一个新的stitcher实例被创建,cv::Stitcher::stitch将做所有的艰苦工作。

cv::Stitcher::create可以在一个预定义的配置(参数mode)中创建stitcher。详见cv::Stitcher::Mode。这些配置将设置多个缝合器属性,以便在预定义的场景之一中操作。在你以预定义的配置之一创建缝合器后,你可以通过设置任何缝合器属性来调整缝合。

如果你有cuda设备,cv::Stitcher可以被配置为卸载某些操作到GPU。如果你喜欢这种配置,请将try_use_gpu设置为true。不管这个标志是什么,OpenCL加速将根据全局OpenCV设置透明地使用。

缝合可能会因为一些原因而失败,你应该经常检查是否一切顺利,并且产生的pano被保存在pano中。参见cv::Stitcher::Status文档,了解可能的错误代码。

摄像机模型

目前有两种相机模型在拼接管道中实现。

注意
cv::Stitcher的某些详细设置可能没有意义。特别是你不应该把实现仿生模型的类和实现同源模型的类混在一起,因为它们使用不同的变换。

试试吧

如果你启用了构建样本,你可以在build/bin/cpp-example-stitching下找到二进制。这个例子是一个控制台应用程序,运行它不需要参数就可以看到帮助。opencv_extra提供了一些测试所有可用配置的样本数据。

尝试全景模式,请运行:

./cpp-example-stitching --mode panorama <path to opencv_extra>/testdata/stitching/boat*

在这里插入图片描述
以尝试扫描模式运行(来自家庭级扫描仪的数据集):

./cpp-example-stitching --mode scans <path to opencv_extra>/testdata/stitching/newspaper*

在这里插入图片描述
或(来自专业书籍扫描仪的数据集):

./cpp-example-stitching --mode scans <path to opencv_extra>/testdata/stitching/budapest*

在这里插入图片描述

注意事项
上面的例子期望的是POSIX平台,在WINDOWS上,你必须明确提供所有的文件名(例如:boat1.jpg
boat2.jpg…),因为WINDOWS命令行不支持*扩展。

Stitching 细节(python opencv >4.0.1)

如果你想研究缝合管道的内部结构,或者你想尝试详细的配置,你可以使用c++或python中的stitching_detailed源代码。

stitching_detailed
stitching_detailed.cpp
stitching_detailed.py

stitching_detailed程序使用命令行来获取缝合参数。存在许多参数。上面的例子显示了一些可能的命令行参数:

boat5.jpg boat2.jpg boat3.jpg boat4.jpg boat1.jpg boat6.jpg -work_megapix 0.6 -features orb -matcher homography -estimator homography -match_conf 0.3 -conf_thresh 0.3 -ba ray -ba_refine_mask xxxxx -save_graph test.txt -wave_correct no -warp fisheye -blend multi band -expos_comp no -seam gc_colorgrad

在这里插入图片描述

成对的图像使用同构图进行匹配 -matcher同构图和估计器也用于变换估计 -estimator同构图

特征匹配步骤的置信度为0.3: -match_conf 0.3。如果你在匹配图像时有一些困难,你可以减少这个值。

两幅图像来自同一全景图的阈值置信度为0: -conf_thresh 0.3 如果你在匹配图像时有一些困难,可以减少这个值

捆绑调整的成本函数是射线-ba射线

捆绑调整的细化掩码是XXXX(-ba_refine_mask xxxxx),其中’x’表示细化各自的参数,'_'表示不细化。细化一个,其格式如下:fx,skew,px,aspect,py

将用DOT语言表示的匹配图保存到test.txt(-save_graph test.txt): 标签描述: Nm是匹配的数量,Ni是离群的数量,C是置信度

在这里插入图片描述

执行波浪效应修正是no(-wave_correct no)。

经面类型为fisheye(-warp fisheye)。

混合方法是multiband(-blend multiband)。

曝光补偿方法不使用 (-expos_comp no)

接缝估计器是最小图样切割的接缝(-seam gc_colorgrad)

你也可以在命令行中使用这些参数:

boat5.jpg boat2.jpg boat3.jpg boat4.jpg boat1.jpg boat6.jpg -work_megapix 0.6 -features orb -matcher homography -estimator homography -match_conf 0.3 -conf_thresh 0.3 -ba ray -ba_refine_mask xxxxx -wave_correct horiz -warp compressionPlaneA2B1 -blend multiband -expos_comp channels_blocks -seam gc_colorgrad

你会得到:

compressedPlaneA2B1.jpg

对于使用扫描仪或无人机拍摄的图像(仿生运动),你可以在命令行中使用这些参数:

newspaper1.jpg newspaper2.jpg -work_megapix 0.6 -features surf -matcher affine -estimator affine -match_conf 0.3 -conf_thresh 0.3 -ba affine -ba_refine_mask xxxxx -wave_correct no -warp affine

affinepano.jpg

你可以在https://github.com/opencv/opencv_extra/tree/4.x/testdata/stitching 找到所有的图片

Logo

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。

更多推荐