【數據結構】【計算機視覺】並查集(disjoint set)結構介紹

1.簡述 

       在實現多圖像無序輸入的拼接中,咱們先使用surf算法對任意兩幅圖像進行特徵點匹配,每對圖像的匹配都有一個置信度confidence參數,來衡量兩幅圖匹配的可信度,當confidence>conf_threshold,咱們就認爲這兩幅圖能夠拼接,屬於一個全景拼接的集合,而後擴展這個集合就能夠肯定最大的可拼接集合,排除一些無效的圖像,而後進行後續的拼接。css

      並查集的定義就是並查集是一種樹型的數據結構,用於處理一些不相交集合(Disjoint Sets)的合併及查詢問題。即將屬於相同集合的元素合併起來,中間須要查找某個元素屬於哪一個集合,而後須要將兩個元素或者集合進行合併處理。html

   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. }  

輸出結果:

相關文章
相關標籤/搜索