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

     




  • 相关阅读:
    Android中设置APP应用字体不缩放,文字不随系统字体大小变化
    day02 作业
    day01
    2018.11.2
    2018.11.1
    2018.10.25
    2018.10.24
    2018.10.23
    2018.10.20
    2018.10.19学习总结
  • 原文地址:https://www.cnblogs.com/jsxyhelu/p/6810964.html
Copyright © 2020-2023  润新知