【数据结构】【计算机视觉】并查集(disjoint set)结构介绍

1.简述

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

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

2.结构体及函数定义

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

  1. classdisjointSets
  2. {
  3. public:
  4. //互斥集初始化,元素个数是elem_count
  5. disjointSets(intelem_count=0){createOneElemSets(elem_count);}
  6. voidcreateOneElemSets(intelem_count);//创建互斥集
  7. intfindSetByElem(intelem);//查找元素所属的集合
  8. intmergeSets(intset1,intset2);//合并两个集合
  9. std::vector<int>parent;//元素所属集合parent[elem]=set,元素elem的集合是set
  10. std::vector<int>size;//集合的包含的元素个数size[set]=set_size,集合set的元素数是set_size
  11. private:
  12. int>rank_;//rank_[set]=rank,集合set标记
  13. };

copy

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

copy

    #include"astdio.h"
  1. #include"disjointset.h"
  2. #defineconf_threshold90
  3. #definenum_imagES10
  4. voidmain()
  5. intmax_comp=0;
  6. intmax_size=0;
  7. vector<int>confident(num_images*num_images);
  8. disjointSetscomps(num_images);
  9. //使用随机数模拟多幅图像中每个图像相互匹配的置信度(0-100)
  10. //另外1与2的匹配置信度和2与1的置信度我们认相同(实际中是不相同的)
  11. srand((unsigned)time(NULL));
  12. inti=0;i<num_images;i++)
  13. cout<<endl;
  14. intj=0;j<num_images;j++)
  15. if(!confident[i*num_images+j])
  16. confident[i*num_images+j]=rand()%100;
  17. confident[j*num_images+i]=confident[i*num_images+j];
  18. if(i==j)
  19. confident[i*num_images+j]=100;
  20. }
  21. cout<<""<<confident[i*num_images+j];
  22. //根据两幅图匹配置信度是否大于conf_threshold来决定是否属于一个全景集合
  23. inti=0;i<num_images;++i)
  24. intj=0;j<num_images;++j)
  25. if(confident[i*num_images+j]<conf_threshold)
  26. continue;
  27. intcomp1=comps.findSetByElem(i);
  28. intcomp2=comps.findSetByElem(j);
  29. if(comp1!=comp2)
  30. comps.mergeSets(comp1,comp2);
  31. //找出包含图片最多的全景集合
  32. inti=0;i<num_images;i++)
  33. if(i==0)
  34. max_comp=0;
  35. max_size=comps.size[i];
  36. elseif(comps.size[i]>max_size)
  37. max_comp=i;
  38. max_size=comps.size[i];
  39. //将该集合中的元素打印出来
  40. cout<<endl<<"imagesinthemax_comp:"<<endl;
  41. intj=0;
  42. if(comps.findSetByElem(i)==max_comp)
  43. cout<<++j<<":"<<i<<endl;
  44. while(1);
  45. }

输出结果:

相关文章

【啊哈!算法】算法3:最常用的排序——快速排序       ...
匿名组 这里可能用到几个不同的分组构造。通过括号内围绕的正...
选择排序:从数组的起始位置处开始,把第一个元素与数组中其...
public struct Pqitem { public int priority; ...
在编写正则表达式的时候,经常会向要向正则表达式添加数量型...
来自:http://blog.csdn.net/morewindows/article/details/6...