stitching_detail算法介绍

本文详细介绍了OpenCV中的stitching_detail算法,包括程序运行流程、接口介绍、代码分析等。从特征点检测、匹配、运动估计、光束平均法、波形校正到图像融合等步骤,深入探讨了图像拼接的各个环节,并提供了参数使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

已经不负责图像拼接相关工作,有技术问题请自己解决,谢谢。

一、stitching_detail程序运行流程

      1.命令行调用程序,输入源图像以及程序的参数

      2.特征点检测,判断是使用surf还是orb,默认是surf。

      3.对图像的特征点进行匹配,使用最近邻和次近邻方法,将两个最优的匹配的置信度保存下来。

      4.对图像进行排序以及将置信度高的图像保存到同一个集合中,删除置信度比较低的图像间的匹配,得到能正确匹配的图像序列。这样将置信度高于门限的所有匹配合并到一个集合中。

     5.对所有图像进行相机参数粗略估计,然后求出旋转矩阵

     6.使用光束平均法进一步精准的估计出旋转矩阵。

     7.波形校正,水平或者垂直

     8.拼接

     9.融合,多频段融合,光照补偿,


二、stitching_detail程序接口介绍

    img1 img2 img3 输入图像

     --preview  以预览模式运行程序,比正常模式要快,但输出图像分辨率低,拼接的分辨率compose_megapix 设置为0.6

     --try_gpu  (yes|no)  是否使用GPU(图形处理器),默认为no

/* 运动估计参数 */

    --work_megapix <--work_megapix <float>> 图像匹配的分辨率大小,图像的面积尺寸变为work_megapix*100000,默认为0.6

    --features (surf|orb) 选择surf或者orb算法进行特征点计算,默认为surf

    --match_conf <float> 特征点检测置信等级,最近邻匹配距离与次近邻匹配距离的比值,surf默认为0.65,orb默认为0.3

    --conf_thresh <float> 两幅图来自同一全景图的置信度,默认为1.0

    --ba (reproj|ray) 光束平均法的误差函数选择,默认是ray方法

    --ba_refine_mask (mask)  ---------------

    --wave_correct (no|horiz|vert) 波形校验 水平,垂直或者没有 默认是horiz

     --save_graph <file_name> 将匹配的图形以点的形式保存到文件中, Nm代表匹配的数量,NI代表正确匹配的数量,C表示置信度

/*图像融合参数:*/

    --warp (plane|cylindrical|spherical|fisheye|stereographic|compressedPlaneA2B1|compressedPlaneA1.5B1|compressedPlanePortraitA2B1

|compressedPlanePortraitA1.5B1|paniniA2B1|paniniA1.5B1|paniniPortraitA2B1|paniniPortraitA1.5B1|mercator|transverseMercator)

    选择融合的平面,默认是球形

    --seam_megapix <float> 拼接缝像素的大小 默认是0.1 ------------

    --seam (no|voronoi|gc_color|gc_colorgrad) 拼接缝隙估计方法 默认是gc_color

    --compose_megapix <float> 拼接分辨率,默认为-1

    --expos_comp (no|gain|gain_blocks) 光照补偿方法,默认是gain_blocks

    --blend (no|feather|multiband) 融合方法,默认是多频段融合

    --blend_strength <float> 融合强度,0-100.默认是5.

   --output <result_img> 输出图像的文件名,默认是result,jpg

    命令使用实例,以及程序运行时的提示:


三、程序代码分析

    1.参数读入

     程序参数读入分析,将程序运行是输入的参数以及需要拼接的图像读入内存,检查图像是否多于2张。

    int retval = parseCmdArgs(argc, argv);
    if (retval)
        return retval;

    // Check if have enough images
    int num_images = static_cast<int>(img_names.size());
    if (num_images < 2)
    {
        LOGLN("Need more images");
        return -1;
    }

      2.特征点检测

      判断选择是surf还是orb特征点检测(默认是surf)以及对图像进行预处理(尺寸缩放),然后计算每幅图形的特征点,以及特征点描述子

      2.1 计算work_scale,将图像resize到面积在work_megapix*10^6以下,(work_megapix 默认是0.6)

work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));
resize(full_img, img, Size(), work_scale, work_scale);
      图像大小是740*830,面积大于6*10^5,所以计算出work_scale = 0.98,然后对图像resize。 

     

     2.2 计算seam_scale,也是根据图像的面积小于seam_megapix*10^6,(seam_megapix 默认是0.1),seam_work_aspect目前还没用到

   seam_scale = min(1.0, sqrt(seam_megapix * 1e6 / full_img.size().area()));
   seam_work_aspect = seam_scale / work_scale; //seam_megapix = 0.1 seam_work_aspect = 0.69
     
    2.3 计算图像特征点,以及计算特征点描述子,并将img_idx设置为i。

  (*finder)(img, features[i]);//matcher.cpp 348
  features[i].img_idx = i;
    特征点描述的结构体定义如下:

	struct detail::ImageFeatures
	Structure containing image keypoints and descriptors.
	struct CV_EXPORTS ImageFeatures
	{
		int img_idx;// 
		Size img_size;
		std::vector<KeyPoint> keypoints;
		Mat descriptors;
	};

    
     2.4 将源图像resize到seam_megapix*10^6,并存入image[]中

        resize(full_img, img, Size(), seam_scale, seam_scale);
        images[i] = img.clone();
    3.图像匹配

       对任意两副图形进行特征点匹配,然后使用查并集法,将图片的匹配关系找出,并删除那些不属于同一全景图的图片。

    3.1 使用最近邻和次近邻匹配,对任意两幅图进行特征点匹配。

    vector<MatchesInfo> pairwise_matches;//Structure containing information about matches between two images. 
    BestOf2NearestMatcher matcher(try_gpu, match_conf);//最近邻和次近邻法
    matcher(features, pairwise_matches);//对每两个图片进行matcher,20-》400 matchers.cpp 502
    介绍一下BestOf2NearestMatcher 函数:

      //Features matcher which finds two best matches for each feature and leaves the best one only if the ratio between descriptor distances is greater than the threshold match_conf.
     detail::BestOf2NearestMatcher::BestOf2NearestMatcher(bool try_use_gpu=false,float match_conf=0.3f,
	                                                     intnum_matches_thresh1=6, int num_matches_thresh2=6)
     Parameters:	try_use_gpu – Should try to use GPU or not
			match_conf – Match distances ration threshold
			num_matches_thresh1 – Minimum number of matches required for the 2D projective
			transform estimation used in the inliers classification step
			num_matches_thresh2 – Minimum number of matches required for the 2D projective
			transform re-estimation on inliers
     函数的定义(只是设置一下参数,属于构造函数):

BestOf2NearestMatcher::BestOf2NearestMatcher(bool try_use_gpu, float match_conf, int num_matches_thresh1, int num_matches_thresh2)
{
#ifdef HAVE_OPENCV_GPU
    if (try_use_gpu && getCudaEnabledDeviceCount() > 0)
        impl_ = new GpuMatcher(match_conf);
    else
#else
    (void)try_use_gpu;
#endif
        impl_ = new CpuMatcher(match_conf);

    is_thread_safe_ = impl_->isThreadSafe();
    num_matches_thresh1_ = num_matches_thresh1;
    num_matches_thresh2_ = num_matches_thresh2;
}

     以及MatchesInfo的结构体定义:

Structure containing information about matches between two images. It’s assumed that there is a homography between those images.
	struct CV_EXPORTS MatchesInfo
	{
		MatchesInfo();
		MatchesInfo(const MatchesInfo &other);
		const MatchesInfo& operator =(const MatchesInfo &other);
		int src_img_idx, dst_img_idx; // Images indices (optional)
		std::vector<DMatch> matches;
		std::vector<uchar> inliers_mask; // Geometrically consistent matches mask
		int num_inliers; // Number of geometrically consistent matches
		Mat H; // Estimated homography
		double confidence; // Confidence two images are from the same panorama
	};
      求出图像匹配的结果如下(具体匹配参见sift特征点匹配),任意两幅图都进行匹配(3*3=9),其中1-》2和2-》1只计算了一次,以1-》2为准,:

     

       3.2 根据任意两幅图匹配的置信度,将所有置信度高于conf_thresh(默认是1.0)的图像合并到一个全集中。

       我们通过函数的参数 save_graph打印匹配结果如下(我稍微修改了一下输出):

"outimage101.jpg" -- "outimage102.jpg"[label="Nm=866, Ni=637, C=2.37864"];
"outimage101.jpg" -- "outimage103.jpg"[label="Nm=165, Ni=59, C=1.02609"];
"outimage102.jpg" -- "outimage103.jpg"[label="Nm=460, Ni=260, C=1.78082"];
      Nm代表匹配的数量,NI代表正确匹配的数量,C表示置信度

      通过查并集方法,查并集介绍请参见博文:

      http://blog.youkuaiyun.com/skeeee/article/details/20471949

    vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);//将置信度高于门限的所有匹配合并到一个集合中
    vector<Mat> img_subset;
    vector<string> img_names_subset;
    vector<Size> full_img_sizes_subset;
    for (size_t i = 0; i < indices.size(); ++i)
    {
        img_names_subset.push_back(img_names[indices[i]]);
        img_subset.push_back(images[indices[i]]);
        full_img_sizes_subset.push_back(full_img_sizes[indices[i]]);
    }

    images = img_subset;
    img_names = img_names_subset;
    full_img_sizes = full_img_sizes_subset;
       4.根据单应性矩阵粗略估计出相机参数(焦距)

        4.1 焦距参数的估计

        根据前面求出的任意两幅图的匹配,我们根据两幅图的单应性矩阵H,求出符合条件的f,(4副图,16个匹配,求出8个符合条件的f),然后求出f的均值或者中值当成所有图形的粗略估计的f。

estimateFocal(features, pairwise_matches, focals);
       函数的主要源码如下:

    for (int i = 0; i < num_images; ++i)
    {
        for (int j = 0; j < num_images; ++j)
        {
            const MatchesInfo &m = pairwise_matches[i*num_images + j];
            if 
<think>好的,我现在需要帮助用户了解OpenCVdetail_GraphCutSeamFinder的功能和用法。首先,我应该先确认这个类属于哪个模块。根据用户提供的引用[1],OpenCV从3.0开始将新模块放在opencv_contrib仓库里,而文档结构包括模块名下的doc、include等目录。所以可能需要检查是否detail_GraphCutSeamFinder属于opencv_contrib中的某个模块,比如stitching模块。 接下来,用户提到想了解功能和用法,我需要先解释这个类的作用。GraphCutSeamFinder应该是用于图像拼接中的接缝查找,基于图割算法来优化拼接区域的重叠部分,减少可见的接缝。可能需要参考OpenCVstitching模块文档,特别是接缝查找相关的部分。 然后,用户可能需要代码示例。根据引用[2],安装OpenCV时涉及编译步骤,而引用[3]提到了使用colcon构建,可能用户是在ROS环境下使用OpenCV。不过代码示例部分需要展示如何创建SeamFinder对象并应用。可能需要包含头文件,比如#include <opencv2/stitching/detail/seam_finders.hpp>,然后使用cv::detail::GraphCutSeamFinder。 另外,用户可能需要知道参数设置,比如cost_type,可能有两种类型:COLOR和COLOR_GRAD。需要解释这些参数的影响以及如何选择。 关于文档部分,引用[1]提到模块的doc目录下有文档页面和BibTeX文件,所以应该引导用户查看官方文档或opencv_contrib仓库中的对应文档。此外,用户可能需要通过编译文档来生成本地版本,或者在线查看。 还需要注意用户提供的引用中有安装步骤,可能需要确认用户是否已经正确安装了包含stitching模块的OpenCV,因为默认安装可能不包括opencv_contrib中的模块。如果用户遇到找不到该类的错误,可能需要检查安装时是否启用了OPENCV_EXTRA_MODULES_PATH,并正确编译了contrib模块。 最后,生成相关问题时要考虑用户可能的后续问题,比如参数调优、与其他接缝查找方法的比较、性能优化等。确保问题覆盖功能、使用、优化和实际应用等方面。</think>### OpenCV detail_GraphCutSeamFinder 功能与用法解析 #### 1. 功能说明 `detail_GraphCutSeamFinder` 是 OpenCV 图像拼接模块中的接缝查找算法实现类,用于在多张图像重叠区域寻找最优拼接边界,减少因光照差异或几何错位导致的接缝可见性。其核心基于图割算法(Graph Cut),通过最小化能量函数实现像素级优化[^1]。 #### 2. 使用方法 ##### 头文件与命名空间 ```cpp #include <opencv2/stitching/detail/seam_finders.hpp> using namespace cv::detail; ``` ##### 基础代码示例 ```cpp // 创建图割接缝查找器 Ptr<GraphCutSeamFinder> seam_finder = GraphCutSeamFinder::create(); // 输入:图像列表、掩码、关键点等预处理数据 std::vector<Mat> images; std::vector<Mat> masks; std::vector<Size> sizes; std::vector<Point> corners; // 执行接缝查找 seam_finder->find(images, corners, masks); ``` ##### 参数配置 支持两种能量计算模式: - `GraphCutSeamFinder::COST_COLOR`:基于颜色差异(默认) - `GraphCutSeamFinder::COST_COLOR_GRAD`:结合颜色和梯度差异 ```cpp seam_finder->setCostFunction(GraphCutSeamFinder::COST_COLOR_GRAD); ``` #### 3. 文档位置 - 官方文档路径:`<opencv_contrib>/modules/stitching/doc/seam_finders.md` - 代码定义位置:`<opencv_contrib>/modules/stitching/include/opencv2/stitching/detail/seam_finders.hpp` #### 4. 编译注意事项 使用前需确保已正确编译包含 `opencv_contrib` 的 OpenCV 版本: ```bash cmake -DOPENCV_EXTRA_MODULES_PATH=<path-to-opencv_contrib/modules> .. make -j8 sudo make install ``` 参考完整安装步骤见引用[2][^2]。
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值