00001
00002 #include "vifa_int_faces_attr.h"
00003
00004
00005 #include <vcl_algorithm.h>
00006 #include <vcl_cmath.h>
00007 #include <vcl_map.h>
00008 #include <vcl_utility.h>
00009 #include <vtol/vtol_edge.h>
00010 #include <vifa/vifa_incr_var.h>
00011 #include <vifa/vifa_parallel.h>
00012
00013
00014
00015
00016
00017
00018 AttrFuncPtr vifa_int_faces_attr::
00019 attr_get_funcs[] =
00020 {
00021 &vifa_int_face_attr::IntMax,
00022 &vifa_int_face_attr::IntMin,
00023 &vifa_int_face_attr::IntMean,
00024 &vifa_int_face_attr::IntVar,
00025 &vifa_int_face_attr::Area,
00026 &vifa_int_face_attr::AspectRatio,
00027 &vifa_int_face_attr::PerimeterLength,
00028 &vifa_int_face_attr::WeightedPerimeterLength,
00029 &vifa_int_face_attr::Complexity,
00030 &vifa_int_face_attr::WeightedComplexity,
00031 &vifa_int_face_attr_common::StrongParallelSal,
00032 &vifa_int_face_attr_common::WeakParallelSal,
00033 &vifa_int_face_attr::TwoPeakParallel,
00034 &vifa_int_face_attr::FourPeakParallel,
00035 &vifa_int_face_attr::EightyPercentParallel
00036 };
00037
00038 const char* const vifa_int_faces_attr::
00039 attr_names[] =
00040 {
00041 "IntMax",
00042 "IntMin",
00043 "IntMean",
00044 "IntVar",
00045 "Area",
00046 "AspectRatio",
00047 "PerimeterLength",
00048 "WeightedPerimeterLength",
00049 "Complexity",
00050 "WeightedComplexity",
00051 "StrongParallel",
00052 "WeakParallel",
00053 "TwoPeakParallel",
00054 "FourPeakParallel",
00055 "EightyPercentParallel"
00056 };
00057
00058
00059
00060 float vifa_int_faces_attr::
00061 attr_min_vals[] = {
00062 0.0039f,
00063 0.0039f,
00064 0.0039f,
00065 0.0001f,
00066 1.0f,
00067 1.0f,
00068 1.0f,
00069 1.0f,
00070 1.0f,
00071 1.0f,
00072 0.05f,
00073 0.05f,
00074 1e-5f,
00075 1e-5f,
00076 1e-5f
00077 };
00078
00079 void vifa_int_faces_attr::
00080 init()
00081 {
00082 centroid_.reserve(2);
00083 centroid_[0] = -1;
00084 centroid_[1] = -1;
00085 perimeter_ = -1;
00086 weighted_perimeter_ = -1;
00087
00088
00089 cached_2_parallel_ = -1;
00090 cached_4_parallel_ = -1;
00091 cached_80_parallel_ = -1;
00092
00093 npobj_ = 0;
00094
00095 attr_vec_.reserve(NumHistAttributes());
00096 for (int i=0; i < NumHistAttributes(); i++)
00097 {
00098
00099 attr_vec_.push_back(NULL);
00100 }
00101
00102 perimeter_ = -1.f;
00103 }
00104
00105 vifa_int_faces_attr::
00106 vifa_int_faces_attr(vdgl_fit_lines_params* fitter_params,
00107 vifa_group_pgram_params* gpp_s,
00108 vifa_group_pgram_params* gpp_w,
00109 vifa_coll_lines_params* cpp,
00110 vifa_norm_params* np,
00111 vifa_int_face_attr_factory* factory)
00112 : vifa_int_face_attr_common(fitter_params, gpp_s, gpp_w, cpp, np)
00113 {
00114 this->init();
00115 factory_ = factory;
00116 }
00117
00118 vifa_int_faces_attr::
00119 vifa_int_faces_attr(iface_list& v,
00120 vdgl_fit_lines_params* fitter_params,
00121 vifa_group_pgram_params* gpp_s,
00122 vifa_group_pgram_params* gpp_w,
00123 vifa_coll_lines_params* cpp,
00124 vifa_norm_params* np,
00125 vifa_int_face_attr_factory* factory)
00126 : vifa_int_face_attr_common(fitter_params, gpp_s, gpp_w, cpp, np),
00127 faces_(v)
00128 {
00129 this->init();
00130 factory_ = factory;
00131 attributes_valid_ = this->ComputeAttributes();
00132 }
00133
00134 vifa_int_faces_attr::
00135 ~vifa_int_faces_attr()
00136 {
00137 delete npobj_;
00138 }
00139
00140
00141
00142
00143
00144
00145 float vifa_int_faces_attr::
00146 CallAttrFunction(vifa_int_face_attr* seed_attr,int i)
00147 {
00148 return (seed_attr->*(attr_get_funcs[i]))();
00149 }
00150
00151 void vifa_int_faces_attr::
00152 SetFaces(iface_list& v)
00153 {
00154
00155 faces_ = v;
00156
00157
00158 delete npobj_;
00159 this->init();
00160
00161
00162 attributes_valid_ = this->ComputeAttributes();
00163 }
00164
00165 edge_2d_list& vifa_int_faces_attr::
00166 GetEdges()
00167 {
00168
00169 if (!edges_.empty())
00170 return edges_;
00171
00172 if (faces_.empty())
00173 {
00174 vcl_cerr << "vifa_int_faces_attr::GetEdges: faces_ is not set\n";
00175 return edges_;
00176 }
00177
00178
00179 for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00180 {
00181 edge_list fedges; (*f)->edges(fedges);
00182 edge_2d_iterator edges_pos_;
00183 for (edge_iterator ei = fedges.begin(); ei != fedges.end(); ei++)
00184 {
00185 vtol_edge_2d* e_ptr = (*ei)->cast_to_edge_2d();
00186
00187 if (e_ptr)
00188 {
00189 vtol_edge_2d_sptr e = vtol_edge_2d_sptr(e_ptr);
00190
00191 edges_pos_ = vcl_find(edges_.begin(), edges_.end(), e);
00192 if (edges_pos_ == edges_.end())
00193 edges_.push_back(e);
00194 }
00195 }
00196 }
00197
00198 return edges_;
00199 }
00200
00201
00202
00203
00204 void vifa_int_faces_attr::
00205 ComputeCentroid()
00206 {
00207 if ((centroid_[0] < 0) && !attr_map_.empty())
00208 {
00209 float area_sum = 0;
00210 float x_area_sum = 0;
00211 float y_area_sum = 0;
00212
00213 for (attr_iterator ai = attr_map_.begin();
00214 ai != attr_map_.end(); ++ai)
00215 {
00216 float area = (*ai)->Area();
00217 area_sum += area;
00218 x_area_sum += area * (*ai)->Xo();
00219 y_area_sum += area * (*ai)->Yo();
00220 }
00221
00222 if (!area_sum)
00223 return;
00224
00225 centroid_[0] = x_area_sum / area_sum;
00226 centroid_[1] = y_area_sum / area_sum;
00227 }
00228 }
00229
00230
00231 float vifa_int_faces_attr::
00232 Xo()
00233 {
00234 if ((centroid_[0] < 0) && !attr_map_.empty())
00235 this->ComputeCentroid();
00236
00237 return centroid_[0];
00238 }
00239
00240
00241 float vifa_int_faces_attr::
00242 Yo()
00243 {
00244 if ((centroid_[1] < 0) && !attr_map_.empty())
00245 this->ComputeCentroid();
00246
00247 return centroid_[1];
00248 }
00249
00250
00251
00252
00253
00254
00255
00256 bool vifa_int_faces_attr::
00257 ComputeSingleFaceAttributes(bool forceP)
00258 {
00259 if (!forceP && attributes_valid_)
00260 return true;
00261
00262 attr_map_.clear();
00263 for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00264 {
00265 vifa_int_face_attr_sptr fattr = factory_new_attr(*f);
00266
00267 if (!(fattr->valid_p()))
00268 return false;
00269
00270 attr_map_.push_back(fattr);
00271 }
00272
00273 return true;
00274 }
00275
00276 bool vifa_int_faces_attr::
00277 ComputeAttributes()
00278 {
00279 if (!this->ComputeSingleFaceAttributes(true))
00280 attributes_valid_ = false;
00281 else
00282 {
00283
00284
00285 for (int i = 0; i < NumHistAttributes(); i++)
00286 this->GetMeanAttr(i);
00287
00288 attributes_valid_ = true;
00289 }
00290
00291 return valid_p();
00292 }
00293
00294
00295 bool vifa_int_faces_attr::
00296 GetAttributes(vcl_vector<float>& attrs)
00297 {
00298
00299
00300
00301 return this->vifa_int_faces_attr::GetNativeAttributes(attrs);
00302 }
00303
00304
00305
00306 bool vifa_int_faces_attr::
00307 GetNativeAttributes(vcl_vector<float>& attrs)
00308 {
00309 if (!this->ComputeAttributes())
00310 {
00311 vcl_cerr << "Couldn't compute group attributes?\n";
00312 return false;
00313 }
00314
00315 attrs.push_back(this->Area());
00316 attrs.push_back(this->PerimeterLength());
00317 attrs.push_back(this->WeightedPerimeterLength());
00318 attrs.push_back(this->Complexity());
00319 attrs.push_back(this->WeightedComplexity());
00320 attrs.push_back(this->StrongParallelSal());
00321 attrs.push_back(this->WeakParallelSal());
00322 attrs.push_back(this->TwoPeakParallel());
00323 attrs.push_back(this->FourPeakParallel());
00324 attrs.push_back(this->EightyPercentParallel());
00325
00326 for (int i = 0; i < this->NumHistAttributes(); i++)
00327 attrs.push_back(this->GetMeanAttr(i));
00328
00329 for (int i = 0; i < this->NumHistAttributes(); i++)
00330 attrs.push_back(this->GetSDAttr(i));
00331
00332 return true;
00333 }
00334
00335
00336
00337 void vifa_int_faces_attr::
00338 GetAttributeNames(vcl_vector<vcl_string>& names)
00339 {
00340 names.push_back("gArea");
00341 names.push_back("gPerimeterLength");
00342 names.push_back("gWeightedPerimeterLength");
00343 names.push_back("gComplexity");
00344 names.push_back("gWeightedComplexity");
00345 names.push_back("gStrongParallel");
00346 names.push_back("gWeakParallel");
00347 names.push_back("gTwoPeakParallel");
00348 names.push_back("gFourPeakParallel");
00349 names.push_back("gEightyPercentParallel");
00350
00351 for (int i = 0; i < NUM_HIST_ATTRIBUTES; i++)
00352 {
00353 vcl_string name(attr_names[i]);
00354 names.push_back("mean" + name);
00355 }
00356
00357 for (int i = 0; i < NUM_HIST_ATTRIBUTES; i++)
00358 {
00359 vcl_string name(attr_names[i]);
00360 names.push_back("sd" + name);
00361 }
00362 }
00363
00364 const char* vifa_int_faces_attr::
00365 GetBaseAttrName(int i)
00366 {
00367 return vifa_int_faces_attr::attr_names[i];
00368 }
00369
00370
00371
00372
00373 vifa_histogram_sptr vifa_int_faces_attr::
00374 MakeAttrHist(vcl_vector<float>& attr_vals)
00375 {
00376 this->ComputeSingleFaceAttributes(false);
00377
00378
00379 int num_bins = vcl_max(20, (int)vcl_sqrt( static_cast<float>(attr_vals.size()) ));
00380
00381
00382 float max_val = 0;
00383 float min_val = 1000000;
00384 for (vcl_vector<float>::iterator vali = attr_vals.begin();
00385 vali != attr_vals.end(); ++vali)
00386 {
00387 float val = *vali;
00388
00389 if (val > max_val)
00390 max_val = val;
00391
00392 if (val < min_val)
00393 min_val = val;
00394 }
00395
00396
00397 vifa_histogram_sptr val_hist = new vifa_histogram(num_bins,
00398 min_val,
00399 max_val);
00400
00401
00402 for (vcl_vector<float>::iterator vali = attr_vals.begin();
00403 vali != attr_vals.end(); ++vali)
00404 val_hist->UpCount(*vali);
00405
00406 return val_hist;
00407 }
00408
00409
00410
00411 float vifa_int_faces_attr::
00412 GetMeanAttr(int attr_index)
00413 {
00414 if (!attr_map_.empty())
00415 {
00416 if (!(attr_vec_[attr_index].ptr()))
00417 {
00418 attr_vec_[attr_index] = new vifa_incr_var;
00419
00420
00421 vcl_vector<float> vals(attr_map_.size());
00422 int index = 0;
00423 for (attr_iterator ai = attr_map_.begin();
00424 ai != attr_map_.end(); ++ai, ++index)
00425 {
00426 vifa_int_face_attr_sptr attr_ptr = *ai;
00427 vals[index] = CallAttrFunction(attr_ptr.ptr(), attr_index);
00428 attr_vec_[attr_index]->add_sample(vals[index]);
00429 }
00430 }
00431
00432 return float(attr_vec_[attr_index]->get_mean());
00433 }
00434 else
00435 {
00436
00437 return -1.f;
00438 }
00439 }
00440
00441
00442
00443 float vifa_int_faces_attr::
00444 GetSDAttr(int attr_index)
00445 {
00446 if (!attr_map_.empty())
00447 {
00448 if (!attr_vec_[attr_index].ptr())
00449 {
00450
00451 this->GetMeanAttr(attr_index);
00452 }
00453
00454 return (float)vcl_sqrt(attr_vec_[attr_index]->get_var());
00455 }
00456 else
00457 {
00458
00459 return -1;
00460 }
00461 }
00462
00463
00464
00465 float vifa_int_faces_attr::
00466 GetMinAttr(int attr_index)
00467 {
00468 if (!attr_map_.empty())
00469 {
00470 if (!attr_vec_[attr_index].ptr())
00471 {
00472
00473 this->GetMeanAttr(attr_index);
00474 }
00475
00476 return float(attr_vec_[attr_index]->get_min());
00477 }
00478 else
00479 return -1.f;
00480 }
00481
00482
00483
00484 float vifa_int_faces_attr::
00485 GetMaxAttr(int attr_index)
00486 {
00487 if (!attr_map_.empty())
00488 {
00489 if (!attr_vec_[attr_index].ptr())
00490 {
00491
00492 this->GetMeanAttr(attr_index);
00493 }
00494
00495 return float(attr_vec_[attr_index]->get_max());
00496 }
00497 else
00498 return -1.f;
00499 }
00500
00501
00502
00503
00504
00505 float vifa_int_faces_attr::
00506 Area()
00507 {
00508 if (!attr_map_.empty())
00509 {
00510 area_ = 0;
00511 for (attr_iterator ai = attr_map_.begin(); ai != attr_map_.end(); ++ai)
00512 area_ += (*ai)->Area();
00513
00514 return area_;
00515 }
00516 else
00517 return 0.f;
00518 }
00519
00520
00521 float vifa_int_faces_attr::
00522 AspectRatio()
00523 {
00524 return 0.f;
00525 }
00526
00527
00528 edge_list* vifa_int_faces_attr::
00529 GetPerimeterEdges()
00530 {
00531 edge_list* p_edges = new edge_list;
00532
00533 if (faces_.empty())
00534 {
00535 vcl_cerr << "no faces to calculate perimeter!\n";
00536 return p_edges;
00537 }
00538
00539
00540 vcl_map<int, int> edge_count;
00541 vcl_map<int, int>::iterator edge_count_pos;
00542
00543 int edge_index = 0;
00544 for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00545 {
00546 edge_list edges; (*f)->edges(edges);
00547
00548 for (edge_iterator ei = edges.begin(); ei != edges.end(); ei++)
00549 {
00550 vtol_edge_sptr e = *ei;
00551 int e_id = e->get_id();
00552
00553 if (e_id == 0)
00554 {
00555 e_id = ++edge_index;
00556 e->set_id(e_id);
00557 }
00558
00559 int count;
00560 edge_count_pos = edge_count.find(e_id);
00561 if (edge_count_pos == edge_count.end())
00562 count = 1;
00563 else
00564 count = edge_count_pos->second + 1;
00565
00566 edge_count.insert(vcl_pair<int, int>(e_id, count));
00567 }
00568 }
00569
00570 int unique_count = 0;
00571 for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00572 {
00573 edge_list edges; (*f)->edges(edges);
00574 for (edge_iterator ei = edges.begin(); ei != edges.end(); ei++)
00575 {
00576 vtol_edge_sptr e = *ei;
00577 int count;
00578
00579 edge_count_pos = edge_count.find(e->get_id());
00580 if (edge_count_pos == edge_count.end())
00581 {
00582 vcl_cerr << "Inconsistency in vifa_int_faces_attr::perimeter()?\n";
00583 continue;
00584 }
00585 else
00586 count = edge_count_pos->second;
00587
00588 if (count == 1)
00589 {
00590 unique_count++;
00591 p_edges->push_back(e);
00592 }
00593 }
00594 }
00595
00596 return p_edges;
00597 }
00598
00599
00600
00601 float vifa_int_faces_attr::
00602 PerimeterLength()
00603 {
00604 if (perimeter_ >= 0)
00605 {
00606
00607 return perimeter_;
00608 }
00609
00610 perimeter_ = 0;
00611
00612 edge_list* p_edges = this->GetPerimeterEdges();
00613 if (p_edges)
00614 {
00615 for (edge_iterator eit = p_edges->begin(); eit != p_edges->end(); ++eit)
00616 {
00617 vtol_edge_2d* e = (*eit)->cast_to_edge_2d();
00618
00619 if (e)
00620 perimeter_ += float(e->curve()->length());
00621 }
00622
00623 delete p_edges;
00624 }
00625
00626 return perimeter_;
00627 }
00628
00629 float vifa_int_faces_attr::
00630 WeightedPerimeterLength()
00631 {
00632 if (weighted_perimeter_ >= 0)
00633 return weighted_perimeter_;
00634
00635
00636
00637 weighted_perimeter_ = 0;
00638
00639 edge_list* p_edges = this->GetPerimeterEdges();
00640 if (p_edges)
00641 {
00642
00643
00644
00645 float weighted_perimeter_sum = 0;
00646 float contrast_sum = 0;
00647 for (edge_iterator eit = p_edges->begin(); eit != p_edges->end(); ++eit)
00648 {
00649 vtol_edge_2d* e = (*eit)->cast_to_edge_2d();
00650
00651 if (e)
00652 {
00653 face_list edge_faces; e->faces(edge_faces);
00654 iface_list in_faces;
00655 iface_list out_faces;
00656
00657
00658
00659 for (face_iterator fi=edge_faces.begin(); fi != edge_faces.end(); ++fi)
00660 {
00661 vtol_intensity_face* int_f = (*fi)->cast_to_intensity_face();
00662
00663 if (!int_f)
00664 {
00665 vcl_cerr << "vifa_int_faces_attr::WeightedPerimeterLength() -"
00666 << " Face is not an intensity face\n";
00667 continue;
00668 }
00669
00670 bool in_face = false;
00671 for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00672 {
00673 if (**f == *int_f)
00674 {
00675 in_face = true;
00676 in_faces.push_back(int_f);
00677 break;
00678 }
00679 }
00680
00681 if (!in_face)
00682 out_faces.push_back(int_f);
00683 }
00684
00685
00686
00687
00688
00689
00690 float i_intensity_sum = 0;
00691 float i_area_sum = 0;
00692 for (iface_iterator f = in_faces.begin(); f != in_faces.end(); ++f)
00693 {
00694 i_intensity_sum += ((*f)->Io() * (*f)->Npix());
00695 i_area_sum += (*f)->Npix();
00696 }
00697
00698
00699
00700
00701 float i_intensity = (i_area_sum > 0) ? i_intensity_sum / i_area_sum : 0.f;
00702
00703 float o_intensity_sum = 0;
00704 float o_area_sum = 0;
00705 for (iface_iterator f = out_faces.begin();
00706 f != out_faces.end(); ++f)
00707 {
00708 o_intensity_sum += ((*f)->Io() * (*f)->Npix());
00709 o_area_sum += (*f)->Npix();
00710 }
00711
00712
00713
00714
00715 float o_intensity = (o_area_sum > 0) ? o_intensity_sum / o_area_sum : 0.f;
00716
00717 float intensity_gradient = vcl_fabs(i_intensity - o_intensity);
00718
00719
00720
00721
00722 weighted_perimeter_sum +=
00723 float(e->curve()->length()) * intensity_gradient;
00724 contrast_sum += intensity_gradient;
00725 }
00726 else
00727 vcl_cerr << "(*eit)->cast_to_edge_2d() returned NULL\n";
00728 }
00729
00730
00731
00732
00733 weighted_perimeter_ = weighted_perimeter_sum / contrast_sum;
00734 delete p_edges;
00735 }
00736
00737
00738
00739 return weighted_perimeter_;
00740 }
00741
00742
00743 float vifa_int_faces_attr::
00744 Complexity()
00745 {
00746 if (this->Area() <= 0)
00747 return 0.f;
00748
00749 float p = this->PerimeterLength();
00750 return p * p / this->Area();
00751 }
00752
00753
00754 float vifa_int_faces_attr::
00755 WeightedComplexity()
00756 {
00757 if (this->Area() <= 0)
00758 return 0.f;
00759
00760 float wp = this->WeightedPerimeterLength();
00761 return wp * wp / this->Area();
00762 }
00763
00764 void vifa_int_faces_attr::
00765 SetNP()
00766 {
00767 if (npobj_)
00768 npobj_->reset();
00769 else
00770 npobj_ = new vifa_parallel(faces_, true);
00771 }
00772
00773 float vifa_int_faces_attr::
00774 TwoPeakParallel()
00775 {
00776 if (cached_2_parallel_ < 0)
00777 {
00778 SetNP();
00779 float max_angle;
00780 float std_dev;
00781 float scale;
00782
00783 for (int i=0; i<1; i++)
00784 {
00785 npobj_->map_gaussian(max_angle, std_dev, scale);
00786 npobj_->remove_gaussian(max_angle, std_dev, scale);
00787 }
00788
00789 cached_2_parallel_ = npobj_->area();
00790 }
00791
00792 return cached_2_parallel_;
00793 }
00794
00795 float vifa_int_faces_attr::
00796 FourPeakParallel()
00797 {
00798 if (cached_4_parallel_ < 0)
00799 {
00800 SetNP();
00801 float max_angle;
00802 float std_dev;
00803 float scale;
00804
00805 for (int i=0; i<3; i++)
00806 {
00807 npobj_->map_gaussian(max_angle, std_dev, scale);
00808 npobj_->remove_gaussian(max_angle, std_dev, scale);
00809 }
00810
00811 cached_4_parallel_ = npobj_->area();
00812 }
00813
00814 return cached_4_parallel_;
00815 }
00816
00817 float vifa_int_faces_attr::
00818 EightyPercentParallel()
00819 {
00820 if (cached_80_parallel_ < 0)
00821 {
00822 SetNP();
00823
00824 for (int i=0; i < 20 && npobj_->area() > 0.3f; ++i)
00825 {
00826 float max_angle, std_dev, scale;
00827 npobj_->map_gaussian(max_angle, std_dev, scale);
00828 npobj_->remove_gaussian(max_angle, std_dev, scale);
00829 cached_80_parallel_ = float(i);
00830 }
00831 }
00832
00833 return cached_80_parallel_;
00834 }
00835
00836 vifa_int_face_attr_sptr vifa_int_faces_attr::
00837 factory_new_attr(vtol_intensity_face_sptr face)
00838 {
00839 if (factory_)
00840 return factory_->obtain_int_face_attr(face,
00841 fitter_params_.ptr(),
00842 gpp_s_.ptr(),
00843 gpp_w_.ptr(),
00844 np_.ptr());
00845 else
00846 return new vifa_int_face_attr(face,
00847 fitter_params_.ptr(),
00848 gpp_s_.ptr(),
00849 gpp_w_.ptr(),
00850 np_.ptr());
00851 }