contrib/mul/mbl/mbl_thin_plate_spline_2d.h
Go to the documentation of this file.
00001 // This is mul/mbl/mbl_thin_plate_spline_2d.h
00002 #ifndef mbl_thin_plate_spline_2d_h_
00003 #define mbl_thin_plate_spline_2d_h_
00004 //:
00005 // \file
00006 // \brief Construct thin plate spline to map 2D to 2D
00007 // \author Tim Cootes
00008 
00009 #include <vgl/vgl_point_2d.h>
00010 #include <vnl/vnl_vector.h>
00011 #include <vnl/vnl_matrix.h>
00012 #include <vsl/vsl_binary_io.h>
00013 #include <vcl_vector.h>
00014 #include <vcl_iosfwd.h>
00015 
00016 //=======================================================================
00017 //: Construct thin plate spline to map 2D to 2D.
00018 // I.e. does some mapping (x',y') = f(x,y). (See Booksteins work, e.g. IPMI 1993)
00019 // The warp is `guided' by a set of
00020 // landmarks p(0) .. p(n-1) in the source plane which are to be
00021 // mapped to a (possibly deformed) set q(0)..q(n-1) in the destination.
00022 // Thus the mapping is constrained so that f(p(i)) = q(i) for i = 0..n-1.
00023 // The points are given to the build() function to set up the object.
00024 //
00025 // If one wishes to map a set of source points to multiple target points,
00026 // use set_source_pts(src_pts);  then build(target_pts); for each target set.
00027 //
00028 // \verbatim
00029 // vcl_vector<vgl_point_2d<double> > src_pts(n_points),dest_pts(n_points);
00030 //
00031 // Fill src_pts and dest_pts
00032 // .....
00033 //
00034 // Construct spline object
00035 // mbl_thin_plate_spline_2d tps;
00036 // tps.build(src_pts,dest_pts);
00037 //
00038 // // Apply to point p:
00039 // vgl_point_3d<double> p(1,2);
00040 //
00041 // vgl_point_2d<double> new_p = tps(p);
00042 // \endverbatim
00043 class mbl_thin_plate_spline_2d
00044 {
00045   vnl_vector<double> Wx_,Wy_;
00046   double Ax0_, AxX_, AxY_;
00047   double Ay0_, AyX_, AyY_;
00048   double energy_x_,energy_y_;
00049 
00050   bool return_pure_affine_;
00051 
00052   vcl_vector<vgl_point_2d<double> > src_pts_;
00053 
00054     //: Used to estimate weights in set_source_points()
00055   vnl_matrix<double> L_inv_;
00056 
00057     //: Build from small number of points
00058   void build_pure_affine(const vcl_vector<vgl_point_2d<double> >& source_pts,
00059                          const vcl_vector<vgl_point_2d<double> >& dest_pts);
00060 
00061    //: Set parameters from vectors
00062   void set_params(const vnl_vector<double>& W1,
00063                   const vnl_vector<double>& W2);
00064 
00065   void set_up_rhs(vnl_vector<double>& Bx,
00066                   vnl_vector<double>& By,
00067                   const vcl_vector<vgl_point_2d<double> >& dest_pts);
00068 
00069    //: Compute spline-bending energy
00070   void compute_energy(vnl_vector<double>& W1,
00071                       vnl_vector<double>& W2,
00072                       const vnl_matrix<double>& L);
00073 
00074  public:
00075 
00076     //: Dflt ctor
00077   mbl_thin_plate_spline_2d();
00078 
00079     //: Destructor
00080   virtual ~mbl_thin_plate_spline_2d();
00081 
00082     //: Sets up internal transformation to map source_pts onto dest_pts
00083   void build(const vcl_vector<vgl_point_2d<double> >& source_pts,
00084              const vcl_vector<vgl_point_2d<double> >& dest_pts,
00085              bool compute_the_energy=false);
00086 
00087     //: Define source point positions
00088     //  Performs pre-computations so that build(dest_points) can be
00089     //  called multiple times efficiently
00090   void set_source_pts(const vcl_vector<vgl_point_2d<double> >& source_pts);
00091 
00092   //: Return current source points
00093   const vcl_vector<vgl_point_2d<double> >& src_pts() const
00094   { return src_pts_; }
00095 
00096 
00097     //: Sets up internal transformation to map source_pts onto dest_pts
00098   void build(const vcl_vector<vgl_point_2d<double> >& dest_pts);
00099 
00100        //: Return transformed version of (x,y)
00101   vgl_point_2d<double>  operator()(double x, double y) const;
00102 
00103        //: Return transformed version of (x,y)
00104   vgl_point_2d<double>  operator()(const vgl_point_2d<double>&  p) const
00105   { return operator()(p.x(),p.y()); }
00106 
00107     //: Bending energy of X component (zero for pure affine)
00108     //  A measure of total amount of non-linear deformation
00109   double bendingEnergyX() const { return energy_x_; }
00110 
00111     //: Bending energy of X component (zero for pure affine)
00112     //  A measure of total amount of non-linear deformation
00113   double bendingEnergyY() const { return energy_y_; }
00114 
00115   //:
00116   // If this parameter is set to true, then only global affine part
00117   // of the currently computed transformation is used
00118   void set_pure_affine(bool val) { return_pure_affine_ = val; }
00119 
00120     //: Version number for I/O
00121   short version_no() const;
00122 
00123     //: Print class to os
00124   void print_summary(vcl_ostream& os) const;
00125 
00126     //: Save class to binary file stream
00127   void b_write(vsl_b_ostream& bfs) const;
00128 
00129     //: Load class from binary file stream
00130   void b_read(vsl_b_istream& bfs);
00131 
00132     //: Comparison operator
00133   bool operator==(const mbl_thin_plate_spline_2d& tps) const;
00134 };
00135 
00136   //: Binary file stream output operator for class reference
00137 void vsl_b_write(vsl_b_ostream& bfs, const mbl_thin_plate_spline_2d& b);
00138 
00139   //: Binary file stream input operator for class reference
00140 void vsl_b_read(vsl_b_istream& bfs, mbl_thin_plate_spline_2d& b);
00141 
00142   //: Stream output operator for class reference
00143 vcl_ostream& operator<<(vcl_ostream& os,const mbl_thin_plate_spline_2d& b);
00144 
00145 #endif
00146 
00147