contrib/mul/vimt/vimt_sample_grid_bilin.txx
Go to the documentation of this file.
00001 // This is mul/vimt/vimt_sample_grid_bilin.txx
00002 #ifndef vimt_sample_grid_bilin_txx_
00003 #define vimt_sample_grid_bilin_txx_
00004 //:
00005 // \file
00006 // \brief Grid sampling functions for 2D images
00007 // \author Tim Cootes
00008 
00009 #include "vimt_sample_grid_bilin.h"
00010 #include <vil/vil_sample_grid_bilin.h>
00011 #include <vil/vil_bilin_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_bilin_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.y()<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 bilinear 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_bilin(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_bilin(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_bilin_corner_in_image(im_p0,image.image()) &&
00067       vimt_grid_bilin_corner_in_image(im_p1,image.image()) &&
00068       vimt_grid_bilin_corner_in_image(im_p2,image.image()) &&
00069       vimt_grid_bilin_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 = (vecType)vil_bilin_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 = (vecType)vil_bilin_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 = (vecType)vil_bilin_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 = (vecType)vil_bilin_interp_safe(im_p.x(),im_p.y(),plane0+k*pstep,ni,nj,istep,jstep);
00133         }
00134       }
00135     }
00136   }
00137 }
00138 
00139 
00140 //: Sample grid from image, using bilinear interpolation
00141 //  Grid points are p+i.u+j.v where i=[0..n1-1], j=[0..n2-1]
00142 //  Vector vec is resized to n1*n2*np elements, where np=image.nplanes().
00143 //  vec[0]..vec[np-1] are the values from point p0
00144 //  Samples are taken along direction v first, then along u.
00145 //  Points outside image return NA.
00146 // \relatesalso vimt_image_2d_of
00147 template <class imType, class vecType>
00148 void vimt_sample_grid_bilin_edgena(vnl_vector<vecType>& vec,
00149                                    const vimt_image_2d_of<imType>& image,
00150                                    const vgl_point_2d<double>& p0,
00151                                    const vgl_vector_2d<double>& u,
00152                                    const vgl_vector_2d<double>& v,
00153                                    int n1, int n2)
00154 {
00155   vgl_point_2d<double> im_p0 = image.world2im()(p0);
00156   vgl_point_2d<double> im_p1 = image.world2im()(p0+(n1-1)*u);
00157   vgl_point_2d<double> im_p2 = image.world2im()(p0+(n2-1)*v);
00158   int np = image.image().nplanes();
00159   vec.set_size(n1*n2*np);
00160   vecType *vec_data = vec.data_block();
00161 
00162   if (image.world2im().form()!=vimt_transform_2d::Projective)
00163   {
00164     // Can do all work in image co-ordinates under an affine transformation
00165     vgl_vector_2d<double> im_u(0,0);
00166     if (n1>1) im_u = (im_p1-im_p0)/(n1-1);
00167     vgl_vector_2d<double> im_v(0,0);
00168     if (n2>1) im_v = (im_p2-im_p0)/(n2-1);
00169 
00170     vil_sample_grid_bilin_edgena(vec_data,image.image(),im_p0.x(),im_p0.y(),
00171                                  im_u.x(),im_u.y(),im_v.x(),im_v.y(),n1,n2);
00172     return;
00173   }
00174 
00175   // Otherwise do more fiddly projective calculations
00176 
00177   // Check that all the grid points are within the image.
00178   const vimt_transform_2d& w2i = image.world2im();
00179   bool all_in_image =
00180       vimt_grid_bilin_corner_in_image(im_p0,image.image()) &&
00181       vimt_grid_bilin_corner_in_image(im_p1,image.image()) &&
00182       vimt_grid_bilin_corner_in_image(im_p2,image.image()) &&
00183       vimt_grid_bilin_corner_in_image(w2i(p0+(n1-1)*u+(n2-1)*v),image.image());
00184 
00185   vgl_point_2d<double> p1=p0;
00186 
00187   const imType* plane0 = image.image().top_left_ptr();
00188   unsigned ni = image.image().ni();
00189   unsigned nj = image.image().nj();
00190   vcl_ptrdiff_t istep = image.image().istep();
00191   vcl_ptrdiff_t jstep = image.image().jstep();
00192   vcl_ptrdiff_t pstep = image.image().planestep();
00193 
00194   if (all_in_image)
00195   {
00196     if (np==1)
00197     {
00198       for (int i=0;i<n1;++i,p1+=u)
00199       {
00200         vgl_point_2d<double> p=p1;  // Start of j-th row
00201         for (int j=0; j<n2; ++j,p+=v,++vec_data)
00202         {
00203           vgl_point_2d<double> im_p = w2i(p);
00204           *vec_data = (vecType)vil_bilin_interp_raw(im_p.x(),im_p.y(),plane0,istep,jstep);
00205         }
00206       }
00207     }
00208     else
00209     {
00210       for (int i=0;i<n1;++i,p1+=u)
00211       {
00212         vgl_point_2d<double> p=p1;  // Start of j-th row
00213         for (int j=0;j<n2;++j,p+=v)
00214         {
00215           vgl_point_2d<double> im_p = w2i(p);
00216           for (int k=0;k<np;++k,++vec_data)
00217             *vec_data = (vecType)vil_bilin_interp_raw(im_p.x(),im_p.y(),plane0+k*pstep,istep,jstep);
00218         }
00219       }
00220     }
00221   }
00222   else
00223   {
00224     // Use safe interpolation
00225     if (np==1)
00226     {
00227       for (int i=0;i<n1;++i,p1+=u)
00228       {
00229         vgl_point_2d<double> p=p1;  // Start of j-th row
00230         for (int j=0;j<n2;++j,p+=v,++vec_data)
00231         {
00232           vgl_point_2d<double> im_p = w2i(p);
00233           *vec_data = (vecType)vil_bilin_interp_safe_edgena(im_p.x(),im_p.y(),plane0,ni,nj,istep,jstep);
00234         }
00235       }
00236     }
00237     else
00238     {
00239       for (int i=0;i<n1;++i,p1+=u)
00240       {
00241         vgl_point_2d<double> p=p1;  // Start of j-th row
00242         for (int j=0;j<n2;++j,p+=v)
00243         {
00244           vgl_point_2d<double> im_p = w2i(p);
00245           for (int k=0;k<np;++k,++vec_data)
00246             *vec_data = (vecType)vil_bilin_interp_safe_edgena(im_p.x(),im_p.y(),plane0+k*pstep,ni,nj,istep,jstep);
00247         }
00248       }
00249     }
00250   }
00251 }
00252 
00253 
00254 #define VIMT_SAMPLE_GRID_BILIN_INSTANTIATE( imType, vecType ) \
00255 template void vimt_sample_grid_bilin(vnl_vector<vecType >&, \
00256                                      const vimt_image_2d_of<imType >&, \
00257                                      const vgl_point_2d<double >&, \
00258                                      const vgl_vector_2d<double >&, \
00259                                      const vgl_vector_2d<double >&, \
00260                                      int, int); \
00261 template void vimt_sample_grid_bilin_edgena(vnl_vector<vecType >&, \
00262                                             const vimt_image_2d_of<imType >&, \
00263                                             const vgl_point_2d<double >&, \
00264                                             const vgl_vector_2d<double >&, \
00265                                             const vgl_vector_2d<double >&, \
00266                                             int, int)
00267 
00268 #endif // vimt_sample_grid_bilin_txx_