contrib/mul/mfpf/mfpf_point_finder.h
Go to the documentation of this file.
00001 #ifndef mfpf_point_finder_h_
00002 #define mfpf_point_finder_h_
00003 //:
00004 // \file
00005 // \brief Base for classes which locate feature points
00006 // \author Tim Cootes
00007 
00008 #include <vimt/vimt_image_2d_of.h>
00009 #include <vgl/vgl_point_2d.h>
00010 #include <vgl/vgl_vector_2d.h>
00011 
00012 #include <mfpf/mfpf_pose.h>
00013 #include <vxl_config.h>  // For vxl_byte
00014 
00015 #include <vsl/vsl_binary_io.h>
00016 #include <vcl_string.h>
00017 #include <vcl_iosfwd.h>
00018 
00019 class vimt_image_pyramid;
00020 
00021 //: Base for classes which locate feature points
00022 //  The object will be set up by an
00023 //  associated mfpf_point_finder_builder object
00024 class mfpf_point_finder
00025 {
00026  protected:
00027   //: Size of step between sample points
00028   double step_size_;
00029 
00030   //: Number of points either side of centre to search
00031   int search_ni_;
00032 
00033   //: Number of points either side of centre to search
00034   int search_nj_;
00035 
00036   //: Define N. angles (ie try at A+idA, i in [-nA,+nA])
00037   unsigned nA_;
00038 
00039   //: Angle step size (ie try at A+idA, i in [-nA,+nA])
00040   double dA_;
00041 
00042   //: Number of scales to try at
00043   unsigned ns_;
00044 
00045   //: Scaling factor (ie try at ((ds)^i), i in [-ns,+ns]
00046   double ds_;
00047 
00048   //: Return true if base class parameters are the same in pf
00049   bool base_equality(const mfpf_point_finder& pf) const;
00050  public:
00051 
00052   //: Dflt ctor
00053   mfpf_point_finder();
00054 
00055   //: Destructor
00056   virtual ~mfpf_point_finder();
00057 
00058   //: Size of step between sample points
00059   virtual void set_step_size(double);
00060 
00061   //: Size of step between sample points
00062   double step_size() const { return step_size_; }
00063 
00064   //: Define search region size
00065   //  During search, samples at points on grid [-ni,ni]x[-nj,nj],
00066   //  with axes defined by u.
00067   virtual void set_search_area(unsigned ni, unsigned nj);
00068 
00069   //: Define angle search parameters
00070   void set_angle_range(unsigned nA, double dA);
00071 
00072   //: Define scale search parameters
00073   void set_scale_range(unsigned ns, double ds);
00074 
00075   //: Number of points either side of centre to search along i
00076   int search_ni() const { return search_ni_; }
00077 
00078   //: Number of points either side of centre to search along j
00079   int search_nj() const { return search_nj_; }
00080 
00081   //: Set model to a new value when provided with a vector
00082   virtual bool set_model(const vcl_vector<double>& v);
00083 
00084   //: Number of dimensions in the model
00085   virtual unsigned model_dim();
00086 
00087   //: Radius of circle containing modelled region (in model frame units)
00088   //  Radius in world units given by step_size()*radius()
00089   virtual double radius() const = 0;
00090 
00091   //: Get sample of region around specified point in image
00092   virtual void get_sample_vector(const vimt_image_2d_of<float>& image,
00093                                  const vgl_point_2d<double>& p,
00094                                  const vgl_vector_2d<double>& u,
00095                                  vcl_vector<double>& v);
00096 
00097   //: Evaluate match at p, using u to define scale and orientation
00098   // Returns a quality of fit measure at the point (the smaller the better).
00099   virtual double evaluate(const vimt_image_2d_of<float>& image,
00100                           const vgl_point_2d<double>& p,
00101                           const vgl_vector_2d<double>& u)=0;
00102 
00103   //: Evaluate match at in a region around p
00104   // Returns a quality of fit at a set of positions.
00105   // response image (whose size and transform is set inside the
00106   // function), indicates the points at which the function was
00107   // evaluated.  response(i,j) is the fit at the point
00108   // response.world2im().inverse()(i,j).  The world2im() transformation
00109   // may be affine.
00110   virtual void evaluate_region(const vimt_image_2d_of<float>& image,
00111                                const vgl_point_2d<double>& p,
00112                                const vgl_vector_2d<double>& u,
00113                                vimt_image_2d_of<double>& response)=0;
00114 
00115   //: Search given image around p, using u to define scale and angle
00116   //  On exit, new_p defines position of the best nearby match.
00117   //  Returns a quality of fit measure at that
00118   //  point (the smaller the better).
00119   virtual double search_one_pose(const vimt_image_2d_of<float>& image,
00120                                  const vgl_point_2d<double>& p,
00121                                  const vgl_vector_2d<double>& u,
00122                                  vgl_point_2d<double>& new_p)=0;
00123 
00124   //: Search given image around p, using u to define scale and angle
00125   //  Evaluates responses on a grid, finds the best point on the
00126   //  grid, then optimises its position by fitting a parabola.
00127   //
00128   //  On exit, new_p defines position of the best nearby match.
00129   //  Returns a quality of fit measure at that
00130   //  point (the smaller the better).
00131   virtual double search_one_pose_with_opt(
00132                         const vimt_image_2d_of<float>& image,
00133                         const vgl_point_2d<double>& p,
00134                         const vgl_vector_2d<double>& u,
00135                         vgl_point_2d<double>& new_p);
00136 
00137   //: Search given image around p, using u to define scale and orientation
00138   //  On exit, new_p and new_u define position, scale and orientation of
00139   //  the best nearby match.  Returns a quality of fit measure at that
00140   //  point (the smaller the better).
00141   //
00142   //  Default implementation calls search_one_pose(...) at multiple
00143   //  angles and scales. Result will be at a grid position
00144   //  and one of the given angle/scales.  True optima can then
00145   //  be found by further optimisation of the point.
00146   virtual double search(const vimt_image_2d_of<float>& image,
00147                         const vgl_point_2d<double>& p,
00148                         const vgl_vector_2d<double>& u,
00149                         vgl_point_2d<double>& new_p,
00150                         vgl_vector_2d<double>& new_u);
00151 
00152   //: Search given image around p, using u to define scale and orientation
00153   //  On exit, new_p and new_u define position, scale and orientation of
00154   //  the best nearby match.  Returns a quality of fit measure at that
00155   //  point (the smaller the better).
00156   //  Parabolic fit used to estimate optimal position.
00157   //
00158   //  Default implementation calls search_one_pose(...) at multiple
00159   //  angles and scales. Result will be at a grid position
00160   //  and one of the given angle/scales.  True optima can then
00161   //  be found by further optimisation of the point.
00162   virtual double search_with_opt(
00163                         const vimt_image_2d_of<float>& image,
00164                         const vgl_point_2d<double>& p,
00165                         const vgl_vector_2d<double>& u,
00166                         vgl_point_2d<double>& new_p,
00167                         vgl_vector_2d<double>& new_u);
00168 
00169   //: Search for local optima around given point/scale/angle
00170   //  Search in a grid around p (defined by search_ni and search_nj).
00171   //  Find local minima on this grid and return append each to
00172   //  pts.  Note: pts is not resized, so empty beforehand if necessary.
00173   virtual void grid_search_one_pose(const vimt_image_2d_of<float>& image,
00174                                     const vgl_point_2d<double>& p,
00175                                     const vgl_vector_2d<double>& u,
00176                                     vcl_vector<mfpf_pose>& pts,
00177                                     vcl_vector<double>& fit);
00178 
00179   //: Search for local optima around given point/scale/angle
00180   //  Search in a grid around p (defined by search_ni and search_nj).
00181   //  Find local minima on this grid.
00182   //  Perform single sub-grid optimisation by fitting a parabola
00183   //  in x and y and testing resulting point.
00184   //  Append each to pts.
00185   //  Note: pts is not resized, so empty beforehand if necessary.
00186   virtual void multi_search_one_pose(
00187                            const vimt_image_2d_of<float>& image,
00188                            const vgl_point_2d<double>& p,
00189                            const vgl_vector_2d<double>& u,
00190                            vcl_vector<mfpf_pose>& pts,
00191                            vcl_vector<double>& fit);
00192 
00193   //: Search for local optima around given point/scale/angle
00194   //  For each angle and scale (defined by internal nA,dA,ns,ds)
00195   //  search in a grid around p (defined by search_ni and search_nj).
00196   //  Find local minima on this grid and return them in poses.
00197   //  Responses lie on grid in (x,y,ds,dA)
00198   //
00199   //  Note that an object in an image may lead to multiple responses,
00200   //  one at each scale and angle near to the optima.  Thus the
00201   //  poses defined in pts should be further refined to eliminate
00202   //  such multiple responses.
00203   virtual void grid_search(const vimt_image_2d_of<float>& image,
00204                            const vgl_point_2d<double>& p,
00205                            const vgl_vector_2d<double>& u,
00206                            vcl_vector<mfpf_pose>& poses,
00207                            vcl_vector<double>& fit);
00208 
00209   //: Search for local optima around given point/scale/angle
00210   //  For each angle and scale (defined by internal nA,dA,ns,ds)
00211   //  search in a grid around p (defined by search_ni and search_nj).
00212   //  Find local minima on this grid.
00213   //  Sub-grid estimation using parabolic fitting included.
00214   //  poses[i] defines result i, with corresponding fit fits[i]
00215   //
00216   //  Note that an object in an image may lead to multiple responses,
00217   //  one at each scale and angle near to the optima.  Thus the
00218   //  poses defined in pts should be further refined to eliminate
00219   //  such multiple responses.
00220   virtual void multi_search(const vimt_image_2d_of<float>& image,
00221                             const vgl_point_2d<double>& p,
00222                             const vgl_vector_2d<double>& u,
00223                             vcl_vector<mfpf_pose>& poses,
00224                             vcl_vector<double>& fits);
00225 
00226   //: Perform local optimisation to refine position,scale and angle
00227   //  On input fit is match at p,u.  On exit p,u and fit are updated.
00228   //  Baseclass implementation uses simplex optimisation.
00229   virtual void refine_match(const vimt_image_2d_of<float>& image,
00230                             vgl_point_2d<double>& p,
00231                             vgl_vector_2d<double>& u,
00232                             double& fit);
00233 
00234   //: Return true if modelled regions at pose1 and pose2 overlap
00235   virtual bool overlap(const mfpf_pose& pose1,
00236                        const mfpf_pose& pose2) const;
00237 
00238   //: Generate points in ref frame that represent boundary
00239   //  Points of a contour around the shape.
00240   //  Used for display purposes.  Join the points with an open
00241   //  contour to get a representation.
00242   virtual void get_outline(vcl_vector<vgl_point_2d<double> >& pts) const=0;
00243 
00244   //: Computes the aligned bounding box for feature with given pose
00245   //  On exit box_pose.p() gives the centre, corners are given by
00246   //  box_pose(+/-0.5*wi, +/-0.5*wj).
00247   virtual void aligned_bounding_box(const mfpf_pose& pose,
00248                                     mfpf_pose& box_pose,
00249                                     double& wi, double& wj) const;
00250 
00251   //: Create an image summarising the average model (where possible)
00252   //  For instance, creates an image of the mean template used for
00253   //  search. image.world2im() gives mapping from reference frame
00254   //  into raw image co-ords (including the step size).
00255   //  Default implementation does nothing - returns an empty image.
00256   virtual void get_image_of_model(vimt_image_2d_of<vxl_byte>& image) const;
00257 
00258   //: Select best level for searching around pose
00259   //  Selects pyramid level with pixel sizes best matching
00260   //  the model pixel size at given pose.
00261   unsigned image_level(const mfpf_pose& pose,
00262                        const vimt_image_pyramid& im_pyr) const;
00263 
00264   //: Version number for I/O
00265   short version_no() const;
00266 
00267   //: Name of the class
00268   virtual vcl_string is_a() const;
00269 
00270   //: Create a copy on the heap and return base class pointer
00271   virtual mfpf_point_finder* clone() const = 0;
00272 
00273   //: Print class to os
00274   virtual void print_summary(vcl_ostream& os) const;
00275 
00276   //: Save class to binary file stream
00277   virtual void b_write(vsl_b_ostream& bfs) const;
00278 
00279   //: Load class from binary file stream
00280   virtual void b_read(vsl_b_istream& bfs);
00281 };
00282 
00283 //: Allows derived class to be loaded by base-class pointer
00284 void vsl_add_to_binary_loader(const mfpf_point_finder& b);
00285 
00286 //: Binary file stream output operator for class reference
00287 void vsl_b_write(vsl_b_ostream& bfs, const mfpf_point_finder& b);
00288 
00289 //: Binary file stream input operator for class reference
00290 void vsl_b_read(vsl_b_istream& bfs, mfpf_point_finder& b);
00291 
00292 //: Stream output operator for class reference
00293 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_point_finder& b);
00294 
00295 //: Stream output operator for class pointer
00296 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_point_finder* b);
00297 
00298 #endif // mfpf_point_finder_h_