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个图片之间的特征匹配关系,也包括确信值
运算之后,需要获得的是在这些所有的关系中,所有对都符合条件的,但是相互之间不想交的对的集合。并且把最大的那个打印出来。

 




posted on 2022-12-03 15:31  jsxyhelu  阅读(63)  评论(0编辑  收藏  举报

导航