contrib/mul/mfpf/mfpf_profile_pdf.cxx
Go to the documentation of this file.
00001 #include "mfpf_profile_pdf.h"
00002 //:
00003 // \file
00004 // \brief Searches along a profile using a statistical model.
00005 // \author Tim Cootes
00006 
00007 #include <vsl/vsl_binary_loader.h>
00008 #include <vcl_cmath.h> // for std::abs
00009 
00010 #include <vimt/vimt_sample_profile_bilin.h>
00011 #include <vnl/io/vnl_io_vector.h>
00012 #include <vnl/vnl_vector_ref.h>
00013 #include <vgl/vgl_point_2d.h>
00014 #include <vgl/vgl_vector_2d.h>
00015 
00016 #include <mfpf/mfpf_norm_vec.h>
00017 
00018 
00019 //=======================================================================
00020 // Dflt ctor
00021 //=======================================================================
00022 
00023 mfpf_profile_pdf::mfpf_profile_pdf()
00024 {
00025   set_defaults();
00026 }
00027 
00028 //: Define default values
00029 void mfpf_profile_pdf::set_defaults()
00030 {
00031   step_size_=1.0;
00032   ilo_=1; ihi_=0;
00033   search_ni_=5;
00034 }
00035 
00036 //=======================================================================
00037 // Destructor
00038 //=======================================================================
00039 
00040 mfpf_profile_pdf::~mfpf_profile_pdf()
00041 {
00042 }
00043 
00044 //: Define filter kernel to search with
00045 void mfpf_profile_pdf::set(int ilo, int ihi, const vpdfl_pdf_base& pdf)
00046 {
00047   ilo_=ilo;
00048   ihi_=ihi;
00049   pdf_=pdf.clone();
00050 }
00051 
00052 //: Radius of circle containing modelled region
00053 double mfpf_profile_pdf::radius() const
00054 {
00055   return vcl_max(vcl_abs(ilo_),vcl_abs(ihi_));
00056 }
00057 
00058 //: Evaluate match at p, using u to define scale and orientation
00059 // Returns -1*edge strength at p along direction u
00060 double mfpf_profile_pdf::evaluate(const vimt_image_2d_of<float>& image,
00061                                   const vgl_point_2d<double>& p,
00062                                   const vgl_vector_2d<double>& u)
00063 {
00064   int n=1+ihi_-ilo_;
00065   vnl_vector<double> v(n*image.image().nplanes());
00066   vgl_vector_2d<double> u1=step_size_*u;
00067 
00068   const vgl_point_2d<double> p0 = p+ilo_*u1;
00069   vimt_sample_profile_bilin(v,image,p0,u1,n);
00070   mfpf_norm_vec(v);
00071   return -1*pdf().log_p(v);
00072 }
00073 
00074    //: Evaluate match at in a region around p
00075    // Returns a quality of fit at a set of positions.
00076    // response image (whose size and transform is set inside the
00077    // function), indicates the points at which the function was
00078    // evaluated.  response(i,j) is the fit at the point
00079 // response.world2im().inverse()(i,j).  The world2im() transformation
00080 // may be affine.
00081 void mfpf_profile_pdf::evaluate_region(
00082                         const vimt_image_2d_of<float>& image,
00083                         const vgl_point_2d<double>& p,
00084                         const vgl_vector_2d<double>& u,
00085                         vimt_image_2d_of<double>& response)
00086 {
00087   int n=1+2*search_ni_;
00088   int ns = 2*search_ni_ + 1+ ihi_-ilo_;
00089   unsigned nv = pdf().n_dims();
00090   unsigned np=image.image().nplanes();
00091   vnl_vector<double> sample(ns*np);
00092   vgl_vector_2d<double> u1=step_size_*u;
00093   const vgl_point_2d<double> p0 = p+(ilo_-search_ni_)*u1;
00094   vimt_sample_profile_bilin(sample,image,p0,u1,ns);
00095   response.image().set_size(n,1);
00096   double* r = response.image().top_left_ptr();
00097   double* sam=sample.data_block();
00098   vnl_vector<double> v;
00099   for (int i=0;i<n;++i,++r,sam+=np)
00100   {
00101     v=vnl_vector_ref<double>(nv,sam);
00102     mfpf_norm_vec(v);
00103     *r = -1*pdf().log_p(v);
00104   }
00105 
00106   // Set up transformation parameters
00107 
00108   // Point (i,j) in dest corresponds to p1+i.u+j.v,
00109   // an affine transformation for image to world
00110   const vgl_point_2d<double> p1 = p-search_ni_*u1;
00111 
00112   vimt_transform_2d i2w;
00113   i2w.set_similarity(vgl_point_2d<double>(u1.x(),u1.y()),p1);
00114   response.set_world2im(i2w.inverse());
00115 }
00116 
00117    //: Search given image around p, using u to define scale and orientation
00118    //  On exit, new_p defines position of
00119    //  the best nearby match.
00120    //  Returns a quality of fit measure at that
00121    //  point (the smaller the better).
00122 double mfpf_profile_pdf::search_one_pose(
00123                                 const vimt_image_2d_of<float>& image,
00124                                 const vgl_point_2d<double>& p,
00125                                 const vgl_vector_2d<double>& u,
00126                                 vgl_point_2d<double>& new_p)
00127 {
00128   int n=1+2*search_ni_;
00129   int ns = 2*search_ni_ + 1+ ihi_-ilo_;
00130   unsigned nv = pdf().n_dims();
00131   unsigned np=image.image().nplanes();
00132   vnl_vector<double> sample(ns*np);
00133   vgl_vector_2d<double> u1=step_size_*u;
00134   const vgl_point_2d<double> p0 = p+(ilo_-search_ni_)*u1;
00135   vimt_sample_profile_bilin(sample,image,p0,u1,ns);
00136   double* sam=sample.data_block();
00137   vnl_vector<double> v=vnl_vector_ref<double>(nv,sam);
00138   mfpf_norm_vec(v);
00139 
00140   int best_i=0;
00141   double best_r = pdf().log_p(v);
00142   sam+=np;  // Move to next point
00143   for (int i=1;i<n;++i,sam+=np)
00144   {
00145     v=vnl_vector_ref<double>(nv,sam);
00146     mfpf_norm_vec(v);
00147     double r = pdf().log_p(v);
00148 
00149     if (r>best_r) { best_r=r; best_i=i; }
00150   }
00151   new_p = p+(best_i-search_ni_)*u1;
00152   return -1.0 * best_r;
00153 }
00154 
00155 //: Generate points in ref frame that represent boundary
00156 //  Points of a contour around the shape.
00157 //  Used for display purposes.
00158 void mfpf_profile_pdf::get_outline(vcl_vector<vgl_point_2d<double> >& pts) const
00159 {
00160   pts.resize(2);
00161   pts[0]=vgl_point_2d<double>(ilo_-0.5,0);
00162   pts[1]=vgl_point_2d<double>(ihi_+0.5,0);
00163 }
00164 
00165 
00166 //=======================================================================
00167 // Method: is_a
00168 //=======================================================================
00169 
00170 vcl_string mfpf_profile_pdf::is_a() const
00171 {
00172   return vcl_string("mfpf_profile_pdf");
00173 }
00174 
00175 //: Create a copy on the heap and return base class pointer
00176 mfpf_point_finder* mfpf_profile_pdf::clone() const
00177 {
00178   return new mfpf_profile_pdf(*this);
00179 }
00180 
00181 //=======================================================================
00182 // Method: print
00183 //=======================================================================
00184 
00185 void mfpf_profile_pdf::print_summary(vcl_ostream& os) const
00186 {
00187   os<< "{  size: [" << ilo_ << ',' << ihi_<< ']'
00188     << " PDF: ";
00189   if (pdf_.ptr()==0) os << "--";
00190   else               os << pdf_;
00191   mfpf_point_finder::print_summary(os);
00192   os << " }";
00193 }
00194 
00195 //: Version number for I/O
00196 short mfpf_profile_pdf::version_no() const
00197 {
00198   return 1;
00199 }
00200 
00201 void mfpf_profile_pdf::b_write(vsl_b_ostream& bfs) const
00202 {
00203   vsl_b_write(bfs,version_no());
00204   mfpf_point_finder::b_write(bfs);  // Save base class
00205   vsl_b_write(bfs,ilo_);
00206   vsl_b_write(bfs,ihi_);
00207   vsl_b_write(bfs,pdf_);
00208 }
00209 
00210 //=======================================================================
00211 // Method: load
00212 //=======================================================================
00213 
00214 void mfpf_profile_pdf::b_read(vsl_b_istream& bfs)
00215 {
00216   if (!bfs) return;
00217   short version;
00218   vsl_b_read(bfs,version);
00219   switch (version)
00220   {
00221     case (1):
00222       mfpf_point_finder::b_read(bfs);  // Load in base class
00223       vsl_b_read(bfs,ilo_);
00224       vsl_b_read(bfs,ihi_);
00225       vsl_b_read(bfs,pdf_);
00226       break;
00227     default:
00228       vcl_cerr << "I/O ERROR: vsl_b_read(vsl_b_istream&)\n"
00229                << "           Unknown version number "<< version << vcl_endl;
00230       bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00231       return;
00232   }
00233 }
00234 
00235 //: Test equality
00236 bool mfpf_profile_pdf::operator==(const mfpf_profile_pdf& nc) const
00237 {
00238   if (!base_equality(nc)) return false;
00239   if (ilo_!=nc.ilo_) return false;
00240   if (ihi_!=nc.ihi_) return false;
00241   // Doesn't check pdf, though it should.
00242   return true;
00243 }
00244