• Stitching模块中leaveBiggestComponent初步研究


    在Stitching模块中以及原始论文《Automatic Panoramic Image Stitching using Invariant Features》3.2中,都有“根据已经匹配好的特征对,判断哪些图片是属于序列,那些图片是不属于序列”的这一步操作。
    论文解释为:
     


    对应的函数为:
    std : :vector < int > leaveBiggestComponent(std : :vector <ImageFeatures >  &features,  std : :vector <MatchesInfo >  &pairwise_matches, float conf_threshold)
    {
         const  int num_images  =  static_cast < int >(features.size());
        DisjointSets comps(num_images);
         for ( int i  =  0; i  < num_images;  ++i)
        {
             for ( int j  =  0; j  < num_images;  ++j)
            {
                 if (pairwise_matches[i *num_images  + j].confidence  < conf_threshold)
                     continue;
                 int comp1  = comps.findSetByElem(i);
                 int comp2  = comps.findSetByElem(j);
                 if (comp1  != comp2)
                    comps.mergeSets(comp1, comp2);
            }
        }
         int max_comp  =  static_cast < int >(std : :max_element(comps.size.begin(),comps.size.end())  - comps.size.begin());
        std : :vector < int > indices;
        std : :vector < int > indices_removed;
         for ( int i  =  0; i  < num_images;  ++i)
             if (comps.findSetByElem(i)  == max_comp)
                indices.push_back(i);
             else
                indices_removed.push_back(i);
        std : :vector <ImageFeatures > features_subset;
        std : :vector <MatchesInfo > pairwise_matches_subset;
         for (size_t i  =  0; i  < indices.size();  ++i)
        {
            features_subset.push_back(features[indices[i]]);
             for (size_t j  =  0; j  < indices.size();  ++j)
            {
                pairwise_matches_subset.push_back(pairwise_matches[indices[i] *num_images  + indices[j]]);
                pairwise_matches_subset.back().src_img_idx  =  static_cast < int >(i);
                pairwise_matches_subset.back().dst_img_idx  =  static_cast < int >(j);
            }
        }
         if ( static_cast < int >(features_subset.size())  == num_images)
             return indices;
        LOG( "Removed some images, because can't match them or there are too similar images: (");
        LOG(indices_removed[ 0+  1);
         for (size_t i  =  1; i  < indices_removed.size();  ++i)
            LOG( ", "  << indices_removed[i] + 1);
        LOGLN( ").");
        LOGLN( "Try to decrease the match confidence threshold and/or check if you're stitching duplicates.");
        features  = features_subset;
        pairwise_matches  = pairwise_matches_subset;
         return indices;
    }
    leaveBiggestComponent的主要目的可以描述为“寻找所有配对中肯定属于一幅全景图像的图片”,主要通过的方法是“并查集”
    那什么是“并查集”了? 举个简单应用的例子。现在社交网站这么流行,假设现在想知道两个人之间是否存在间接好友关系(A和B为好友,B和C为好友,A和C为间接好友),有什么好方法呢?并查集就是用于这类查询问题的有效 数据结构 ,正如其名(disjoint set),并查集本质上是一个集合,集合的元素为树,因此并查集实际上表示了一个森林(disjoint-set forests)。它的特点是每棵树中的成员都可由根结点所代表,这样要知道两个结点是否属于集合的同一元素,只要看它们是否有同一“代表”。
    为此,搜集资料,编写代码
    # include  "stdafx.h"
    # include  "opencv2/opencv_modules.hpp"
    # include  <opencv2 /core /utility.hpp >
    # include  "opencv2/imgcodecs.hpp"
    # include  "opencv2/highgui.hpp"
    # include  "opencv2/stitching/detail/autocalib.hpp"
    # include  "opencv2/stitching/detail/blenders.hpp"
    # include  "opencv2/stitching/detail/timelapsers.hpp"
    # include  "opencv2/stitching/detail/camera.hpp"
    # include  "opencv2/stitching/detail/exposure_compensate.hpp"
    # include  "opencv2/stitching/detail/matchers.hpp"
    # include  "opencv2/stitching/detail/motion_estimators.hpp"
    # include  "opencv2/stitching/detail/seam_finders.hpp"
    # include  "opencv2/stitching/detail/warpers.hpp"
    # include  "opencv2/stitching/warpers.hpp"
    # define  conf_threshold  90  
    # define  num_images  10  
    using  namespace std;
    using  namespace cv;
    using  namespace cv : :detail;
    void main()  
    {  
         int max_comp  =  0;  
         int max_size  =  0;  
        vector < int > confident(num_images *num_images);  
        DisjointSets comps(num_images);  
         //使用随机数模拟多幅图像中每个图像相互匹配的置信度(0-100)  
         //另外1与2的匹配置信度和2与1的置信度我们默认相同(实际中是不相同的)  
        srand(( unsigned)time(NULL));  
         for ( int i   =  0;i <num_images;i ++)  
        {  
            cout <<endl;  
             for ( int j  =  0;j <num_images;j ++)  
            {  
                 if ( !confident[i *num_images +j])  
                {  
                    confident[i *num_images +j]  = rand() % 100;  
                    confident[j *num_images +i]  = confident[i *num_images +j];  
                }  
                 if (i  == j)  
                {  
                    confident[i *num_images +j]  =  100;  
                }  
                cout << "   " <<confident[i *num_images +j];  
            }  
        }  
         //根据两幅图匹配置信度是否大于conf_threshold来决定是否属于一个全景集合  
         for ( int i  =  0; i  < num_images;  ++i)  
        {  
             for ( int j  =  0; j  < num_images;  ++j)  
            {  
                 if (confident[i *num_images  + j]  < conf_threshold)  
                     continue;  
                 int comp1  = comps.findSetByElem(i);  
                 int comp2  = comps.findSetByElem(j);  
                 if (comp1  != comp2)  
                    comps.mergeSets(comp1, comp2);  
            }  
        }  
         //找出包含图片最多的全景集合  
         for ( int i  =  0;i < num_images;i ++)  
        {  
             if (i  ==  0)  
            {  
                max_comp  =  0;  
                max_size  = comps.size[i];  
            }  
             else  if(comps.size[i] >max_size)  
            {  
                max_comp  = i;  
                max_size  = comps.size[i];  
            }  
        }  
         //将该集合中的元素打印出来  
        cout <<endl << "images in the max_comp:" <<endl;  
         int j  =  0;  
         for ( int i  =  0;i <num_images;i ++)  
        {  
             if (comps.findSetByElem(i)  == max_comp)  
            {  
                cout << ++j << ":  " << i <<endl;  
            }  
        }  
         while( 1);  
    }  
    其中相关函数解释:
     comps.mergeSets(comp1, comp2); 
    是将comp1和comp2合并起来。
    最后得到的,就是在目前情况下,最大可能的符合条件的序列组合。
    解析:
    这里的理解可能有一些困难,关键是要把握在运算前有什么,运算后有什么?
    在运算前,我们得到的是一个矩阵,那就是N*N的图片序列中,每一个图片和其他N-1个图片之间的特征匹配关系,也包括确信值
    运算之后,需要获得的是在这些所有的关系中,所有对都符合条件的,但是相互之间不想交的对的集合。并且把最大的那个打印出来。

     




  • 相关阅读:
    liunx基本命令
    liunx—awk
    python—__name__
    python—url路径拼接/编码
    python—__init__作用
    单元测试
    2、选择排序
    1、算法简介
    在命令行输入python出现“Warning:This Python interpreter is in a conda environment, but the environment has not been activated. Libraries may fail to load. To activate this environment please see https://conda.
    如何明确区分代码中的1和l
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/16948019.html
Copyright © 2020-2023  润新知