contrib/mul/mfpf/mfpf_prune_overlaps.cxx
Go to the documentation of this file.
00001 #include "mfpf_prune_overlaps.h"
00002 //:
00003 // \file
00004 // \brief Function to remove any overlapping matching responses
00005 // \author Tim Cootes
00006 
00007 #include <mbl/mbl_index_sort.h>
00008 
00009 //: Find list of poses overlapping given pose
00010 void mfpf_find_overlaps(mfpf_point_finder& pf,
00011                         const vcl_vector<mfpf_pose>& poses,
00012                         const mfpf_pose& pose,
00013                         vcl_vector<unsigned>& overlaps)
00014 {
00015   overlaps.resize(0);
00016   for (unsigned i=0;i<poses.size();++i)
00017   {
00018     if (pf.overlap(poses[i],pose))
00019       overlaps.push_back(i);
00020   }
00021 }
00022 
00023 //: If pose not near any poses in list, return false
00024 //  If it is near one, and its fit is better, then replace it.
00025 //  Uses pf.overlap() function to check for proximity
00026 bool mfpf_find_near_pose(mfpf_point_finder& pf,
00027                          vcl_vector<mfpf_pose>& poses,
00028                          vcl_vector<double>& fits,
00029                          const mfpf_pose& pose, double fit)
00030 {
00031   vcl_vector<unsigned> index;
00032   mfpf_find_overlaps(pf,poses,pose,index);
00033   if (index.size()==0) return false;  // No overlaps
00034 
00035   if (index.size()==1)
00036   {
00037     // Only overlaps with a single pose
00038     // Replace that pose if new one is better
00039     if (fits[index[0]]>fit)
00040     {
00041       poses[index[0]]=pose;
00042       fits[index[0]]=fit;
00043     }
00044     return true;
00045   }
00046 
00047   // More complicated situation
00048   // We have more than one overlapping pose
00049   // If new one is worse than all of them, ignore it.
00050   // If new one is better than all of them, replace them all
00051   // Otherwise we have a potentially ambiguous situation
00052   // eg three overlapping objects in a row A-B-C with A not
00053   // overlapping with C, but f(A)<f(B)<f(C)
00054   // In this case eliminate all overlapping poses except the best one.
00055   // There's a danger that this might loose some weaker local
00056   // minima, so perhaps revise this later.
00057 
00058   // Count the number of overlaps with worse fit
00059   // and record best fit
00060   unsigned n_worse=0;
00061   double best_fit = fit;
00062   unsigned best_i = 0;
00063   for (unsigned i=0;i<index.size();++i)
00064   {
00065     if (fits[index[i]]>fit) { n_worse++;}
00066     if (fits[index[i]]<best_fit)
00067     { best_i=index[i]; best_fit=fits[index[i]]; }
00068   }
00069 
00070   if (n_worse==0) return true; // New pose no better than any existing
00071 
00072   // Have to generate new lists
00073   vcl_vector<mfpf_pose> poses0=poses;
00074   vcl_vector<double> fits0=fits;
00075   unsigned n1 = poses.size()+1-index.size();
00076   poses.resize(n1);
00077   fits.resize(n1);
00078   unsigned j=0;
00079   // First add all poses which don't overlap with new pose
00080   for (unsigned i=0;i<poses0.size();++i)
00081   {
00082     if (!pf.overlap(poses0[i],pose))
00083     {
00084       poses[j]=poses0[i];
00085       fits[j]=fits0[i];
00086       ++j;
00087     }
00088   }
00089   if (n_worse==index.size())
00090   {
00091     // New one better than all overlaps
00092     poses[j]=pose;  fits[j]=fit;
00093   }
00094   else
00095   {
00096     // Retain best fit
00097     poses[j]=poses0[best_i]; fits[j]=best_fit;
00098   }
00099   return true;
00100 }
00101 
00102 
00103 //: Remove any overlapping matching responses (retaining best fit)
00104 void mfpf_prune_overlaps(mfpf_point_finder& pf,
00105                          vcl_vector<mfpf_pose>& poses,
00106                          vcl_vector<double>& fits)
00107 {
00108   vcl_vector<mfpf_pose> poses0 = poses;
00109   vcl_vector<double> fits0 = fits;
00110 
00111   poses.resize(0); fits.resize(0);
00112 
00113   for (unsigned i=0;i<poses0.size();++i)
00114   {
00115     if (!mfpf_find_near_pose(pf,poses,fits,poses0[i],fits0[i]))
00116     {
00117       // Pose distinct
00118       poses.push_back(poses0[i]);
00119       fits.push_back(fits0[i]);
00120     }
00121   }
00122 }
00123 
00124 //: Return true if pose overlaps with any of poses
00125 bool mfpf_any_overlaps(mfpf_point_finder& pf,
00126                        const vcl_vector<mfpf_pose>& poses,
00127                        const mfpf_pose& pose)
00128 {
00129   for (unsigned i=0;i<poses.size();++i)
00130   {
00131     if (pf.overlap(poses[i],pose)) return true;
00132   }
00133   return false;
00134 }
00135 
00136 
00137 //:  Sort responses and return list of non-overlapping responses
00138 //  If max_n>0 then return at most max_n
00139 void mfpf_prune_and_sort_overlaps(mfpf_point_finder& pf,
00140                                   vcl_vector<mfpf_pose>& poses,
00141                                   vcl_vector<double>& fits,
00142                                   unsigned max_n)
00143 {
00144   vcl_vector<mfpf_pose> poses0 = poses;
00145   vcl_vector<double> fits0 = fits;
00146 
00147   poses.resize(0); fits.resize(0);
00148 
00149   vcl_vector<int> index;
00150   mbl_index_sort(fits0,index);
00151   for (unsigned i=0;i<index.size();++i)
00152   {
00153     if (!mfpf_any_overlaps(pf,poses,poses0[index[i]]))
00154     {
00155       poses.push_back(poses0[index[i]]);
00156       fits.push_back(fits0[index[i]]);
00157     }
00158     if (max_n>0 && poses.size()>=max_n) return;
00159   }
00160 }
00161