contrib/mul/vimt/vimt_sample_grid_bicub.txx
Go to the documentation of this file.
00001 // This is mul/vimt/vimt_sample_grid_bicub.txx
00002 #ifndef vimt_sample_grid_bicub_txx_
00003 #define vimt_sample_grid_bicub_txx_
00004 //:
00005 // \file
00006 // \brief Grid sampling functions for 2D images
00007 // \author Tim Cootes
00008 
00009 #include "vimt_sample_grid_bicub.h"
00010 #include <vil/vil_sample_grid_bicub.h>
00011 #include <vil/vil_bicub_interp.h>
00012 #include <vnl/vnl_vector.h>
00013 #include <vgl/vgl_point_2d.h>
00014 #include <vgl/vgl_vector_2d.h>
00015 
00016 inline bool vimt_grid_bicub_corner_in_image(const vgl_point_2d<double>& p,
00017                                             const vil_image_view_base& image)
00018 {
00019   if (p.x()<1) return false;
00020   if (p.x()<1) return false;
00021   if (p.x()+2>image.ni()) return false;
00022   if (p.y()+2>image.nj()) return false;
00023   return true;
00024 }
00025 
00026 //: Sample grid from image, using bicubic interpolation
00027 //  Grid points are p+i.u+j.v where i=[0..n1-1], j=[0..n2-1]
00028 //  Vector vec is resized to n1*n2*np elements, where np=image.nplanes().
00029 //  vec[0]..vec[np-1] are the values from point p0
00030 //  Samples are taken along direction v first, then along u.
00031 //  Points outside image return zero.
00032 // \relatesalso vimt_image_2d_of
00033 template <class imType, class vecType>
00034 void vimt_sample_grid_bicub(vnl_vector<vecType>& vec,
00035                             const vimt_image_2d_of<imType>& image,
00036                             const vgl_point_2d<double>& p0,
00037                             const vgl_vector_2d<double>& u,
00038                             const vgl_vector_2d<double>& v,
00039                             int n1, int n2)
00040 {
00041   vgl_point_2d<double> im_p0 = image.world2im()(p0);
00042   vgl_point_2d<double> im_p1 = image.world2im()(p0+(n1-1)*u);
00043   vgl_point_2d<double> im_p2 = image.world2im()(p0+(n2-1)*v);
00044   int np = image.image().nplanes();
00045   vec.set_size(n1*n2*np);
00046   vecType *vec_data = vec.data_block();
00047 
00048   if (image.world2im().form()!=vimt_transform_2d::Projective)
00049   {
00050     // Can do all work in image co-ordinates under an affine transformation
00051     vgl_vector_2d<double> im_u(0,0);
00052     if (n1>1) im_u = (im_p1-im_p0)/(n1-1);
00053     vgl_vector_2d<double> im_v(0,0);
00054     if (n2>1) im_v = (im_p2-im_p0)/(n2-1);
00055 
00056     vil_sample_grid_bicub(vec_data,image.image(),im_p0.x(),im_p0.y(),
00057                           im_u.x(),im_u.y(),im_v.x(),im_v.y(),n1,n2);
00058     return;
00059   }
00060 
00061   // Otherwise do more fiddly projective calculations
00062 
00063   // Check that all the grid points are within the image.
00064   const vimt_transform_2d& w2i = image.world2im();
00065   bool all_in_image =
00066       vimt_grid_bicub_corner_in_image(im_p0,image.image()) &&
00067       vimt_grid_bicub_corner_in_image(im_p1,image.image()) &&
00068       vimt_grid_bicub_corner_in_image(im_p2,image.image()) &&
00069       vimt_grid_bicub_corner_in_image(w2i(p0+(n1-1)*u+(n2-1)*v),image.image());
00070 
00071   vgl_point_2d<double> p1=p0;
00072 
00073   const imType* plane0 = image.image().top_left_ptr();
00074   unsigned ni = image.image().ni();
00075   unsigned nj = image.image().nj();
00076   vcl_ptrdiff_t istep = image.image().istep();
00077   vcl_ptrdiff_t jstep = image.image().jstep();
00078   vcl_ptrdiff_t pstep = image.image().planestep();
00079 
00080   if (all_in_image)
00081   {
00082     if (np==1)
00083     {
00084       for (int i=0;i<n1;++i,p1+=u)
00085       {
00086         vgl_point_2d<double> p=p1;  // Start of j-th row
00087         for (int j=0;j<n2;++j,p+=v,++vec_data)
00088         {
00089           vgl_point_2d<double> im_p = w2i(p);
00090           *vec_data = vil_bicub_interp_raw(im_p.x(),im_p.y(),plane0,istep,jstep);
00091         }
00092       }
00093     }
00094     else
00095     {
00096       for (int i=0;i<n1;++i,p1+=u)
00097       {
00098         vgl_point_2d<double> p=p1;  // Start of j-th row
00099         for (int j=0;j<n2;++j,p+=v)
00100         {
00101           vgl_point_2d<double> im_p = w2i(p);
00102           for (int k=0;k<np;++k,++vec_data)
00103             *vec_data = vil_bicub_interp_raw(im_p.x(),im_p.y(),plane0+k*pstep,istep,jstep);
00104         }
00105       }
00106     }
00107   }
00108   else
00109   {
00110     // Use safe interpolation
00111     if (np==1)
00112     {
00113       for (int i=0;i<n1;++i,p1+=u)
00114       {
00115         vgl_point_2d<double> p=p1;  // Start of j-th row
00116         for (int j=0;j<n2;++j,p+=v,++vec_data)
00117         {
00118           vgl_point_2d<double> im_p = w2i(p);
00119           *vec_data = vil_bicub_interp_safe(im_p.x(),im_p.y(),plane0,ni,nj,istep,jstep);
00120         }
00121       }
00122     }
00123     else
00124     {
00125       for (int i=0;i<n1;++i,p1+=u)
00126       {
00127         vgl_point_2d<double> p=p1;  // Start of j-th row
00128         for (int j=0;j<n2;++j,p+=v)
00129         {
00130           vgl_point_2d<double> im_p = w2i(p);
00131           for (int k=0;k<np;++k,++vec_data)
00132             *vec_data = vil_bicub_interp_safe(im_p.x(),im_p.y(),plane0+k*pstep,ni,nj,istep,jstep);
00133         }
00134       }
00135     }
00136   }
00137 }
00138 
00139 #define VIMT_SAMPLE_GRID_BICUB_INSTANTIATE( imType, vecType ) \
00140 template void vimt_sample_grid_bicub(vnl_vector<vecType >&, \
00141                                      const vimt_image_2d_of<imType >&, \
00142                                      const vgl_point_2d<double >&, \
00143                                      const vgl_vector_2d<double >&, \
00144                                      const vgl_vector_2d<double >&, \
00145                                      int, int)
00146 
00147 #endif // vimt_sample_grid_bicub_txx_