Superpixel Benchmark
Superpixel benchmark, tools and algorithms.
connected_components.h
Go to the documentation of this file.
1 
6 #ifndef _CONNECTED_H
7 #define _CONNECTED_H
8 
9 #include <vector>
10 #include <algorithm>
11 
17 {
18 public:
19  ConnectedComponents(int soft_maxlabels) : labels(soft_maxlabels) {
20  clear();
21  }
22  void clear() {
23  std::fill(labels.begin(), labels.end(), Similarity());
24  highest_label = 0;
25  }
26  template<class Tin, class Tlabel, class Comparator, class Boolean>
27  int connected(const Tin *img, Tlabel *out,
28  int width, int height, Comparator,
29  Boolean K8_connectivity);
30 
31 private:
32  struct Similarity {
33  Similarity() : id(0), sameas(0) {}
34  Similarity(int _id, int _sameas) : id(_id), sameas(_sameas) {}
35  Similarity(int _id) : id(_id), sameas(_id) {}
36  int id, sameas, tag;
37  };
38 
39  bool is_root_label(int id) {
40  return (labels[id].sameas == id);
41  }
42  int root_of(int id) {
43  while (!is_root_label(id)) {
44  // link this node to its parent's parent, just to shorten
45  // the tree.
46  labels[id].sameas = labels[labels[id].sameas].sameas;
47 
48  id = labels[id].sameas;
49  }
50  return id;
51  }
52  bool is_equivalent(int id, int as) {
53  return (root_of(id) == root_of(as));
54  }
55  bool merge(int id1, int id2) {
56  if(!is_equivalent(id1, id2)) {
57  labels[root_of(id1)].sameas = root_of(id2);
58  return false;
59  }
60  return true;
61  }
62  int new_label() {
63  if(highest_label+1 > labels.size())
64  labels.reserve(highest_label*2);
65  labels.resize(highest_label+1);
66  labels[highest_label] = Similarity(highest_label);
67  return highest_label++;
68  }
69 
70 
71  template<class Tin, class Tlabel, class Comparator, class Boolean>
72  void label_image(const Tin *img, Tlabel *out,
73  int width, int height, Comparator,
74  Boolean K8_connectivity);
75  template<class Tlabel>
76  int relabel_image(Tlabel *out, int width, int height);
77 
78 
79  std::vector<Similarity> labels;
80  int highest_label;
81 };
82 
83 template<class Tin, class Tlabel, class Comparator, class Boolean>
84 int
85 ConnectedComponents::connected(const Tin *img, Tlabel *labelimg,
86  int width, int height, Comparator SAME,
87  Boolean K8_connectivity)
88 {
89  label_image(img,labelimg, width,height, SAME, K8_connectivity);
90  return relabel_image(labelimg, width,height);
91 }
92 
93 template<class Tin, class Tlabel, class Comparator, class Boolean>
94 void
95 ConnectedComponents::label_image(const Tin *img, Tlabel *labelimg,
96  int width, int height, Comparator SAME,
97  const Boolean K8_CONNECTIVITY)
98 {
99  const Tin *row = img;
100  const Tin *last_row = 0;
101  struct Label_handler {
102  Label_handler(const Tin *img, Tlabel *limg) :
103  piximg(img), labelimg(limg) {}
104  Tlabel &operator()(const Tin *pixp) { return labelimg[pixp-piximg]; }
105  const Tin *piximg;
106  Tlabel *labelimg;
107  } label(img, labelimg);
108 
109  clear();
110 
111  label(&row[0]) = new_label();
112 
113  // label the first row.
114  for(int c=1; c<width; ++c) {
115  if(SAME(row[c], row[c-1]))
116  label(&row[c]) = label(&row[c-1]);
117  else
118  label(&row[c]) = new_label();
119  }
120 
121  // label subsequent rows.
122  for(int r=1; r<height; ++r) {
123  // label the first pixel on this row.
124  last_row = row;
125  row = &img[width*r];
126 
127  if(SAME(row[0], last_row[0]))
128  label(&row[0]) = label(&last_row[0]);
129  else
130  label(&row[0]) = new_label();
131 
132  // label subsequent pixels on this row.
133  for(int c=1; c<width; ++c) {
134  int mylab = -1;
135 
136  // inherit label from pixel on the left if we're in the same blob.
137  if(SAME(row[c],row[c-1]))
138  mylab = label(&row[c-1]);
139  for(int d=(K8_CONNECTIVITY?-1:0); d<1; ++d) {
140  // if we're in the same blob, inherit value from above pixel.
141  // if we've already been assigned, merge its label with ours.
142  if(SAME(row[c], last_row[c+d])) {
143  if(mylab>=0) merge(mylab, label(&last_row[c+d]));
144  else mylab = label(&last_row[c+d]);
145  }
146  }
147  if(mylab>=0) label(&row[c]) = static_cast<Tlabel>(mylab);
148  else label(&row[c]) = new_label();
149 
150  if(K8_CONNECTIVITY && SAME(row[c-1], last_row[c]))
151  merge(label(&row[c-1]), label(&last_row[c]));
152  }
153  }
154 }
155 
156 template<class Tlabel>
157 int
158 ConnectedComponents::relabel_image(Tlabel *labelimg, int width, int height)
159 {
160  int newtag = 0;
161  for(int id=0; id<labels.size(); ++id)
162  if(is_root_label(id))
163  labels[id].tag = newtag++;
164 
165  for(int i = 0; i<width*height; ++i)
166  labelimg[i] = labels[root_of(labelimg[i])].tag;
167 
168  return newtag;
169 }
170 
171 
172 #endif // _CONNECTED_H
ConnectedComponents(int soft_maxlabels)
Definition: connected_components.h:19
int connected(const Tin *img, Tlabel *out, int width, int height, Comparator, Boolean K8_connectivity)
Definition: connected_components.h:85
void clear()
Definition: connected_components.h:22
Efficient (multi-label) connected components algorithm.
Definition: connected_components.h:16