1 // This is brl/bseg/brec/brec_part_hierarchy_detector.cxx
2 #include <utility>
3 #include <iostream>
4 #include <algorithm>
5 #include "brec_part_hierarchy_detector.h"
6 //:
7 // \file
8 // \author Ozge C Ozcanli (ozge@lems.brown.edu)
9 // \date Oct 16, 2008
10 
11 #include "brec_part_base.h"
12 #include "brec_part_gaussian.h"
13 #include "brec_part_hierarchy.h"
14 
15 #include "vil/vil_image_view.h"
16 #include "vil/vil_image_resource.h"
17 
18 #ifdef _MSC_VER
19 #  include "vcl_msvc_warnings.h"
20 #endif
21 
~brec_part_hierarchy_detector()22 brec_part_hierarchy_detector::~brec_part_hierarchy_detector()
23 {
24   auto it = map_rtree_.begin();
25   for ( ; it != map_rtree_.end(); it++) {
26     delete (*it).second;
27   }
28 
29   map_rtree_.clear();
30 
31   auto it2 = map_instance_.begin();
32   for ( ; it2 != map_instance_.end(); it2++) {
33     ((*it2).second).clear();
34   }
35 
36   map_instance_.clear();
37 }
38 
detect(const vil_image_resource_sptr & img)39 bool brec_part_hierarchy_detector::detect(const vil_image_resource_sptr& img)
40 {
41   // start from the primitives
42   std::vector<brec_part_instance_sptr> dumm_ins = h_->get_dummy_primitive_instances();
43   std::vector<brec_part_instance_sptr> parts_prims;
44   for (auto & dumm_in : dumm_ins) {
45     if (dumm_in->kind_ == brec_part_instance_kind::GAUSSIAN) {
46       brec_part_gaussian_sptr p = dumm_in->cast_to_gaussian();
47       if (!extract_gaussian_primitives(img, p->lambda0_, p->lambda1_, p->theta_, p->bright_, p->cutoff_percentage_, p->detection_threshold_, p->type_, parts_prims)) {
48         std::cout << "problems in extracting gaussian primitives!!\n";
49         return false;
50       }
51     }
52   }
53 
54   map_instance_[0] = parts_prims;
55 
56   // create an rtree
57   auto *tr = new Rtree_type();
58   map_rtree_.insert(std::pair<unsigned, Rtree_type*> (0, tr));
59   for (const auto & parts_prim : parts_prims) {
60     tr->add(parts_prim);
61   }
62 
63   unsigned highest = h_->highest_layer_id();
64   std::vector<brec_part_instance_sptr> parts_upper_most(parts_prims);
65   Rtree_type *rtree_upper_most = tr;
66   for (unsigned l = 1; l <= highest; l++) {
67     std::vector<brec_part_instance_sptr> parts_current;
68 
69     extract_upper_layer(parts_upper_most, img->ni(), img->nj(), rtree_upper_most, parts_current);
70     std::cout << "extracted " << parts_current.size() << " parts of layer " << l << std::endl;
71 
72     map_instance_[l] = parts_current;
73 
74     auto *rtree_current = new Rtree_type();
75     map_rtree_.insert(std::pair<unsigned, Rtree_type*> (l, rtree_current));
76 
77     for (const auto & i : parts_current) {
78       rtree_current->add(i);
79     }
80 
81     parts_upper_most.clear();
82     parts_upper_most = parts_current;
83 
84     rtree_upper_most = rtree_current;
85   }
86 
87   std::cout << "\textracted " << parts_upper_most.size() << " of highest layer: " << highest << " parts, rtree size: " << rtree_upper_most->size() << std::endl;
88 
89   return true;
90 }
91 
92 //: extracts instances of each layer in the given image, by rotating the detector with the given amount
detect(const vil_image_resource_sptr & img,float angle)93 bool brec_part_hierarchy_detector::detect(const vil_image_resource_sptr& img, float angle)
94 {
95   // start from the primitives
96   std::vector<brec_part_instance_sptr> dumm_ins = h_->get_dummy_primitive_instances();
97   std::vector<brec_part_instance_sptr> parts_prims;
98   for (auto & dumm_in : dumm_ins) {
99     if (dumm_in->kind_ == brec_part_instance_kind::GAUSSIAN) {
100       brec_part_gaussian_sptr p = dumm_in->cast_to_gaussian();
101       if (!extract_gaussian_primitives(img, p->lambda0_, p->lambda1_, p->theta_+angle, p->bright_, p->cutoff_percentage_, p->detection_threshold_, p->type_, parts_prims)) {
102         std::cout << "problems in extracting gaussian primitives!!\n";
103         return false;
104       }
105     }
106   }
107   map_instance_[0] = parts_prims;
108   std::cout << "extracted " << parts_prims.size() << " parts of layer 0\n";
109   // create an rtree
110   auto *tr = new Rtree_type();
111   map_rtree_.insert(std::pair<unsigned, Rtree_type*> (0, tr));
112   for (const auto & parts_prim : parts_prims) {
113     tr->add(parts_prim);
114   }
115 
116   unsigned highest = h_->highest_layer_id();
117   std::vector<brec_part_instance_sptr> parts_upper_most(parts_prims);
118   Rtree_type *rtree_upper_most = tr;
119   for (unsigned l = 1; l <= highest; l++) {
120     std::vector<brec_part_instance_sptr> parts_current;
121 
122     extract_upper_layer(parts_upper_most, img->ni(), img->nj(), rtree_upper_most, parts_current);
123     std::cout << "extracted " << parts_current.size() << " parts of layer " << l << std::endl;
124 
125     map_instance_[l] = parts_current;
126 
127     auto *rtree_current = new Rtree_type();
128     map_rtree_.insert(std::pair<unsigned, Rtree_type*> (l, rtree_current));
129 
130     for (const auto & i : parts_current) {
131       rtree_current->add(i);
132     }
133 
134     parts_upper_most.clear();
135     parts_upper_most = parts_current;
136 
137     rtree_upper_most = rtree_current;
138   }
139 
140   std::cout << "\textracted " << parts_upper_most.size() << " of highest layer: " << highest << " parts, rtree size: " << rtree_upper_most->size() << std::endl;
141 
142   return true;
143 }
144 
detect_primitives_using_trained_response_models(vil_image_view<float> & img,vil_image_view<float> & fg_prob_img,float angle,float prior_class)145 bool brec_part_hierarchy_detector::detect_primitives_using_trained_response_models(vil_image_view<float>& img, vil_image_view<float>& fg_prob_img, float angle, float prior_class)
146 {
147   // start from the primitives
148   std::vector<brec_part_instance_sptr> dumm_ins = h_->get_dummy_primitive_instances();
149   std::vector<brec_part_instance_sptr> parts_prims;
150   for (auto & dumm_in : dumm_ins) {
151     if (dumm_in->kind_ == brec_part_instance_kind::GAUSSIAN) {
152       brec_part_gaussian_sptr p = dumm_in->cast_to_gaussian();
153       if (!p->extract(img, fg_prob_img, angle, h_->model_dir(), parts_prims, prior_class)) {
154         std::cout << "problems in extracting gaussian primitives!!\n";
155         return false;
156       }
157     }
158   }
159 
160   map_instance_[0] = parts_prims;
161 
162   // create an rtree
163   auto *tr = new Rtree_type();
164   map_rtree_.insert(std::pair<unsigned, Rtree_type*> (0, tr));
165   for (const auto & parts_prim : parts_prims) {
166     tr->add(parts_prim);
167   }
168 
169   return true;
170 }
171 
172 //: sets rho parameter of the primitives differently during training
173 //  Rotates the detector with the given amount
detect_primitives_for_training(vil_image_view<float> & inp,vil_image_view<float> & fg_prob_img,float angle)174 bool brec_part_hierarchy_detector::detect_primitives_for_training(vil_image_view<float>& inp, vil_image_view<float>& fg_prob_img, float angle)
175 {
176   // start from the primitives
177   std::vector<brec_part_instance_sptr> dumm_ins = h_->get_dummy_primitive_instances();
178   std::vector<brec_part_instance_sptr> parts_prims;
179   for (auto & dumm_in : dumm_ins) {
180     if (dumm_in->kind_ == brec_part_instance_kind::GAUSSIAN) {
181       brec_part_gaussian_sptr p = dumm_in->cast_to_gaussian();
182       if (!p->extract(inp, fg_prob_img, angle, parts_prims)) {
183         std::cout << "problems in extracting gaussian primitives!!\n";
184         return false;
185       }
186     }
187   }
188   map_instance_[0] = parts_prims;
189   std::cout << "extracted " << parts_prims.size() << " primitives\n";
190 
191   // create an rtree
192   auto *tr = new Rtree_type();
193   map_rtree_.insert(std::pair<unsigned, Rtree_type*> (0, tr));
194   for (const auto & parts_prim : parts_prims) {
195     tr->add(parts_prim);
196   }
197 
198   return true;
199 }
200 
detect(vil_image_view<float> & img,vil_image_view<float> & fg_prob_img,float angle,unsigned rho_calculation_method,double radius,float prior_class,unsigned layer_id)201 bool brec_part_hierarchy_detector::detect(vil_image_view<float>& img, vil_image_view<float>& fg_prob_img, float angle, unsigned rho_calculation_method, double radius, float prior_class, unsigned layer_id)
202 {
203   switch (rho_calculation_method) {
204       case brec_detector_methods::POSTERIOR_NUMERATOR :
205       case brec_detector_methods::POSTERIOR :
206         if (!detect_primitives_using_trained_response_models(img, fg_prob_img, angle, prior_class))
207           return false;
208         break;
209       case brec_detector_methods::DENSITY_FOR_TRAINING :
210         if (!detect_primitives_for_training(img, fg_prob_img, angle))
211           return false;
212         break;
213       default:
214         std::cout << "Warning: unknown brec_detector_method encountered: " << rho_calculation_method << std::endl;
215         break;
216   }
217 
218   std::cout << "extracted " << map_instance_[0].size() << " primitive parts." << std::endl;
219 
220   unsigned highest = h_->highest_layer_id();
221   if (layer_id < highest)
222     highest = layer_id;
223 
224   std::vector<brec_part_instance_sptr> parts_upper_most(map_instance_[0]);
225   Rtree_type *rtree_upper_most = map_rtree_[0];
226   for (unsigned l = 1; l <= highest; l++) {
227     std::vector<brec_part_instance_sptr> parts_current;
228 
229     extract_upper_layer(parts_upper_most, rtree_upper_most, parts_current, rho_calculation_method, l*radius);
230     std::cout << "extracted " << parts_current.size() << " parts of layer " << l << std::endl;
231 
232     map_instance_[l] = parts_current;
233 
234     auto *rtree_current = new Rtree_type();
235     map_rtree_.insert(std::pair<unsigned, Rtree_type*> (l, rtree_current));
236 
237     for (const auto & i : parts_current) {
238       rtree_current->add(i);
239     }
240 
241     parts_upper_most.clear();
242     parts_upper_most = parts_current;
243 
244     rtree_upper_most = rtree_current;
245   }
246 
247   std::cout << "\textracted " << parts_upper_most.size() << " of highest layer: " << highest << " parts, rtree size: " << rtree_upper_most->size() << std::endl;
248 
249   return true;
250 }
251 
252 // check for existence of upper_p with central_p as its central part and map will tell if all the other parts exist
253 brec_part_instance_sptr
exists(const brec_part_base_sptr & upper_p,const brec_part_instance_sptr & central_p,unsigned,unsigned,Rtree_type * lower_rtree,float det_threshold)254 brec_part_hierarchy_detector::exists(const brec_part_base_sptr& upper_p,
255                                      const brec_part_instance_sptr& central_p, unsigned /*ni*/, unsigned /*nj*/, // FIXME - ni and nj unused
256                                      Rtree_type* lower_rtree,
257                                      float det_threshold)
258 {
259   // first check if types and layers of central_p instance matches with upper_p's info
260   if (upper_p->central_part()->type_ != central_p->type_ || upper_p->layer_ != central_p->layer_ + 1) {
261     std::cout << "central_p instance passed is not compatible with the upper layer part passed\n";
262     return nullptr;
263   }
264 
265   brec_part_instance_sptr pi = new brec_part_instance(upper_p->layer_, upper_p->type_, brec_part_instance_kind::COMPOSED, central_p->x_, central_p->y_, 0.0f);
266   brec_hierarchy_edge_sptr e1 = new brec_hierarchy_edge(pi->cast_to_base(), central_p->cast_to_base(), true);
267   pi->add_outgoing_edge(e1);
268 
269   // now for each other part of upper_p, check whether they exist in the map
270   float cx = central_p->x_; float cy = central_p->y_;
271   auto eit = upper_p->out_edges_begin();
272   eit++;  // skip the central part
273   double strength = 1.0;
274 
275   for ( ; eit != upper_p->out_edges_end(); eit++) {
276     vgl_box_2d<float> probe = (*eit)->get_probe_box(central_p);
277     std::vector<brec_part_instance_sptr> found;
278     lower_rtree->get(probe, found);
279 
280     double best_fit = 0.0;
281     double best_fit_str = 1.0;
282     brec_part_instance_sptr best_part;
283     for (auto & i : found) {
284       if (i->strength_ > det_threshold && i->type_ == (*eit)->target()->type_)
285       {
286         vnl_vector_fixed<float, 2> v(i->x_-cx, i->y_-cy);
287         float dist, angle;
288         (*eit)->calculate_dist_angle(central_p, v, dist, angle);
289         double str = (*eit)->prob_density(dist, angle);
290 
291         if (str < double(det_threshold))
292           continue;
293         if (best_fit < str) {
294           best_fit = str;
295           best_fit_str = i->strength_;
296           best_part = i;
297         }
298       }
299     }
300 
301     if (best_fit <= 0)
302       return nullptr;  // this sub-part not found
303     strength *= best_fit*best_fit_str;
304     if (best_part) {
305       brec_hierarchy_edge_sptr e2 = new brec_hierarchy_edge(pi->cast_to_base(), best_part->cast_to_base(), false);
306       pi->add_outgoing_edge(e2);
307     }
308   }
309   strength *= central_p->strength_;
310 
311   // if all of them have been detected then declare existence at the central parts location
312   pi->strength_ = float(strength);
313 
314   return pi;
315 }
316 
317 //: check for existence of \p upper_p with \p central_p as its central part and map will tell if all the other parts exist
318 //  No thresholding, \return a probabilistic score
319 brec_part_instance_sptr
exists(const brec_part_base_sptr & upper_p,const brec_part_instance_sptr & central_p,Rtree_type * lower_rtree)320 brec_part_hierarchy_detector::exists(const brec_part_base_sptr& upper_p,
321                                      const brec_part_instance_sptr& central_p,
322                                      Rtree_type* lower_rtree)
323 {
324   // first check if types and layers of central_p instance matches with upper_p's info
325   if (upper_p->central_part()->type_ != central_p->type_ || upper_p->layer_ != central_p->layer_ + 1) {
326     std::cout << "central_p instance passed is not compatible with the upper layer part passes\n";
327     return nullptr;
328   }
329 
330   brec_part_instance_sptr pi = new brec_part_instance(upper_p->layer_, upper_p->type_, brec_part_instance_kind::COMPOSED, central_p->x_, central_p->y_, 0.0f);
331   brec_hierarchy_edge_sptr e1 = new brec_hierarchy_edge(pi->cast_to_base(), central_p->cast_to_base(), true);
332   pi->add_outgoing_edge(e1);
333 
334   // now for each other part of upper_p, check whether they exist in the map
335   float cx = central_p->x_; float cy = central_p->y_;
336   auto eit = upper_p->out_edges_begin();
337   eit++;  // skip the central part
338   double strength = 1.0;
339   for ( ; eit != upper_p->out_edges_end(); eit++) {
340     vgl_box_2d<float> probe = (*eit)->get_probe_box(central_p);
341     std::vector<brec_part_instance_sptr> found;
342     lower_rtree->get(probe, found);
343 
344     double best_fit = 0.0;
345     double best_fit_str = 1.0;
346     brec_part_instance_sptr best_part;
347     for (auto & i : found) {
348       if (i->type_ == (*eit)->target()->type_) {
349         vnl_vector_fixed<float, 2> v(i->x_-cx, i->y_-cy);
350         float dist, angle;
351         (*eit)->calculate_dist_angle(central_p, v, dist, angle);
352         double str = (*eit)->prob_density(dist, angle);
353         if (best_fit < str) {
354           best_fit = str;
355           best_fit_str = i->strength_;
356           best_part = i;
357         }
358       }
359     }
360 
361     if (best_fit <= 0 || !best_part)
362       return nullptr;  // this sub-part not found
363 
364     brec_hierarchy_edge_sptr e2 = new brec_hierarchy_edge(pi->cast_to_base(), best_part->cast_to_base(), false);
365     pi->add_outgoing_edge(e2);
366     strength *= best_fit*best_fit_str;
367   }
368   strength *= central_p->strength_;
369 
370   // if all of them have been detected then declare existence at the central parts location
371   pi->strength_ = float(strength);
372 
373   return pi;
374 }
375 
376 //: given a set of detected lower level parts, create a set of instance detections for one layer above in the hierarchy
extract_upper_layer(std::vector<brec_part_instance_sptr> & extracted_parts,unsigned ni,unsigned nj,Rtree_type * extracted_parts_rtree,std::vector<brec_part_instance_sptr> & extracted_upper_parts)377 void brec_part_hierarchy_detector::extract_upper_layer(std::vector<brec_part_instance_sptr>& extracted_parts, unsigned ni, unsigned nj,
378                                                        Rtree_type* extracted_parts_rtree,
379                                                        std::vector<brec_part_instance_sptr>& extracted_upper_parts)
380 {
381   // for each detected part, check for the existence of each upper layer part that uses it as a central part
382   for (const auto& p : extracted_parts) {
383     // find this type in the primitive layer of the hierarchy
384     brec_part_base_sptr hp = h_->get_node(p->layer_, p->type_);
385     if (!hp)
386       continue;
387 
388     // find the all the upper layer parts that use hp as a central part
389     // check the incoming edges of hp
390     for (auto eit = hp->in_edges_begin(); eit != hp->in_edges_end(); eit++) {
391       if (hp == (*eit)->source()->central_part()) {
392         brec_part_base_sptr hp_upper = (*eit)->source();
393 
394         // now check for the existence of other primitives wrt to the central part and initiate an instance of it if so
395         brec_part_instance_sptr hp_upper_instance = exists(hp_upper, p, ni, nj, extracted_parts_rtree, hp_upper->detection_threshold_); // p will be its central part and map will tell if all the other parts exist
396         if (!hp_upper_instance)
397           continue;
398         if (hp_upper_instance->strength_ > hp_upper->detection_threshold_)
399           extracted_upper_parts.push_back(hp_upper_instance);
400       }
401     }
402   }
403 }
404 
405 //: check for existence of \p upper_p with \p central_p as its central part and map will tell if all the other parts exist
406 //  No thresholding, \return a probabilistic score
407 brec_part_instance_sptr
exists_for_training(const brec_part_base_sptr & upper_p,const brec_part_instance_sptr & central_p,Rtree_type * lower_rtree)408 brec_part_hierarchy_detector::exists_for_training(const brec_part_base_sptr& upper_p,
409                                                   const brec_part_instance_sptr& central_p,
410                                                   Rtree_type* lower_rtree)
411 {
412   // first check if types and layers of central_p instance matches with upper_p's info
413   if (upper_p->central_part()->type_ != central_p->type_ || upper_p->layer_ != central_p->layer_ + 1) {
414     std::cout << "central_p instance passed is not compatible with the upper layer part passes\n";
415     return nullptr;
416   }
417 
418   brec_part_instance_sptr pi = new brec_part_instance(upper_p->layer_, upper_p->type_, brec_part_instance_kind::COMPOSED, central_p->x_, central_p->y_, 0.0f);
419   brec_hierarchy_edge_sptr e1 = new brec_hierarchy_edge(pi->cast_to_base(), central_p->cast_to_base(), true);
420   pi->add_outgoing_edge(e1);
421 
422   // now for each other part of upper_p, check whether they exist in the map
423   float cx = central_p->x_; float cy = central_p->y_;
424   auto eit = upper_p->out_edges_begin();
425   eit++;  // skip the central part
426   double rho = 1.0;
427   for ( ; eit != upper_p->out_edges_end(); eit++) {
428     vgl_box_2d<float> probe = (*eit)->get_probe_box(central_p);
429     std::vector<brec_part_instance_sptr> found;
430     lower_rtree->get(probe, found);
431 
432     double best_fit = -100000.0;
433     brec_part_instance_sptr best_part;
434     for (auto & i : found) {
435       if (i->type_ == (*eit)->target()->type_) {
436         vnl_vector_fixed<float, 2> v(i->x_-cx, i->y_-cy);
437         float dist, angle;
438         (*eit)->calculate_dist_angle(central_p, v, dist, angle);
439         double rho = (*eit)->prob_density(dist, angle)*i->rho_c_f_;
440         if (best_fit < rho) {
441           best_fit = rho;
442           best_part = i;
443         }
444       }
445     }
446 
447     if (best_fit <= 0 || !best_part)
448       return nullptr;  // this sub-part not found
449 
450     brec_hierarchy_edge_sptr e2 = new brec_hierarchy_edge(pi->cast_to_base(), best_part->cast_to_base(), false);
451     pi->add_outgoing_edge(e2);
452     rho *= best_fit;
453   }
454   rho *= central_p->rho_c_f_;
455 
456   // if all of them have been detected then declare existence at the central parts location
457   pi->rho_c_f_ = rho;
458   pi->strength_ = float(rho);
459 
460   return pi;
461 }
462 
463 //: check for existence of \p upper_p with \p central_p as its central part and map will tell if all the other parts exist
464 //  No thresholding, \return a probabilistic score
465 brec_part_instance_sptr
exists_using_hierarchies(const brec_part_base_sptr & upper_p,const brec_part_instance_sptr & central_p,Rtree_type * lower_rtree,double radius)466 brec_part_hierarchy_detector::exists_using_hierarchies(const brec_part_base_sptr& upper_p,
467                                                        const brec_part_instance_sptr& central_p,
468                                                        Rtree_type* lower_rtree, double radius)
469 {
470   // first check if types and layers of central_p instance matches with upper_p's info
471   if (upper_p->central_part()->type_ != central_p->type_ || upper_p->layer_ != central_p->layer_ + 1) {
472     std::cout << "central_p instance passed is not compatible with the upper layer part passes\n";
473     return nullptr;
474   }
475 
476   double uniform = 1.0/radius * 1.0/8.0;
477 
478   brec_part_instance_sptr pi = new brec_part_instance(upper_p->layer_, upper_p->type_, brec_part_instance_kind::COMPOSED, central_p->x_, central_p->y_, 0.0f);
479   brec_hierarchy_edge_sptr e1 = new brec_hierarchy_edge(pi->cast_to_base(), central_p->cast_to_base(), true);
480   pi->add_outgoing_edge(e1);
481 
482   // now for each other part of upper_p, check whether they exist in the map
483   float cx = central_p->x_; float cy = central_p->y_;
484 
485   auto eit = upper_p->out_edges_begin();
486   eit++;  // skip the central part
487 
488   float prior_non_c_b = 1.0f - (prior_c_f_ + prior_non_c_f_ + prior_c_b_);
489 
490   double rho_c_f = central_p->rho_c_f_ * prior_c_f_;
491   double rho_c_b = central_p->rho_c_b_ * prior_c_b_;
492   double rho_nc_f = central_p->rho_nc_f_ * prior_non_c_f_;
493   double rho_nc_b = central_p->rho_nc_b_ * prior_non_c_b;
494 
495   for ( ; eit != upper_p->out_edges_end(); eit++) {
496     vgl_box_2d<float> probe = (*eit)->get_probe_box(central_p);
497     std::vector<brec_part_instance_sptr> found;
498     lower_rtree->get(probe, found);
499 
500     double best_score = -100000.0;
501     brec_part_instance_sptr best_part;
502     brec_hierarchy_edge_sptr best_edge;
503     for (auto & i : found) {
504       if (i == central_p)  // skip itself
505         continue;
506       if (i->type_ == (*eit)->target()->type_) {
507         vnl_vector_fixed<float, 2> v(i->x_-cx, i->y_-cy);
508         float dist, angle;
509         (*eit)->calculate_dist_angle(central_p, v, dist, angle);
510         double dens = (*eit)->prob_density(dist, angle);
511         double rho_c_f_i = dens*i->rho_c_f_*rho_c_f;
512         double rho_c_b_i = dens*i->rho_c_b_*rho_c_b;
513         double rho_nc_f_i = uniform*i->rho_nc_f_*rho_nc_f;
514         double rho_nc_b_i = uniform*i->rho_nc_b_*rho_nc_b;
515 
516         double s = std::min(rho_c_f_i/rho_c_b_i,rho_c_f_i/rho_nc_f_i);
517         s = std::min(s, rho_c_f_i/rho_nc_b_i);
518 
519         if (best_score < s) {
520           best_score = s;
521           best_part = i;
522           best_edge = (*eit);
523         }
524       }
525     }
526 
527     if (best_score <= 0 || !best_part)
528       return nullptr;  // this sub-part not found
529 
530     brec_hierarchy_edge_sptr e2 = new brec_hierarchy_edge(pi->cast_to_base(), best_part->cast_to_base(), false);
531     e2->set_model(best_edge->dist_model_, best_edge->angle_model_, best_edge->weight_);
532     pi->add_outgoing_edge(e2);
533   }
534 
535   // now compute the score for the part with a second pass
536   eit = pi->out_edges_begin();
537   eit++;  // skip the central part
538   for ( ; eit != pi->out_edges_end(); eit++) {
539     brec_part_instance_sptr pi2 = (*eit)->target()->cast_to_instance();
540     vnl_vector_fixed<float, 2> v(pi2->x_-cx, pi2->y_-cy);
541     float dist, angle;
542     (*eit)->calculate_dist_angle(central_p, v, dist, angle);
543     double dens = (*eit)->prob_density(dist, angle);
544     rho_c_f *= dens*pi2->rho_c_f_;
545     rho_c_b *= dens*pi2->rho_c_b_;
546     rho_nc_f *= uniform*pi2->rho_nc_f_;
547     rho_nc_b *= uniform*pi2->rho_nc_b_;
548   }
549 
550 #if 0 // OZGE TODO: implement the contributions from the other classes
551   // compute the denominator by locating a part with the same primitives with this one in each hierarchy in the list
552   double sum = 0.0;
553   for (unsigned i = 0; i < class_hierarchies_.size(); i++) {
554     std::vector<double> scores;
555     if (class_hierarchies_[i]->get_score(pi, scores))
556       for (unsigned k = 0; k < scores.size(); k++)
557         sum += scores[k];
558   }
559 #endif // 0
560 
561   // if all of them have been detected then declare existence at the central parts location
562   double den = (rho_c_f+rho_c_b+rho_nc_f+rho_nc_b);
563   pi->rho_c_f_ = rho_c_f/den;
564   pi->rho_c_b_ = rho_c_b/den;
565   pi->rho_nc_f_ = rho_nc_f/den;
566   pi->rho_nc_b_ = rho_nc_b/den;
567 
568   pi->strength_ = float(pi->rho_c_f_);
569 
570   return pi;
571 }
572 
573 
574 //: given a set of detected lower level parts, create a set of instance detections for one layer above in the hierarchy
575 //  No thresholding, \return a probabilistic score
576 //  rho_calculation_method = 0 if probabilistic score
577 //  rho_calculation_method = 1 if training
578 //  rho_calculation_method = 2 if using other hierarchies to compute a posterior
extract_upper_layer(std::vector<brec_part_instance_sptr> & extracted_parts,Rtree_type * extracted_parts_rtree,std::vector<brec_part_instance_sptr> & extracted_upper_parts,unsigned rho_calculation_method,double radius)579 void brec_part_hierarchy_detector::extract_upper_layer(std::vector<brec_part_instance_sptr>& extracted_parts,
580                                                        Rtree_type* extracted_parts_rtree,
581                                                        std::vector<brec_part_instance_sptr>& extracted_upper_parts, unsigned rho_calculation_method, double radius)
582 {
583   // for each detected part, check for the existence of each upper layer part that uses it as a central part
584   for (const auto& p : extracted_parts) {
585     // find this type
586     brec_part_base_sptr hp = h_->get_node(p->layer_, p->type_);
587     if (!hp)
588       continue;
589 
590     if (p->layer_ == 1 && p->x_ == 165 && p->y_ == 189) {
591       std::cout << "here!\n";
592     }
593 
594     // find the all the upper layer parts that use hp as a central part
595     // check the incoming edges of hp
596     for (auto eit = hp->in_edges_begin(); eit != hp->in_edges_end(); eit++) {
597       if ((*eit)->to_central() && hp == (*eit)->source()->central_part()) {
598         brec_part_base_sptr hp_upper = (*eit)->source();
599 
600         // now check for the existence of other primitives wrt to the central part and initiate an instance of it if so
601         brec_part_instance_sptr hp_upper_instance;
602 
603         // p will be its central part and map will tell if all the other parts exist
604         switch (rho_calculation_method) {
605           case brec_detector_methods::POSTERIOR_NUMERATOR : hp_upper_instance = exists(hp_upper, p, extracted_parts_rtree); break;
606           case brec_detector_methods::DENSITY_FOR_TRAINING : hp_upper_instance = exists_for_training(hp_upper, p, extracted_parts_rtree); break;
607           case brec_detector_methods::POSTERIOR : hp_upper_instance = exists_using_hierarchies(hp_upper, p, extracted_parts_rtree, radius); break;
608           default: std::cout << "Warning: unknown brec_detector_method encountered: " << rho_calculation_method << std::endl; break;
609         }
610 
611         if (!hp_upper_instance)
612           continue;
613         extracted_upper_parts.push_back(hp_upper_instance);
614       }
615     }
616   }
617 }
618 
619 //: Binary io, NOT IMPLEMENTED, signatures defined to use brec_part_hierarchy as a brdb_value
vsl_b_write(vsl_b_ostream &,brec_part_hierarchy_detector const &)620 void vsl_b_write(vsl_b_ostream & /*os*/, brec_part_hierarchy_detector const & /*ph*/)
621 {
622   std::cerr << "vsl_b_write() -- Binary io, NOT IMPLEMENTED, signatures defined to use brec_part_hierarchy_learner as a brdb_value\n";
623   return;
624 }
625 
626 //: Binary io, NOT IMPLEMENTED, signatures defined to use brec_part_hierarchy as a brdb_value
vsl_b_read(vsl_b_istream &,brec_part_hierarchy_detector &)627 void vsl_b_read(vsl_b_istream & /*is*/, brec_part_hierarchy_detector & /*ph*/)
628 {
629   std::cerr << "vsl_b_read() -- Binary io, NOT IMPLEMENTED, signatures defined to use brec_part_hierarchy_learner as a brdb_value\n";
630   return;
631 }
632 
vsl_b_read(vsl_b_istream & is,brec_part_hierarchy_detector * ph)633 void vsl_b_read(vsl_b_istream& is, brec_part_hierarchy_detector* ph)
634 {
635   delete ph;
636   bool not_null_ptr;
637   vsl_b_read(is, not_null_ptr);
638   if (not_null_ptr)
639   {
640     brec_part_hierarchy_sptr dummy;
641     ph = new brec_part_hierarchy_detector(dummy);
642     vsl_b_read(is, *ph);
643   }
644   else
645     ph = nullptr;
646 }
647 
vsl_b_write(vsl_b_ostream & os,const brec_part_hierarchy_detector * & ph)648 void vsl_b_write(vsl_b_ostream& os, const brec_part_hierarchy_detector* &ph)
649 {
650   if (ph==nullptr)
651   {
652     vsl_b_write(os, false); // Indicate null pointer stored
653   }
654   else
655   {
656     vsl_b_write(os,true); // Indicate non-null pointer stored
657     vsl_b_write(os,*ph);
658   }
659 }
660