zoukankan      html  css  js  c++  java
  • 【数据结构】【计算机视觉】并查集(disjoint set)结构介绍

    1.简述 

           在实现多图像无序输入的拼接中,我们先使用surf算法对任意两幅图像进行特征点匹配,每对图像的匹配都有一个置信度confidence参数,来衡量两幅图匹配的可信度,当confidence>conf_threshold,我们就认为这两幅图可以拼接,属于一个全景拼接的集合,然后扩展这个集合就可以确定最大的可拼接集合,排除一些无效的图像,然后进行后续的拼接。

          并查集的定义就是并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。即将属于相同集合的元素合并起来,中间需要查找某个元素属于哪个集合,然后需要将两个元素或者集合进行合并处理。

       2.结构体及函数定义

         下面我们介绍opencv_stitching中使用的互斥集结构和函数的定义

    [cpp] view plain copy
    1. class  DisjointSets  
    2. {  
    3. public:  
    4.     //互斥集初始化,元素个数是elem_count  
    5.     DisjointSets(int elem_count = 0) { createOneElemSets(elem_count); }  
    6.   
    7.       
    8.     void createOneElemSets(int elem_count);//创建互斥集    
    9.     int findSetByElem(int elem);//查找元素所属的集合  
    10.     int mergeSets(int set1, int set2);//合并两个集合  
    11.   
    12.       
    13.     std::vector<int> parent;//元素所属集合 parent[elem] = set ,元素elem的集合是set  
    14.     std::vector<int> size;//集合的包含的元素个数 size[set] = set_size,集合set的元素数是set_size  
    15.   
    16. private:  
    17.     std::vector<int> rank_;//rank_[set] = rank,集合set标记  
    18. };  

    [cpp] view plain copy
    1. /************************************************************************/  
    2. /* 
    3.   创建一个互斥集,尺寸为n 
    4.   %参数 int n,输入互斥集的尺寸 
    5. */  
    6. /************************************************************************/  
    7. void DisjointSets::createOneElemSets(int n)  
    8. {  
    9.     rank_.assign(n, 0);//设置rank_长度为n,初始值为0  
    10.     size.assign(n, 1);//设置size长度为n,初始值为1  
    11.     parent.resize(n);//设置parent的长度为n  
    12.     for (int i = 0; i < n; ++i)  
    13.         parent[i] = i;//parent[elem] = set,初始化每个元素所在的集合  
    14. }  
    15.   
    16. /************************************************************************/  
    17. /*  
    18.    查找元素所在的集合 
    19.    %参数int elem  输入元素 
    20. */  
    21. /************************************************************************/  
    22. int DisjointSets::findSetByElem(int elem)  
    23. {  
    24.     //由于互斥集也是树形结构,所以需要向上递归到根节点,即元素所属的最终集合  
    25.     int set = elem;  
    26.     while (set != parent[set])//如果元素的值与所属集合的值不相同,说明元素是经过集合合并过的,所以要继续向上递归  
    27.         set = parent[set];  
    28.     int next;  
    29.     while (elem != parent[elem])//将之前所有的递归过的元素的集合全改成最终的根节点集合  
    30.     {  
    31.         next = parent[elem];  
    32.         parent[elem] = set;  
    33.         elem = next;  
    34.     }  
    35.     return set;  
    36. }  
    37.   
    38. /************************************************************************/  
    39. /*  
    40.     合并两个集合 
    41.     %参数int set1,int set2 两个集合set1和set2 
    42. */  
    43. /************************************************************************/  
    44. int DisjointSets::mergeSets(int set1, int set2)  
    45. {  
    46.     //比较两个集合的rank_,将rank_值小的集合合并到值大的集合中  
    47.     if (rank_[set1] < rank_[set2])  
    48.     {  
    49.         parent[set1] = set2;  
    50.         size[set2] += size[set1];  
    51.         return set2;  
    52.     }  
    53.     if (rank_[set2] < rank_[set1])  
    54.     {  
    55.         parent[set2] = set1;  
    56.         size[set1] += size[set2];  
    57.         return set1;  
    58.     }  
    59.     //如果rank_相等,则默认将set1合并到set2中,set2的rank_值+1  
    60.     parent[set1] = set2;  
    61.     rank_[set2]++;  
    62.     size[set2] += size[set1];  
    63.     return set2;  
    64. }  
      模拟程序:

    [cpp] view plain copy
    1. #include "astdio.h"  
    2. #include "disjointset.h"  
    3.   
    4. #define  conf_threshold 90  
    5. #define  num_images 10  
    6.   
    7.   
    8. void main()  
    9. {  
    10.     int max_comp = 0;  
    11.     int max_size = 0;  
    12.     vector<int> confident(num_images*num_images);  
    13.     DisjointSets comps(num_images);  
    14.     //使用随机数模拟多幅图像中每个图像相互匹配的置信度(0-100)  
    15.     //另外1与2的匹配置信度和2与1的置信度我们默认相同(实际中是不相同的)  
    16.     srand((unsigned)time(NULL));  
    17.     for (int i  = 0;i<num_images;i++)  
    18.     {  
    19.         cout<<endl;  
    20.         for (int j = 0;j<num_images;j++)  
    21.         {  
    22.             if (!confident[i*num_images+j])  
    23.             {  
    24.                 confident[i*num_images+j] = rand()%100;  
    25.                 confident[j*num_images+i] = confident[i*num_images+j];  
    26.             }  
    27.               
    28.             if (i == j)  
    29.             {  
    30.                 confident[i*num_images+j] = 100;  
    31.             }  
    32.             cout<<"   "<<confident[i*num_images+j];  
    33.         }  
    34.     }  
    35.     //根据两幅图匹配置信度是否大于conf_threshold来决定是否属于一个全景集合  
    36.     for (int i = 0; i < num_images; ++i)  
    37.     {  
    38.         for (int j = 0; j < num_images; ++j)  
    39.         {  
    40.               
    41.             if (confident[i*num_images + j] < conf_threshold)  
    42.                 continue;  
    43.             int comp1 = comps.findSetByElem(i);  
    44.             int comp2 = comps.findSetByElem(j);  
    45.             if (comp1 != comp2)  
    46.                 comps.mergeSets(comp1, comp2);  
    47.         }  
    48.     }  
    49.     //找出包含图片最多的全景集合  
    50.     for (int i = 0;i< num_images;i++)  
    51.     {  
    52.         if (i == 0)  
    53.         {  
    54.             max_comp = 0;  
    55.             max_size = comps.size[i];  
    56.         }  
    57.         else if(comps.size[i]>max_size)  
    58.         {  
    59.             max_comp = i;  
    60.             max_size = comps.size[i];  
    61.         }  
    62.     }  
    63.     //将该集合中的元素打印出来  
    64.     cout<<endl<<"images in the max_comp:"<<endl;  
    65.     int j = 0;  
    66.     for (int i = 0;i<num_images;i++)  
    67.     {  
    68.         if (comps.findSetByElem(i) == max_comp)  
    69.         {  
    70.             cout<<++j<<":  "<< i<<endl;  
    71.         }  
    72.     }  
    73.     while(1);  
    74.   
    75. }  

    输出结果:

  • 相关阅读:
    mysql热备脚本
    linux系统编程-进程
    15-模块
    14-面向对象3
    13-面向对象2
    12-面向对象1
    02-对比两个文件的差异
    11-面向对象基础
    08-不定长函数
    07-缺省参数
  • 原文地址:https://www.cnblogs.com/huty/p/8516982.html
Copyright © 2011-2022 走看看