00001
00002
00003
00004
00005
00006 #include "vil_blob.h"
00007 #include <vcl_algorithm.h>
00008 #include <vcl_cassert.h>
00009
00010 namespace
00011 {
00012
00013
00014
00015 class disjoint_sets
00016 {
00017 typedef unsigned LABEL;
00018 typedef unsigned LEN;
00019 struct node
00020 {
00021 LABEL parent;
00022 LEN rank;
00023 };
00024 vcl_vector<node> store_;
00025 public:
00026 disjoint_sets(): store_(1u)
00027 {
00028 store_.front().parent=0;
00029 store_.front().rank=0;
00030 }
00031
00032
00033 LABEL root(LABEL v)
00034 {
00035 node & n=store_[v];
00036 if (n.parent == v)
00037 return v;
00038 else
00039 {
00040 n.parent=root(n.parent);
00041 return n.parent;
00042 }
00043 }
00044
00045
00046 void merge_labels(LABEL left_label, LABEL right_label)
00047 {
00048 LABEL left_root = root(left_label);
00049 LABEL right_root = root(right_label);
00050 if (left_root == right_root) return;
00051 node& left_root_node = store_[left_root];
00052 node& right_root_node = store_[right_root];
00053 if (left_root_node.rank > right_root_node.rank)
00054 {
00055 right_root_node.parent = left_root_node.parent;
00056 }
00057 else
00058 {
00059 left_root_node.parent = right_root_node.parent;
00060 if (left_root_node.rank == right_root_node.rank)
00061 right_root_node.rank++;
00062 }
00063 }
00064
00065
00066 LABEL new_label()
00067 {
00068 node n = {(LABEL)store_.size(), 0};
00069 store_.push_back(n);
00070 return n.parent;
00071 }
00072
00073 LEN size()
00074 {
00075 return store_.size();
00076 }
00077 };
00078 }
00079
00080
00081 void vil_blob_labels(const vil_image_view<bool>& src_binary,
00082 vil_blob_connectivity conn,
00083 vil_image_view<unsigned>& dest_label)
00084 {
00085 unsigned ni=src_binary.ni();
00086 unsigned nj=src_binary.nj();
00087 dest_label.set_size(ni, nj);
00088 dest_label.fill(0);
00089
00090 disjoint_sets merge_list;
00091 vcl_vector<unsigned> neighbouring_labels;
00092
00093 unsigned n_prev_neighbours;
00094 switch (conn)
00095 {
00096 case vil_blob_4_conn:
00097 n_prev_neighbours=2;
00098 break;
00099 case vil_blob_8_conn:
00100 n_prev_neighbours=4;
00101 break;
00102 default:
00103 n_prev_neighbours=0; assert(!"unknown connectivity");
00104 }
00105
00106
00107
00108 int neighbourhood_ii[] = { -1, 0, -1, +1};
00109 int neighbourhood_jj[] = { 0, -1, -1, -1};
00110
00111 typedef vcl_vector<unsigned>::iterator ITER;
00112
00113 for (unsigned j=0; j<nj; ++j)
00114 for (unsigned i=0; i<ni; ++i)
00115 {
00116 if (!src_binary(i,j)) continue;
00117 neighbouring_labels.clear();
00118 for (unsigned l=0; l<n_prev_neighbours; ++l)
00119 {
00120 unsigned ii = i + neighbourhood_ii[l];
00121 if (ii >= ni) continue;
00122 unsigned jj = j + neighbourhood_jj[l];
00123 if (jj >= nj) continue;
00124 unsigned d = dest_label(ii,jj);
00125 if (d!=0) neighbouring_labels.push_back(d);
00126 }
00127 if (neighbouring_labels.empty())
00128 {
00129 unsigned new_label = merge_list.new_label();
00130 dest_label(i,j) = new_label;
00131 }
00132 else
00133 {
00134
00135 vcl_sort(neighbouring_labels.begin(), neighbouring_labels.end());
00136 ITER end = vcl_unique(neighbouring_labels.begin(), neighbouring_labels.end());
00137
00138
00139 ITER it=neighbouring_labels.begin();
00140 unsigned label = *it++;
00141 dest_label(i,j) = label;
00142
00143
00144
00145
00146
00147 for (; it!=end; ++it)
00148 merge_list.merge_labels(*it, label);
00149 }
00150 }
00151 unsigned n_merge=merge_list.size();
00152 vcl_vector<unsigned> renumbering(n_merge, 0u);
00153
00154
00155
00156 for (unsigned l=1; l<n_merge; ++l)
00157 {
00158 if (renumbering[l]!=0) continue;
00159 unsigned root_label = merge_list.root(l);
00160 unsigned root_label_renumber = renumbering[root_label];
00161 if (root_label_renumber==0)
00162 {
00163 renumbering[root_label]=l;
00164 renumbering[l]=l;
00165 }
00166 else
00167 renumbering[l]=renumbering[root_label];
00168 }
00169
00170
00171
00172 vcl_vector<unsigned> labels(renumbering.begin(), renumbering.end());
00173 vcl_sort(labels.begin(), labels.end());
00174 labels.erase(vcl_unique(labels.begin(), labels.end()), labels.end());
00175 const unsigned dodgy = static_cast<unsigned>(-1);
00176 vcl_vector<unsigned> renum_renum(renumbering.size(), dodgy);
00177 renum_renum[0]=0;
00178 for (unsigned l=0, n=labels.size(); l<n; ++l)
00179 renum_renum[labels[l]] = l;
00180
00181 for (ITER it=renumbering.begin(), end=renumbering.end(); it!=end; ++it)
00182 *it=renum_renum[*it];
00183
00184
00185 assert(vcl_find(renumbering.begin(), renumbering.end(), dodgy)
00186 == renumbering.end() );
00187
00188
00189
00190 for (unsigned j=0; j<nj; ++j)
00191 for (unsigned i=0; i<ni; ++i)
00192 dest_label(i,j) = renumbering[dest_label(i,j)];
00193 }
00194
00195
00196
00197 void vil_blob_labels_to_edge_labels(const vil_image_view<unsigned>& src_label,
00198 vil_blob_connectivity conn,
00199 vil_image_view<unsigned>& dest_label)
00200 {
00201 unsigned ni=src_label.ni();
00202 unsigned nj=src_label.nj();
00203 dest_label.set_size(ni, nj);
00204 dest_label.fill(0);
00205
00206 unsigned n_edge_neighbours;
00207 switch (conn)
00208 {
00209 case vil_blob_4_conn:
00210 n_edge_neighbours=8;
00211 break;
00212 case vil_blob_8_conn:
00213 n_edge_neighbours=4;
00214 break;
00215 default:
00216 n_edge_neighbours=0; assert(!"unknown connectivity");
00217 }
00218
00219
00220
00221 int neighbourhood_ii[] = { 0, -1, 1, 0, -1, 1, -1, 1};
00222 int neighbourhood_jj[] = { -1, 0, 0, 1, -1, -1, 1, 1};
00223
00224 for (unsigned j=0; j<nj; ++j)
00225 for (unsigned i=0; i<ni; ++i)
00226 {
00227 unsigned v = src_label(i,j);
00228 if (!v) continue;
00229 for (unsigned l=0; l<n_edge_neighbours; ++l)
00230 {
00231 unsigned ii = i + neighbourhood_ii[l];
00232 if (ii >= ni) continue;
00233 unsigned jj = j + neighbourhood_jj[l];
00234 if (jj >= nj) continue;
00235 if (v!=src_label(ii,jj))
00236 {
00237 dest_label(i,j) = v;
00238 break;
00239 }
00240 }
00241 }
00242 }
00243
00244
00245
00246
00247 void vil_blob_labels_to_regions(const vil_image_view<unsigned>& src_label,
00248 vcl_vector<vil_blob_region>& dest_regions)
00249 {
00250 dest_regions.clear();
00251 unsigned ni=src_label.ni();
00252 unsigned nj=src_label.nj();
00253
00254 for (unsigned j=0; j<nj; ++j)
00255 for (unsigned i=0; i<ni;)
00256 {
00257 unsigned label = src_label(i,j);
00258 if (!label)
00259 {
00260 ++i;
00261 continue;
00262 }
00263
00264 if (label > dest_regions.size()) dest_regions.resize(label);
00265 unsigned i_start=i;
00266
00267 while (++i < ni && src_label(i,j)==label);
00268 dest_regions[label-1].push_back(vil_chord(i_start, i-1, j));
00269 }
00270 }
00271
00272
00273
00274
00275 void vil_blob_labels_to_pixel_lists(const vil_image_view<unsigned>& src_label,
00276 vcl_vector<vil_blob_pixel_list>& dest_pixel_lists)
00277 {
00278 dest_pixel_lists.clear();
00279 unsigned ni=src_label.ni();
00280 unsigned nj=src_label.nj();
00281
00282 for (unsigned j=0; j<nj; ++j)
00283 for (unsigned i=0; i<ni; ++i)
00284 {
00285 unsigned label = src_label(i,j);
00286 if (!label) continue;
00287
00288 if (label > dest_pixel_lists.size()) dest_pixel_lists.resize(label);
00289 dest_pixel_lists[label-1].push_back(vcl_make_pair(i,j));
00290 }
00291 }