Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

bmrf_node.cxx

Go to the documentation of this file.
00001 // This is brl/bseg/bmrf/bmrf_node.cxx
00002 #include "bmrf_node.h"
00003 //:
00004 // \file
00005 
00006 #include <bmrf/bmrf_arc.h>
00007 #include <bmrf/bmrf_epi_transform.h>
00008 #include <bmrf/bmrf_gamma_func.h>
00009 #include <bmrf/bmrf_epi_seg_compare.h>
00010 #include <vsl/vsl_binary_io.h>
00011 #include <vbl/io/vbl_io_smart_ptr.h>
00012 #include <vcl_algorithm.h>
00013 #include <vcl_cmath.h>
00014 
00015 
00016 //: Constructor
00017 bmrf_node::bmrf_node( const bmrf_epi_seg_sptr& epi_seg, int frame_num,
00018                       double prob )
00019   : segment_(epi_seg), frame_num_(frame_num), probability_(prob),
00020     out_arcs_(), in_arcs_(), boundaries_(ALL+1, out_arcs_.end()), sizes_(ALL,0)
00021 {
00022 }
00023 
00024 //: Copy constructor
00025 bmrf_node::bmrf_node(bmrf_node const& n)
00026   : vbl_ref_count(),
00027     segment_(n.segment_), frame_num_(n.frame_num_), probability_(n.probability_),
00028     out_arcs_(n.out_arcs_), in_arcs_(n.in_arcs_), boundaries_(n.boundaries_), sizes_(n.sizes_)
00029 {
00030 }
00031 
00032 //: Strip all of the arcs from this node
00033 void
00034 bmrf_node::strip()
00035 {
00036   for (int t = 0; t<ALL; ++t)
00037     for (arc_iterator itr = boundaries_[t]; itr != boundaries_[t+1]; )
00038     {
00039       arc_iterator next_itr = itr; ++next_itr;
00040       remove_helper(itr, neighbor_type(t));
00041       itr = next_itr;
00042     }
00043 
00044   for (arc_iterator itr = in_arcs_.begin(); itr != in_arcs_.end(); ++itr)
00045     if ((*itr)->from_)
00046       (*(itr--))->from_->remove_neighbor(this, ALL);
00047 }
00048 
00049 
00050 //: Remove any arcs to or from NULL nodes
00051 bool
00052 bmrf_node::purge()
00053 {
00054   bool retval = false;
00055   for (int t = 0; t<ALL; ++t)
00056   {
00057     for (arc_iterator itr = boundaries_[t]; itr != boundaries_[t+1]; ++itr) {
00058       if (!(*itr)->to_) {
00059         // adjust boundaries if necessary
00060         for (int t2=t; t2>=0 && (boundaries_[t2] == itr); --t2)
00061           ++boundaries_[t2];
00062         out_arcs_.erase(itr--); // remove the arc
00063         --sizes_[t]; // decrease count
00064         retval = true;
00065       }
00066     }
00067   }
00068 
00069   for (arc_iterator itr = in_arcs_.begin(); itr != in_arcs_.end(); ++itr) {
00070     if (!(*itr)->from_) {
00071       in_arcs_.erase(itr--);
00072       retval = true;
00073     }
00074   }
00075 
00076   // Invalidate the probability
00077   this->probability_ = -1.0;
00078 
00079   return retval;
00080 }
00081 
00082 
00083 //: Return the probability of this node
00084 double
00085 bmrf_node::probability()
00086 {
00087   if (probability_ < 0.0)
00088     compute_probability();
00089 
00090   return probability_;
00091 }
00092 
00093 
00094 //: Return the gamma funtion of this node
00095 bmrf_gamma_func_sptr
00096 bmrf_node::gamma()
00097 {
00098   if (!gamma_.ptr())
00099     compute_probability();
00100 
00101   return gamma_;
00102 }
00103 
00104 
00105 static bool
00106 pair_dbl_arc_gt_cmp ( const vcl_pair<double,bmrf_node::arc_iterator>& lhs,
00107                       const vcl_pair<double,bmrf_node::arc_iterator>& rhs )
00108 {
00109   return lhs.first > rhs.first;
00110 }
00111 
00112 //: Compute the conditional probability that this node is correct given its neighbors
00113 void
00114 bmrf_node::compute_probability()
00115 {
00116   probability_ = 0.0;
00117   double sum = 0.0;
00118   for ( arc_iterator a_itr = this->begin(TIME);
00119         a_itr != this->end(TIME); ++a_itr )
00120   {
00121     // use the gamma function associated with the arc
00122     bmrf_gamma_func_sptr gamma_func = (*a_itr)->gamma_func();
00123     (*a_itr)->probability_ = this->probability(gamma_func, -1)
00124                             *this->probability(gamma_func, 1);
00125 
00126     sum += (*a_itr)->probability_;
00127     // select the probability of the best neighbor
00128     if ( (*a_itr)->probability_ > probability_ ) {
00129       probability_ = (*a_itr)->probability_;
00130       gamma_ = gamma_func;
00131     }
00132   }
00133   probability_ /= sum;
00134   // Normalize so probabilities sum to 1
00135   for ( arc_iterator a_itr = this->begin(TIME);
00136         a_itr != this->end(TIME); ++a_itr )
00137   {
00138     (*a_itr)->probability_ /= sum;
00139   }
00140 }
00141 
00142 
00143 //: Prune neighbors with a probability below \p threshold
00144 void
00145 bmrf_node::prune_by_probability(double threshold, bool relative)
00146 {
00147   // Compute a probability mass function
00148   vcl_vector<vcl_pair<double,arc_iterator> > pmf;
00149   for ( arc_iterator a_itr = this->begin(TIME);
00150         a_itr != this->end(TIME); ++a_itr )
00151   {
00152     // use the gamma function associated with the arc
00153     bmrf_gamma_func_sptr gamma_func = (*a_itr)->gamma_func();
00154     pmf.push_back(vcl_pair<double,arc_iterator>( this->probability(gamma_func,-1)
00155                                                  *this->probability(gamma_func,1), a_itr));
00156   }
00157 
00158   // Sort the results by probability
00159   vcl_sort(pmf.begin(), pmf.end(), pair_dbl_arc_gt_cmp);
00160 
00161   // if relative, modify the threshold relative to the maximum probability
00162   if ( relative )
00163     threshold *= pmf.front().first;
00164 
00165   // Remove arcs to neighbors that are below threshold
00166   vcl_vector<vcl_pair<double,arc_iterator> >::iterator p_itr = pmf.begin();
00167   while ( p_itr != pmf.end() && p_itr->first > threshold)  ++p_itr;
00168   for ( ; p_itr != pmf.end(); ++p_itr ) {
00169     remove_helper(p_itr->second, TIME);
00170   }
00171 }
00172 
00173 
00174 //: Prune neighbors with a gamma outside this range
00175 void
00176 bmrf_node::prune_by_gamma(double min_gamma, double max_gamma)
00177 {
00178   for ( arc_iterator a_itr = this->begin(TIME);
00179         a_itr != this->end(TIME);)
00180   {
00181     double gamma = (*a_itr)->induced_gamma();
00182 
00183     arc_iterator next_itr = a_itr;
00184     ++next_itr;
00185     if ( gamma < min_gamma || gamma > max_gamma ){
00186       remove_helper(a_itr, TIME);
00187     }
00188     a_itr = next_itr;
00189   }
00190 }
00191 
00192 
00193 //: Prune directed arcs leaving only arcs to nodes which have arcs back to this node
00194 void
00195 bmrf_node::prune_directed()
00196 {
00197   for (int t = 0; t<ALL; ++t){
00198     for (arc_iterator o_itr = boundaries_[t]; o_itr != boundaries_[t+1]; ) {
00199       bool found = false;
00200       for ( arc_iterator i_itr = in_arcs_.begin();
00201             i_itr != in_arcs_.end(); ++i_itr )
00202         if ( (*i_itr)->from_ == (*o_itr)->to_ ){
00203           found = true;
00204           break;
00205         }
00206       if (!found){
00207         arc_iterator next_itr = o_itr;
00208         ++next_itr;
00209         remove_helper(o_itr, neighbor_type(t));
00210         o_itr = next_itr;
00211       }
00212       else
00213         ++o_itr;
00214     }
00215   }
00216 }
00217 
00218 
00219 //: Calculate the error in similarity between this transformed by \p xform
00220 double
00221 bmrf_node::probability(const bmrf_gamma_func_sptr& gamma, int time_step)
00222 {
00223   // precompute the transformed segment 
00224   bmrf_epi_seg_sptr trans_seg = bmrf_epi_transform(this->epi_seg(), gamma, time_step);
00225   double prob = 0.0;
00226   double total_alpha = 0.0;
00227   for ( arc_iterator a_itr = this->begin(TIME); a_itr != this->end(TIME); ++a_itr ) {
00228     if((*a_itr)->time_step() != time_step)
00229       continue;
00230 
00231     bmrf_node_sptr neighbor = (*a_itr)->to();
00232     double error = bmrf_match_error(trans_seg, neighbor->epi_seg());
00233 
00234     double alpha_range = (*a_itr)->max_alpha_ - (*a_itr)->min_alpha_;
00235     const double int_var = 0.001; // intensity variance
00236     prob += alpha_range * vcl_exp(-error/2.0 - (*a_itr)->avg_intensity_error_/(2.0*int_var));
00237     total_alpha += alpha_range;
00238   }
00239 
00240   // no neighbors found in this frame
00241   if(total_alpha == 0.0)
00242     return 1.0;
00243 
00244   return (prob / total_alpha);
00245 }
00246 
00247 
00248 //: Add \p node as a neighbor of type \p type
00249 bool
00250 bmrf_node::add_neighbor( const bmrf_node_sptr& node, neighbor_type type )
00251 {
00252   if (!node || node == this || type == ALL)
00253     return false;
00254 
00255   // verify that this arc is not already present
00256   for (arc_iterator itr = boundaries_[type]; itr != boundaries_[type+1]; ++itr)
00257     if ((*itr)->to_ == node) return false;
00258 
00259   // add the arc
00260   bmrf_arc_sptr new_arc = new bmrf_arc(this, node);
00261   out_arcs_.insert(boundaries_[type+1], new_arc);
00262   node->in_arcs_.push_back(new_arc);
00263   ++sizes_[type];
00264 
00265   // adjust boundaries if necessary
00266   for (int t=type; t>=0 && (boundaries_[type+1] == boundaries_[t]); --t)
00267     --boundaries_[t];
00268 
00269   // Invalidate the probability
00270   this->probability_ = -1.0;
00271 
00272   return true;
00273 }
00274 
00275 
00276 //: Add an arc \p arc of type \p type
00277 bool
00278 bmrf_node::add_arc( const bmrf_arc_sptr& arc, neighbor_type type )
00279 {
00280   if ( !arc.ptr() || arc->from_ != this || arc->to_ == this || type == ALL)
00281     return false;
00282 
00283   // verify that this arc is not already present
00284   for (arc_iterator itr = boundaries_[type]; itr != boundaries_[type+1]; ++itr)
00285     if ((*itr)->to_ == arc->to_) return false;
00286 
00287   out_arcs_.insert(boundaries_[type+1], arc);
00288   arc->to_->in_arcs_.push_back(arc);
00289   ++sizes_[type];
00290 
00291   // adjust boundaries if necessary
00292   for (int t=type; t>=0 && (boundaries_[type+1] == boundaries_[t]); --t)
00293     --boundaries_[t];
00294 
00295   // Invalidate the probability
00296   this->probability_ = -1.0;
00297 
00298   return true;
00299 }
00300 
00301 
00302 //: Remove \p node from the neighborhood
00303 bool
00304 bmrf_node::remove_neighbor( bmrf_node_sptr node, neighbor_type type )
00305 {
00306   if (!node || node == this)
00307     return false;
00308 
00309   bool removed = false;
00310   int init_t = type;
00311   if (type == ALL) init_t=0;
00312 
00313   for (int t = init_t; t<ALL; ++t)
00314   {
00315     for (arc_iterator itr = boundaries_[t]; itr != boundaries_[t+1]; ++itr) {
00316       if ((*itr)->to_ == node) {
00317         arc_iterator prev_itr = itr; --prev_itr;
00318         remove_helper(itr, neighbor_type(t));
00319         itr = prev_itr;
00320         if (type != ALL) return true;
00321         removed = true;
00322       }
00323     }
00324   }
00325 
00326   return removed;
00327 }
00328 
00329 
00330 //: Remove the arc associated with the outgoing iterator
00331 bool
00332 bmrf_node::remove_helper( arc_iterator& a_itr, neighbor_type type)
00333 {
00334   bmrf_arc_sptr arc = *a_itr;
00335   if ( arc->from_ != this )
00336     return false;
00337 
00338   // adjust boundaries if necessary
00339   for (int t=int(type); t>=0 && (boundaries_[t] == a_itr); --t)
00340     ++boundaries_[t];
00341 
00342   // find the pointer back from the other node
00343   arc_iterator back_itr = vcl_find( (*a_itr)->to_->in_arcs_.begin(),
00344                                     (*a_itr)->to_->in_arcs_.end(),
00345                                     *a_itr );
00346 
00347   // erase the pointer back from the other node
00348   if (back_itr != (*a_itr)->to_->in_arcs_.end())
00349       (*a_itr)->to_->in_arcs_.erase(back_itr);
00350 
00351   // erase the arc
00352   out_arcs_.erase(a_itr);
00353 
00354   // decrease count
00355   --sizes_[type];
00356 
00357   // Make these pointers NULL in case someone else still has
00358   // a pointer to this arc
00359   arc->to_ = NULL;
00360   arc->from_ = NULL;
00361 
00362   this->probability_ = -1.0;
00363 
00364   return true;
00365 }
00366 
00367 
00368 //: Returns an iterator to the beginning of the type \p type neighbors
00369 bmrf_node::arc_iterator
00370 bmrf_node::begin( neighbor_type type )
00371 {
00372   if (type == ALL) return out_arcs_.begin();
00373   return boundaries_[type];
00374 }
00375 
00376 
00377 //: Returns an iterator to the end of the type \p type neighbors
00378 bmrf_node::arc_iterator
00379 bmrf_node::end( neighbor_type type )
00380 {
00381   if (type == ALL) return out_arcs_.end();
00382   return boundaries_[type+1];
00383 }
00384 
00385 
00386 //: Returns the number of outgoing neighbors to this node of type \p type
00387 int
00388 bmrf_node::num_neighbors( neighbor_type type )
00389 {
00390   if (type == ALL) return out_arcs_.size();
00391   return sizes_[type];
00392 }
00393 
00394 
00395 //: Binary save self to stream.
00396 void
00397 bmrf_node::b_write( vsl_b_ostream& os ) const
00398 {
00399   vsl_b_write(os, version());
00400 
00401   vsl_b_write(os, this->segment_);
00402   vsl_b_write(os, this->frame_num_);
00403   vsl_b_write(os, this->probability_);
00404 
00405   // write the number of nodes of each type
00406   for (int t=0; t<ALL; ++t)
00407     vsl_b_write(os, sizes_[t]);
00408 
00409   // write all the outgoing arcs
00410   for (vcl_list<bmrf_arc_sptr>::const_iterator itr = out_arcs_.begin();
00411        itr != out_arcs_.end(); ++itr) {
00412     vsl_b_write(os, *itr);  // Save the arc
00413   }
00414 
00415   // write the number of incoming arcs
00416   vsl_b_write(os, (unsigned int) in_arcs_.size());
00417   // write all the incoming arcs
00418   for (vcl_list<bmrf_arc_sptr>::const_iterator itr = in_arcs_.begin();
00419        itr != in_arcs_.end(); ++itr) {
00420     vsl_b_write(os, *itr);  // Save the arc
00421   }
00422 }
00423 
00424 
00425 //: Binary load self from stream.
00426 void
00427 bmrf_node::b_read( vsl_b_istream& is )
00428 {
00429   if (!is) return;
00430 
00431   short ver;
00432   vsl_b_read(is, ver);
00433   switch (ver)
00434   {
00435    case 1:
00436    {
00437     vsl_b_read(is, this->segment_);
00438     vsl_b_read(is, this->frame_num_);
00439     vsl_b_read(is, this->probability_);
00440 
00441     out_arcs_.clear();
00442     boundaries_.clear();
00443     boundaries_.resize(ALL+1, out_arcs_.end());
00444 
00445     int num_neighbors = 0;
00446     for (int t=0; t<ALL; ++t) {
00447       vsl_b_read(is, sizes_[t]);
00448       num_neighbors += sizes_[t];
00449     }
00450     int type = 0;
00451     int b_loc = sizes_[0];
00452     for (int n=0; n<num_neighbors; ++n) {
00453       bmrf_arc_sptr arc_ptr;
00454       vsl_b_read(is, arc_ptr);
00455       arc_ptr->from_ = this;
00456       if (arc_ptr->to_)
00457         arc_ptr->time_init();
00458       out_arcs_.push_back(arc_ptr);
00459 
00460       while (type < ALL && n == b_loc) {
00461         boundaries_[++type] = out_arcs_.end();
00462         --boundaries_[type];
00463         b_loc += sizes_[type];
00464       }
00465     }
00466     boundaries_[0] = out_arcs_.begin();
00467 
00468     unsigned int num_incoming;
00469     vsl_b_read(is, num_incoming);
00470     for (unsigned int n=0; n<num_incoming; ++n) {
00471       bmrf_arc_sptr arc_ptr;
00472       vsl_b_read(is, arc_ptr);
00473       arc_ptr->to_ = this;
00474       if (arc_ptr->from_)
00475         arc_ptr->time_init();
00476       in_arcs_.push_back(arc_ptr);
00477     }
00478     break;
00479    }
00480 
00481    default:
00482     vcl_cerr << "I/O ERROR: bmrf_node::b_read(vsl_b_istream&)\n"
00483              << "           Unknown version number "<< ver << '\n';
00484     is.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00485     return;
00486   }
00487 }
00488 
00489 
00490 //: Return IO version number;
00491 short
00492 bmrf_node::version() const
00493 {
00494   return 1;
00495 }
00496 
00497 
00498 //: Print an ascii summary to the stream
00499 void
00500 bmrf_node::print_summary( vcl_ostream& os ) const
00501 {
00502   os << "pr=" << probability_ << ", frame=" << frame_num_;
00503 }
00504 
00505 
00506 //-----------------------------------------------------------------------------------------
00507 // External functions
00508 //-----------------------------------------------------------------------------------------
00509 
00510 //: Binary save bmrf_node to stream.
00511 void
00512 vsl_b_write(vsl_b_ostream &os, const bmrf_node* n)
00513 {
00514   if (n==0) {
00515     vsl_b_write(os, false); // Indicate null pointer stored
00516   }
00517   else{
00518     vsl_b_write(os,true); // Indicate non-null pointer stored
00519     n->b_write(os);
00520   }
00521 }
00522 
00523 
00524 //: Binary load bmrf_node from stream.
00525 void
00526 vsl_b_read(vsl_b_istream &is, bmrf_node* &n)
00527 {
00528   delete n;
00529   bool not_null_ptr;
00530   vsl_b_read(is, not_null_ptr);
00531   if (not_null_ptr) {
00532     n = new bmrf_node();
00533     n->b_read(is);
00534   }
00535   else
00536     n = 0;
00537 }
00538 
00539 
00540 //: Print an ASCII summary to the stream
00541 void
00542 vsl_print_summary(vcl_ostream &os, const bmrf_node* n)
00543 {
00544   os << "bmrf_node{ ";
00545   n->print_summary(os);
00546   os << " }";
00547 }
00548 

Generated on Thu Jan 10 14:51:53 2008 for contrib/brl/bseg/bmrf by  doxygen 1.4.4