OpenCV  4.10.0
开源计算机视觉
正在加载...
正在搜索...
无匹配项
高级拼接 API(Stitcher 类)

上一教程: 高动态范围成像
下一教程: 如何使用背景减除方法

原作者Jiri Horner
兼容性OpenCV >= 3.2

目标

在本教程中,您将学习如何

  • 使用由
  • 提供的用于拼接的高级拼接 API。

学习如何使用预配置的 Stitcher 配置来拼接使用不同相机模型的图像。

代码

本教程代码如下所示。您也可以从 这里 下载。
#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 << "无法拼接图像,错误代码 = " << int(status) << endl;
}
return EXIT_FAILURE;
imwrite(result_name, pano);
cout << "拼接完成成功\n" << result_name << " 已保存!";
}
return EXIT_SUCCESS;
{
void printUsage(char** argv)
cout <<
"图像拼接器。\n\n" << "用法:\n" << argv[0] <<" [标志] img1 img2 [...imgN]\n\n"
"标志:\n"
" --d3\n"
" 内部创建每个图像的三个块以提高拼接成功率\n"
" --mode (panorama|scans)\n"
" 确定拼接器的配置。默认值为 'panorama',\n"
" 适合创建照片全景图的模式。选项 'scans' 适合\n"
" 拼接仿射变换下的材料,例如扫描件。\n"
" --output <result_img>\n"
" 默认值为 'result.jpg'。\n\n"
}
"示例用法:\n" << argv[0] << " --d3 --mode scans img1.jpg img2.jpg\n";
{
int parseCmdArgs(int argc, char** argv)
{
if (argc == 1)
cout << "无法拼接图像,错误代码 = " << int(status) << endl;
}
printUsage(argv);
{
for (int i = 1; i < argc; ++i)
{
if (argc == 1)
cout << "无法拼接图像,错误代码 = " << int(status) << endl;
}
if (string(argv[i]) == "--help" || string(argv[i]) == "/?")
{
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 << "无法拼接图像,错误代码 = " << int(status) << endl;
}
result_name = argv[i + 1];
}
mode = Stitcher::SCANS;
{
cout << "错误的 --mode 标志值\n";
Mat img = imread(samples::findFile(argv[i]));
{
if (img.empty())
cout << "无法拼接图像,错误代码 = " << int(status) << endl;
}
cout << "无法读取图像 '" << argv[i] << "'\n";
{
if (divide_images)
Rect rect(0, 0, img.cols / 2, img.rows);
imgs.push_back(img(rect).clone());
Rect rect(0, 0, img.cols / 2, img.rows);
rect.x = img.cols / 3;
Rect rect(0, 0, img.cols / 2, img.rows);
}
mode = Stitcher::SCANS;
rect.x = img.cols / 2;
}
}
cout << "拼接完成成功\n" << result_name << " 已保存!";
}
cv::Mat
n 维密集数组类
cv::Mat::cols
int cols
cv::Mat::empty
bool empty() const
cv::Stitcher::Mode
Mode
cv::Stitcher::Status
Status
cv::Ptr
std::shared_ptr< _Tp > Ptr
cv::imread
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR)
main
int main(int argc, char *argv[])
cv
"黑盒" 表示与磁盘上文件关联的文件存储。

stitching.hpp

解释

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 << "无法拼接图像,错误代码 = " << int(status) << endl;
}

最重要的代码部分是

创建一个新的拼接器实例,并且 cv::Stitcher::stitch 将完成所有繁重的工作。

cv::Stitcher::create 可以以预定义的配置之一创建拼接器(参数 mode)。有关详细信息,请参阅 cv::Stitcher::Mode。这些配置将设置多个拼接器属性以在预定义的场景之一中运行。在您以预定义的配置之一创建拼接器后,您可以通过设置任何拼接器属性来调整拼接。

如果您有 cuda 设备,cv::Stitcher 可以配置为将某些操作卸载到 GPU。如果您更喜欢这种配置,请将 try_use_gpu 设置为 true。无论此标志如何,OpenCL 加速将根据全局 OpenCV 设置透明地使用。

拼接可能会由于多种原因失败,您应始终检查一切是否正常,并将结果全景图存储在 pano 中。有关可能的错误代码,请参阅 cv::Stitcher::Status 文档。

相机模型

仿射模型 预计仿射变换具有 6 个自由度或 4 个自由度,在 cv::detail::AffineBestOf2NearestMatcher cv::detail::AffineBasedEstimator cv::detail::BundleAdjusterAffine cv::detail::BundleAdjusterAffinePartial cv::AffineWarper 中实现。

单应性模型适用于创建由相机拍摄的照片全景图,而基于仿射的模型可用于拼接由专业设备拍摄的扫描件和物体。
注意

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 命令行不支持 * 扩展。

拼接详解(python opencv >4.0.1)

如果您想研究拼接管道的内部机制,或者想尝试详细配置,您可以使用 stitching_detailed 源代码(可在 C++ 或 python 中获得)

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 multiband –expos_comp no –seam gc_colorgrad

使用单应性匹配成对图像 -matcher homography,用于变换估计的估计器也是单应性 -estimator homography。

特征匹配步骤的置信度为 0.3:-match_conf 0.3。如果匹配图像遇到困难,可以降低此值。

来自同一全景的两个图像的阈值为 0.3:-conf_thresh 0.3。如果匹配图像遇到困难,可以降低此值。

束调整成本函数为射线 -ba ray。

束调整的细化掩码为 xxxxx(-ba_refine_mask xxxxx),其中“x”表示细化相应参数,“_”表示不细化。细化一个,并具有以下格式:fx,skew,ppx,aspect,ppy。

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

执行波浪效果校正是否(-wave_correct no)。

扭曲表面类型为鱼眼(-warp fisheye)。

混合方法为多波段(-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 compressedPlaneA2B1 –blend multiband –expos_comp channels_blocks –seam gc_colorgrad

您将获得

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

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

您可以在 https://github.com/opencv/opencv_extra/tree/4.x/testdata/stitching 中找到所有图像。