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