contrib/mul/vimt3d/vimt3d_sample_grid_trilin.txx
Go to the documentation of this file.
00001 // This is mul/vimt3d/vimt3d_sample_grid_trilin.txx
00002 #ifndef vimt3d_sample_grid_trilin_txx_
00003 #define vimt3d_sample_grid_trilin_txx_
00004 //:
00005 // \file
00006 // \brief Profile sampling functions for 3D images
00007 // \author Graham Vincent
00008 
00009 #include "vimt3d_sample_grid_trilin.h"
00010 #include <vil3d/vil3d_trilin_interp.h>
00011 #include <vnl/vnl_vector.h>
00012 #include <vgl/vgl_point_3d.h>
00013 #include <vgl/vgl_vector_3d.h>
00014 
00015 //: True if p clearly inside the image
00016 template<class T>
00017 inline bool
00018 vimt3d_trilin_point_in_image(const vgl_point_3d<double>& p, const vil3d_image_view<T>& image)
00019 {
00020   if (p.x()<1) return false;
00021   if (p.y()<1) return false;
00022   if (p.z()<1) return false;
00023   if (p.x()+2>image.ni()) return false;
00024   if (p.y()+2>image.nj()) return false;
00025   if (p.z()+2>image.nk()) return false;
00026   return true;
00027 }
00028 
00029 //: True if grid of size nu * nv * nw (in steps of u,v,w) is entirely in the image.
00030 //  p defines centre of one size.
00031 template<class T>
00032 inline bool vimt3d_grid_in_image_ic(const vgl_point_3d<double>& im_p,
00033                                     const vgl_vector_3d<double>& im_u,
00034                                     const vgl_vector_3d<double>& im_v,
00035                                     const vgl_vector_3d<double>& im_w,
00036                                     unsigned nu, unsigned nv, unsigned nw,
00037                                     const vil3d_image_view<T>& image)
00038 {
00039   vgl_vector_3d<double> u1=(nu-1)*im_u;
00040   vgl_vector_3d<double> v1=(nv-1)*im_v;
00041   vgl_vector_3d<double> w1=(nw-1)*im_w;
00042   if (!vimt3d_trilin_point_in_image(im_p,image)) return false;
00043   if (!vimt3d_trilin_point_in_image(im_p+u1,image)) return false;
00044   if (!vimt3d_trilin_point_in_image(im_p+v1,image)) return false;
00045   if (!vimt3d_trilin_point_in_image(im_p+w1,image)) return false;
00046   if (!vimt3d_trilin_point_in_image(im_p+u1+v1,image)) return false;
00047   if (!vimt3d_trilin_point_in_image(im_p+u1+w1,image)) return false;
00048   if (!vimt3d_trilin_point_in_image(im_p+v1+w1,image)) return false;
00049   if (!vimt3d_trilin_point_in_image(im_p+u1+v1+w1,image)) return false;
00050 
00051   return true;
00052 }
00053 
00054 
00055 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in world coordinates.
00056 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00057 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00058 //  v[0]..v[np-1] are the values from point p.
00059 //  Samples are taken along direction w first. Samples
00060 //  outside the image are set to 0.
00061 template <class imType, class vecType>
00062 void vimt3d_sample_grid_trilin(vnl_vector<vecType>& vec,
00063                                const vimt3d_image_3d_of<imType>& image,
00064                                const vgl_point_3d<double>& p,
00065                                const vgl_vector_3d<double>& u,
00066                                const vgl_vector_3d<double>& v,
00067                                const vgl_vector_3d<double>& w,
00068                                unsigned nu, unsigned nv, unsigned nw)
00069 {
00070   // convert to image coordinates
00071   vgl_point_3d<double> im_p0 = image.world2im()(p);
00072   vgl_vector_3d<double> im_u = image.world2im()(p+u)-im_p0;
00073   vgl_vector_3d<double> im_v = image.world2im()(p+v)-im_p0;
00074   vgl_vector_3d<double> im_w = image.world2im()(p+w)-im_p0;
00075 
00076   // call image coordinate version of grid sampler
00077   vimt3d_sample_grid_trilin_ic(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00078 
00079   return;
00080 }
00081 
00082 
00083 //: Sample grid p+i.u+j.v+k.w in image coordinates using trilinear interpolation with NO CHECKS.
00084 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00085 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00086 //  v[0]..v[np-1] are the values from point p
00087 //  Samples are taken along each image plane first, then direction w, then v, and u.
00088 //  Points outside image return zero.
00089 template <class imType, class vecType>
00090 inline void vimt3d_sample_grid_trilin_ic_no_checks(
00091   vnl_vector<vecType>& vec,
00092   const vil3d_image_view<imType>& image,
00093   const vgl_point_3d<double>& p0,
00094   const vgl_vector_3d<double>& u,
00095   const vgl_vector_3d<double>& v,
00096   const vgl_vector_3d<double>& w,
00097   unsigned nu, unsigned nv, unsigned nw)
00098 {
00099   unsigned np = image.nplanes();
00100   vcl_ptrdiff_t istep = image.istep();
00101   vcl_ptrdiff_t jstep = image.jstep();
00102   vcl_ptrdiff_t kstep = image.kstep();
00103   vcl_ptrdiff_t pstep = image.planestep();
00104 
00105   vec.set_size(nu*nv*nw*np);
00106   vecType* vc = vec.begin();
00107 
00108   vgl_point_3d<double> p1 = p0;
00109 
00110   if (np==1)
00111   {
00112     const imType* plane0 = image.origin_ptr();
00113     for (unsigned i=0;i<nu;++i,p1+=u)
00114     {
00115       vgl_point_3d<double> p2 = p1;
00116       for (unsigned j=0;j<nv;++j,p2+=v)
00117       {
00118         vgl_point_3d<double> p = p2;
00119         // Sample each row (along w)
00120         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00121           *vc = vil3d_trilin_interp_raw(p.x(),p.y(),p.z(),
00122                                         plane0,istep,jstep,kstep);
00123       }
00124     }
00125   }
00126   else
00127   {
00128     for (unsigned i=0;i<nu;++i,p1+=u)
00129     {
00130       vgl_point_3d<double> p2 = p1;
00131       for (unsigned j=0;j<nv;++j,p2+=v)
00132       {
00133         vgl_point_3d<double> p = p2;
00134         // Sample each row (along w)
00135         for (unsigned l=0;l<nw;++l,p+=w)
00136           for (unsigned k=0;k<np;++k,++vc)
00137             *vc = vil3d_trilin_interp_raw(p.x(),p.y(),p.z(),
00138                                           image.origin_ptr()+k*pstep,istep,jstep,kstep);
00139       }
00140     }
00141   }
00142 }
00143 
00144 //: Sample grid p+i.u+j.v+k.w safely in image coordinates using trilinear interpolation.
00145 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00146 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00147 //  v[0]..v[np-1] are the values from point p
00148 //  Samples are taken along direction w first
00149 //  Points outside image return zero.
00150 template <class imType, class vecType>
00151 inline void vimt3d_sample_grid_trilin_ic_safe(
00152   vnl_vector<vecType>& vec,
00153   const vil3d_image_view<imType>& image,
00154   const vgl_point_3d<double>& p0,
00155   const vgl_vector_3d<double>& u,
00156   const vgl_vector_3d<double>& v,
00157   const vgl_vector_3d<double>& w,
00158   unsigned nu, unsigned nv, unsigned nw)
00159 {
00160   unsigned np = image.nplanes();
00161   unsigned ni = image.ni();
00162   unsigned nj = image.nj();
00163   unsigned nk = image.nk();
00164   vcl_ptrdiff_t istep = image.istep();
00165   vcl_ptrdiff_t jstep = image.jstep();
00166   vcl_ptrdiff_t kstep = image.kstep();
00167   vcl_ptrdiff_t pstep = image.planestep();
00168 
00169   vec.set_size(nu*nv*nw*np);
00170   vecType* vc = vec.begin();
00171 
00172   vgl_point_3d<double> p1 = p0;
00173 
00174   if (np==1)
00175   {
00176     const imType* plane0 = image.origin_ptr();
00177     for (unsigned i=0;i<nu;++i,p1+=u)
00178     {
00179       vgl_point_3d<double> p2 = p1;
00180       for (unsigned j=0;j<nv;++j,p2+=v)
00181       {
00182         vgl_point_3d<double> p = p2;
00183         // Sample each row (along w)
00184         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00185           *vc = vil3d_trilin_interp_safe(p.x(),p.y(),p.z(),plane0,ni,nj,nk,istep,jstep,kstep);
00186       }
00187     }
00188   }
00189   else
00190   {
00191     for (unsigned i=0;i<nu;++i,p1+=u)
00192     {
00193       vgl_point_3d<double> p2 = p1;
00194       for (unsigned j=0;j<nv;++j,p2+=v)
00195       {
00196         vgl_point_3d<double> p = p2;
00197         // Sample each row (along w)
00198         for (unsigned l=0;l<nw;++l,p+=w)
00199           for (unsigned k=0;k<np;++k,++vc)
00200             *vc = vil3d_trilin_interp_safe(p.x(),p.y(),p.z(),
00201                                            image.origin_ptr()+k*pstep,ni,nj,nk,istep,jstep,kstep);
00202       }
00203     }
00204   }
00205 }
00206 
00207 //: Sample grid p+i.u+j.v+k.w safely in image coordinates using trilinear interpolation.
00208 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00209 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00210 //  v[0]..v[np-1] are the values from point p
00211 //  Samples are taken along direction w first
00212 //  Points outside image are set to the nearest voxel's value.
00213 template <class imType, class vecType>
00214 inline void vimt3d_sample_grid_trilin_ic_extend(
00215   vnl_vector<vecType>& vec,
00216   const vil3d_image_view<imType>& image,
00217   const vgl_point_3d<double>& p0,
00218   const vgl_vector_3d<double>& u,
00219   const vgl_vector_3d<double>& v,
00220   const vgl_vector_3d<double>& w,
00221   unsigned nu, unsigned nv, unsigned nw)
00222 {
00223   unsigned np = image.nplanes();
00224   unsigned ni = image.ni();
00225   unsigned nj = image.nj();
00226   unsigned nk = image.nk();
00227   vcl_ptrdiff_t istep = image.istep();
00228   vcl_ptrdiff_t jstep = image.jstep();
00229   vcl_ptrdiff_t kstep = image.kstep();
00230   vcl_ptrdiff_t pstep = image.planestep();
00231 
00232   vec.set_size(nu*nv*nw*np);
00233   vecType* vc = vec.begin();
00234 
00235   vgl_point_3d<double> p1 = p0;
00236 
00237   if (np==1)
00238   {
00239     const imType* plane0 = image.origin_ptr();
00240     for (unsigned i=0;i<nu;++i,p1+=u)
00241     {
00242       vgl_point_3d<double> p2 = p1;
00243       for (unsigned j=0;j<nv;++j,p2+=v)
00244       {
00245         vgl_point_3d<double> p = p2;
00246         // Sample each row (along w)
00247         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00248           *vc = vil3d_trilin_interp_safe_extend(p.x(),p.y(),p.z(),
00249                                                 plane0,ni,nj,nk,istep,jstep,kstep);
00250       }
00251     }
00252   }
00253   else
00254   {
00255     for (unsigned i=0;i<nu;++i,p1+=u)
00256     {
00257       vgl_point_3d<double> p2 = p1;
00258       for (unsigned j=0;j<nv;++j,p2+=v)
00259       {
00260         vgl_point_3d<double> p = p2;
00261         // Sample each row (along w)
00262         for (unsigned l=0;l<nw;++l,p+=w)
00263           for (unsigned k=0;k<np;++k,++vc)
00264             *vc = vil3d_trilin_interp_safe_extend(p.x(),p.y(),p.z(),
00265                                                   image.origin_ptr()+k*pstep,ni,nj,nk,istep,jstep,kstep);
00266       }
00267     }
00268   }
00269 }
00270 
00271 //: Sample grid p+i.u+j.v+k.w safely in image coordinates using trilinear interpolation.
00272 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00273 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00274 //  v[0]..v[np-1] are the values from point p
00275 //  Samples are taken along direction w first
00276 //  Points outside image are set to the nearest voxel's value.
00277 template <class imType, class vecType>
00278 inline void vimt3d_sample_grid_trilin_ic_edgena(
00279   vnl_vector<vecType>& vec,
00280   const vil3d_image_view<imType>& image,
00281   const vgl_point_3d<double>& p0,
00282   const vgl_vector_3d<double>& u,
00283   const vgl_vector_3d<double>& v,
00284   const vgl_vector_3d<double>& w,
00285   unsigned nu, unsigned nv, unsigned nw)
00286 {
00287   unsigned np = image.nplanes();
00288   unsigned ni = image.ni();
00289   unsigned nj = image.nj();
00290   unsigned nk = image.nk();
00291   vcl_ptrdiff_t istep = image.istep();
00292   vcl_ptrdiff_t jstep = image.jstep();
00293   vcl_ptrdiff_t kstep = image.kstep();
00294   vcl_ptrdiff_t pstep = image.planestep();
00295 
00296   vec.set_size(nu*nv*nw*np);
00297   vecType* vc = vec.begin();
00298 
00299   vgl_point_3d<double> p1 = p0;
00300 
00301   if (np==1)
00302   {
00303     const imType* plane0 = image.origin_ptr();
00304     for (unsigned i=0;i<nu;++i,p1+=u)
00305     {
00306       vgl_point_3d<double> p2 = p1;
00307       for (unsigned j=0;j<nv;++j,p2+=v)
00308       {
00309         vgl_point_3d<double> p = p2;
00310         // Sample each row (along w)
00311         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00312           *vc = vil3d_trilin_interp_safe_edgena(p.x(),p.y(),p.z(),
00313                                                 plane0,ni,nj,nk,istep,jstep,kstep);
00314       }
00315     }
00316   }
00317   else
00318   {
00319     for (unsigned i=0;i<nu;++i,p1+=u)
00320     {
00321       vgl_point_3d<double> p2 = p1;
00322       for (unsigned j=0;j<nv;++j,p2+=v)
00323       {
00324         vgl_point_3d<double> p = p2;
00325         // Sample each row (along w)
00326         for (unsigned l=0;l<nw;++l,p+=w)
00327           for (unsigned k=0;k<np;++k,++vc)
00328             *vc = vil3d_trilin_interp_safe_edgena(p.x(),p.y(),p.z(),
00329                                                   image.origin_ptr()+k*pstep,ni,nj,nk,istep,jstep,kstep);
00330       }
00331     }
00332   }
00333 }
00334 
00335 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in world coordinates.
00336 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00337 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00338 //  v[0]..v[np-1] are the values from point p.
00339 //  Samples are taken along direction w first. Samples
00340 //  outside the image are set to the value of the nearest voxel's value.
00341 template <class imType, class vecType>
00342 void vimt3d_sample_grid_trilin_extend(
00343   vnl_vector<vecType>& vec,
00344   const vimt3d_image_3d_of<imType>& image,
00345   const vgl_point_3d<double>& p,
00346   const vgl_vector_3d<double>& u,
00347   const vgl_vector_3d<double>& v,
00348   const vgl_vector_3d<double>& w,
00349   unsigned nu, unsigned nv, unsigned nw)
00350 {
00351   // convert to image coordinates
00352   vgl_point_3d<double> im_p0 = image.world2im()(p);
00353   vgl_vector_3d<double> im_u = image.world2im()(p+u)-im_p0;
00354   vgl_vector_3d<double> im_v = image.world2im()(p+v)-im_p0;
00355   vgl_vector_3d<double> im_w = image.world2im()(p+w)-im_p0;
00356 
00357   // call image coordinate version of grid sampler
00358   if (vimt3d_grid_in_image_ic(im_p0,im_u,im_v,im_w,nu,nv,nw,image.image()))
00359     vimt3d_sample_grid_trilin_ic_no_checks(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00360   else
00361     vimt3d_sample_grid_trilin_ic_extend(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00362 
00363   return;
00364 }
00365 
00366 
00367 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in world coordinates.
00368 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00369 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00370 //  v[0]..v[np-1] are the values from point p.
00371 //  Samples are taken along direction w first. Samples
00372 //  outside the image are set to the value of the nearest voxel's value.
00373 template <class imType, class vecType>
00374 void vimt3d_sample_grid_trilin_edgena(
00375   vnl_vector<vecType>& vec,
00376   const vimt3d_image_3d_of<imType>& image,
00377   const vgl_point_3d<double>& p,
00378   const vgl_vector_3d<double>& u,
00379   const vgl_vector_3d<double>& v,
00380   const vgl_vector_3d<double>& w,
00381   unsigned nu, unsigned nv, unsigned nw)
00382 {
00383   // convert to image coordinates
00384   vgl_point_3d<double> im_p0 = image.world2im()(p);
00385   vgl_vector_3d<double> im_u = image.world2im()(p+u)-im_p0;
00386   vgl_vector_3d<double> im_v = image.world2im()(p+v)-im_p0;
00387   vgl_vector_3d<double> im_w = image.world2im()(p+w)-im_p0;
00388 
00389   // call image coordinate version of grid sampler
00390   if (vimt3d_grid_in_image_ic(im_p0,im_u,im_v,im_w,nu,nv,nw,image.image()))
00391     vimt3d_sample_grid_trilin_ic_no_checks(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00392   else
00393     vimt3d_sample_grid_trilin_ic_edgena(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00394 
00395   return;
00396 }
00397 
00398 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in image coordinates.
00399 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00400 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00401 //  v[0]..v[np-1] are the values from point p
00402 //  Samples are taken along direction w first.
00403 //  Samples outside the image are set to 0.
00404 template <class imType, class vecType>
00405 void vimt3d_sample_grid_trilin_ic(vnl_vector<vecType>& vec,
00406                                   const vil3d_image_view<imType>& image,
00407                                   const vgl_point_3d<double>& im_p,
00408                                   const vgl_vector_3d<double>& im_u,
00409                                   const vgl_vector_3d<double>& im_v,
00410                                   const vgl_vector_3d<double>& im_w,
00411                                   unsigned nu, unsigned nv, unsigned nw)
00412 {
00413   if (vimt3d_grid_in_image_ic(im_p,im_u,im_v,im_w,nu,nv,nw,image))
00414     vimt3d_sample_grid_trilin_ic_no_checks(vec,image,im_p,im_u,im_v,im_w,nu,nv,nw);
00415   else
00416     vimt3d_sample_grid_trilin_ic_safe(vec,image,im_p,im_u,im_v,im_w,nu,nv,nw);
00417 
00418   return;
00419 }
00420 
00421 
00422 #define VIMT3D_SAMPLE_GRID_TRILIN_INSTANTIATE( imType, vecType ) \
00423 template void vimt3d_sample_grid_trilin( \
00424   vnl_vector<vecType >& vec, \
00425   const vimt3d_image_3d_of<imType >& image, \
00426   const vgl_point_3d<double >& p, \
00427   const vgl_vector_3d<double >& u, \
00428   const vgl_vector_3d<double >& v, \
00429   const vgl_vector_3d<double >& w, \
00430   unsigned nu, unsigned nv, unsigned nw); \
00431 template void vimt3d_sample_grid_trilin_extend( \
00432   vnl_vector<vecType >& vec, \
00433   const vimt3d_image_3d_of<imType >& image, \
00434   const vgl_point_3d<double >& p, \
00435   const vgl_vector_3d<double >& u, \
00436   const vgl_vector_3d<double >& v, \
00437   const vgl_vector_3d<double >& w, \
00438   unsigned nu, unsigned nv, unsigned nw); \
00439 template void vimt3d_sample_grid_trilin_edgena( \
00440   vnl_vector<vecType >& vec, \
00441   const vimt3d_image_3d_of<imType >& image, \
00442   const vgl_point_3d<double >& p, \
00443   const vgl_vector_3d<double >& u, \
00444   const vgl_vector_3d<double >& v, \
00445   const vgl_vector_3d<double >& w, \
00446   unsigned nu, unsigned nv, unsigned nw); \
00447 template void vimt3d_sample_grid_trilin_ic( \
00448   vnl_vector<vecType >& vec, \
00449   const vil3d_image_view<imType >& image, \
00450   const vgl_point_3d<double >& im_p, \
00451   const vgl_vector_3d<double >& im_u, \
00452   const vgl_vector_3d<double >& im_v, \
00453   const vgl_vector_3d<double >& im_w, \
00454   unsigned nu, unsigned nv, unsigned nw)
00455 
00456 #endif // vimt3d_sample_grid_trilin_txx_