00001
00002 #include <vdgl/vdgl_fit_lines.h>
00003 #include <vtol/vtol_intensity_face.h>
00004 #include <vgl/vgl_point_2d.h>
00005 #include <vsol/vsol_line_2d.h>
00006 #include <vtol/vtol_vertex_sptr.h>
00007 #include <vifa/vifa_int_face_attr_common.h>
00008 #include <vifa/vifa_group_pgram.h>
00009 #include <vcl_cmath.h>
00010
00011 vifa_int_face_attr_common::
00012 vifa_int_face_attr_common(vdgl_fit_lines_params* fitter_params,
00013 vifa_group_pgram_params* gpp_s,
00014 vifa_group_pgram_params* gpp_w,
00015 vifa_coll_lines_params* cpp,
00016 vifa_norm_params* np) :
00017 vifa_int_face_attr_common_params(fitter_params, gpp_s, gpp_w, cpp, np)
00018 {
00019 this->init();
00020 }
00021
00022 vifa_int_face_attr_common::~vifa_int_face_attr_common()
00023 {
00024 }
00025
00026
00027
00028
00029
00030
00031
00032 edge_2d_list& vifa_int_face_attr_common::
00033 GetFittedEdges()
00034 {
00035 if (!fitted_edges_.size())
00036 this->fit_lines();
00037
00038 return fitted_edges_;
00039 }
00040
00041 coll_list& vifa_int_face_attr_common::
00042 get_collinear_lines()
00043 {
00044 if (!cpp_)
00045 cpp_ = new vifa_coll_lines_params;
00046
00047 if (!collinear_lines_.size())
00048 this->find_collinear_lines();
00049
00050 return collinear_lines_;
00051 }
00052
00053 double vifa_int_face_attr_common::
00054 col_collapse()
00055 {
00056 double collapsed_count = 0;
00057 double total_count = 0;
00058
00059 for (coll_iterator c = collinear_lines_.begin();
00060 c != collinear_lines_.end(); ++c)
00061 {
00062 total_count++;
00063
00064 if ((*c)->get_discard_flag())
00065 collapsed_count++;
00066 }
00067
00068 if (total_count == 0)
00069 return 0;
00070
00071 return collapsed_count / total_count;
00072 }
00073
00074 double vifa_int_face_attr_common::
00075 get_contrast_across_edge(vtol_edge_sptr e, double dflt_cont)
00076 {
00077 double cont = dflt_cont;
00078 face_list faces; e->faces(faces);
00079
00080
00081 if (faces.size() == 2)
00082 {
00083 vtol_intensity_face* f1 = faces[0]->cast_to_intensity_face();
00084 vtol_intensity_face* f2 = faces[1]->cast_to_intensity_face();
00085
00086 if (f1 && f2)
00087 cont = vcl_fabs(f1->Io() - f2->Io());
00088 }
00089 return cont;
00090 }
00091
00092 vifa_coll_lines_sptr vifa_int_face_attr_common::
00093 get_line_along_edge(vtol_edge* edge)
00094 {
00095 vifa_coll_lines_sptr ret(0);
00096 vtol_vertex_sptr ev1 = edge->v1();
00097 vtol_vertex_sptr ev2 = edge->v2();
00098
00099 for (coll_iterator c = collinear_lines_.begin();
00100 c != collinear_lines_.end(); ++c)
00101 {
00102 edge_2d_list& c_edges = (*c)->get_contributors();
00103
00104 for (edge_2d_iterator e = c_edges.begin(); e != c_edges.end(); ++e)
00105 {
00106 vtol_vertex_sptr v1 = (*e)->v1();
00107 vtol_vertex_sptr v2 = (*e)->v2();
00108
00109 if (((*ev1 == *v1) && (*ev2 == *v2)) ||
00110 ((*ev1 == *v2) && (*ev2 == *v1)))
00111 ret = *c;
00112 }
00113 }
00114
00115 return ret;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 float vifa_int_face_attr_common::
00127 StrongParallelSal()
00128 {
00129 if (para_sal_strong_ < 0)
00130 {
00131 if (!gpp_s_.ptr())
00132 {
00133 const float angle_increment = 5.f;
00134 gpp_s_ = new vifa_group_pgram_params(angle_increment);
00135 }
00136
00137 para_sal_strong_ = this->compute_parallel_sal(gpp_s_);
00138 }
00139
00140 return para_sal_strong_;
00141 }
00142
00143 float vifa_int_face_attr_common::
00144 WeakParallelSal()
00145 {
00146 if (para_sal_weak_ < 0)
00147 {
00148 if (!gpp_w_.ptr())
00149 {
00150 const float angle_increment = 20.f;
00151 gpp_w_ = new vifa_group_pgram_params(angle_increment);
00152 }
00153
00154 para_sal_weak_ = this->compute_parallel_sal(gpp_w_);
00155 }
00156
00157 return para_sal_weak_;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166 void vifa_int_face_attr_common::
00167 init()
00168 {
00169 attributes_valid_ = false;
00170 complexity_ = -1;
00171 weighted_complexity_ = -1;
00172 aspect_ratio_ = -1;
00173 peri_length_ = -1;
00174 weighted_peri_length_ = -1;
00175 para_sal_weak_ = -1;
00176 para_sal_strong_ = -1;
00177 }
00178
00179
00180
00181
00182 void vifa_int_face_attr_common::
00183 fit_lines()
00184 {
00185 edge_2d_list edges_in_vect = this->GetEdges();
00186
00187 #ifdef DEBUG
00188 vcl_cout << "ifac::fit_lines(): " << edges_in_vect.size()
00189 << " edges available\n";
00190 #endif
00191
00192 if (!edges_in_vect.size())
00193 {
00194 vcl_cerr << "vifa_int_face_attr_common::fit_lines: face_ is not set\n";
00195 return;
00196 }
00197
00198 vcl_vector<vdgl_digital_curve_sptr> curves_in;
00199 for (edge_2d_iterator ei = edges_in_vect.begin();
00200 ei != edges_in_vect.end(); ei++)
00201 {
00202 vsol_curve_2d_sptr c = (*ei)->curve();
00203 vdgl_digital_curve_sptr dc = c->cast_to_vdgl_digital_curve();
00204 if (!dc)
00205 continue;
00206 curves_in.push_back(dc);
00207 }
00208
00209 if (!fitter_params_.ptr())
00210 {
00211 const int fit_length = 6;
00212 fitter_params_ = new vdgl_fit_lines_params(fit_length);
00213 }
00214
00215
00216 vdgl_fit_lines fitter(*(fitter_params_.ptr()));
00217 fitter.set_curves(curves_in);
00218 vcl_vector<vsol_line_2d_sptr>& segs = fitter.get_line_segs();
00219
00220 #ifdef DEBUG
00221 vcl_cout << "ifac::fit_lines(): " << segs.size() << " segments from fitter\n";
00222 #endif
00223
00224
00225 vcl_vector<vsol_line_2d_sptr>::iterator segi = segs.begin();
00226 for (; segi != segs.end(); segi++)
00227 {
00228 vsol_line_2d_sptr seg = *segi;
00229 vtol_vertex_2d_sptr v1 = new vtol_vertex_2d(*(seg->p0()));
00230 vtol_vertex_2d_sptr v2 = new vtol_vertex_2d(*(seg->p1()));
00231 vtol_edge_2d_sptr e = new vtol_edge_2d(v1, v2);
00232 fitted_edges_.push_back(e);
00233
00234
00235 fitted_edges_stats_.add_sample(seg->length());
00236 }
00237 }
00238
00239 void vifa_int_face_attr_common::
00240 find_collinear_lines()
00241 {
00242
00243 edge_2d_list unsorted_edges = this->GetFittedEdges();
00244 edge_2d_list f_edges;
00245 for (edge_2d_iterator e = unsorted_edges.begin();
00246 e != unsorted_edges.end(); ++e)
00247 {
00248 double len = (*e)->curve()->length();
00249 edge_2d_iterator slot = f_edges.begin();
00250 for (; slot != f_edges.end(); ++slot)
00251 if ((*slot)->curve()->length() < len)
00252 {
00253 f_edges.insert(slot, *e);
00254 break;
00255 }
00256 }
00257
00258
00259 coll_list unfiltered_lines;
00260 coll_iterator match;
00261
00262 #ifdef DEBUG
00263 vcl_cout << "Collineating: ";
00264 #endif
00265 for (edge_2d_iterator e = f_edges.begin(); e != f_edges.end(); ++e)
00266 {
00267 #ifdef DEBUG
00268 vcl_cout << '.';
00269 #endif
00270
00271 if ((*e)->curve()->length() == 0)
00272 continue;
00273
00274 bool match_flag = find_collinear_match(*e,
00275 unfiltered_lines,
00276 cpp_->midpt_distance(),
00277 match);
00278
00279 if (!match_flag)
00280 {
00281 vifa_coll_lines_sptr cl(new vifa_coll_lines(*e, cpp_->angle_tolerance()));
00282
00283 unfiltered_lines.push_back(cl);
00284 }
00285 else
00286 (*match)->add_and_update(*e);
00287 }
00288
00289 #ifdef DEBUG
00290 vcl_cout << vcl_endl;
00291 #endif
00292
00293
00294 for (coll_iterator c = unfiltered_lines.begin();
00295 c != unfiltered_lines.end(); ++c)
00296 {
00297 double span = (*c)->spanning_length();
00298 double support = (*c)->support_length();
00299
00300 if ((support/span) >= cpp_->discard_threshold())
00301 {
00302 collinear_lines_.push_back(*c);
00303 col_span_.add_sample(span);
00304 col_support_.add_sample(support);
00305 col_contrib_.add_sample((*c)->get_contributors().size());
00306 }
00307 else
00308 {
00309
00310 edge_2d_list& contrib = (*c)->get_contributors();
00311 for (edge_2d_iterator e = contrib.begin(); e != contrib.end(); ++e)
00312 {
00313 vifa_coll_lines_sptr cl(new vifa_coll_lines(*e,
00314 cpp_->angle_tolerance(),
00315 cpp_->endpt_distance(),
00316 true));
00317
00318 collinear_lines_.push_back(cl);
00319
00320 double span = cl->spanning_length();
00321 double support = cl->support_length();
00322
00323 col_span_.add_sample(span);
00324 col_support_.add_sample(support);
00325 col_contrib_.add_sample(cl->get_contributors().size());
00326 }
00327 }
00328 }
00329
00330 #ifdef DEBUG
00331 vcl_cout << unfiltered_lines.size() << " raw collinear lines; "
00332 << collinear_lines_.size() << " lines above discard threshold "
00333 << cpp_->discard_threshold_ << vcl_endl;
00334 #endif
00335 }
00336
00337 bool vifa_int_face_attr_common::
00338 find_collinear_match(vtol_edge_2d_sptr edge,
00339 coll_list& lines,
00340 double dist_threshold,
00341 coll_iterator& result)
00342 {
00343 double min_dist = dist_threshold;
00344 coll_iterator match = lines.end();
00345 for (coll_iterator c = lines.begin(); c != lines.end(); ++c)
00346 {
00347 double dist = (*c)->get_measure(edge);
00348 if ((dist < dist_threshold) && (dist < min_dist))
00349 {
00350 min_dist = dist;
00351 match = c;
00352 }
00353 }
00354
00355 if (match == lines.end())
00356 {
00357 return false;
00358 }
00359
00360 result = match;
00361 return true;
00362 }
00363
00364 float vifa_int_face_attr_common::
00365 compute_parallel_sal(vifa_group_pgram_params_sptr gpp)
00366 {
00367 float sal = 0.f;
00368 edge_2d_list fedges = this->GetFittedEdges();
00369
00370 #ifdef DEBUG
00371 vcl_cout << "ifac::compute_parallel_sal(): " << fedges.size()
00372 << " edges found\n";
00373 #endif
00374
00375 if (fedges.size())
00376 {
00377 #ifdef DEBUG
00378 vcl_cout << (*fitter_params_);
00379 #endif
00380
00381 float total_len = 0.f;
00382 int nlines = 0;
00383 imp_line_list lg_filtered;
00384 for (edge_2d_iterator ei = fedges.begin(); ei != fedges.end(); ++ei)
00385 {
00386 vsol_curve_2d_sptr cur = (*ei)->curve();
00387 float len = float(cur->length());
00388 total_len += len;
00389
00390 if (len >= fitter_params_->min_fit_length_)
00391 {
00392 const vgl_point_2d<double>& p1 = cur->p0()->get_p();
00393 const vgl_point_2d<double>& p2 = cur->p1()->get_p();
00394 imp_line_sptr filt_line = new imp_line(p1, p2);
00395
00396 lg_filtered.push_back(filt_line);
00397 nlines++;
00398 }
00399 }
00400
00401 #ifdef DEBUG
00402 vcl_cout << "ifac::compute_parallel_sal(): " << nlines
00403 << " lines after filtering, total_len = " << total_len << vcl_endl;
00404 #endif
00405
00406
00407 if (nlines > 2)
00408 {
00409
00410 vifa_group_pgram gp(lg_filtered, *gpp);
00411 gp.SetTemp1(total_len);
00412
00413
00414 sal = float(gp.norm_parallel_line_length());
00415 }
00416 }
00417
00418 return sal;
00419 }