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 vimt3d_point_in_image(const vgl_point_3d<double>& p, const vil3d_image_view<T>& image)
00018 {
00019   if (p.x()<1) return false;
00020   if (p.y()<1) return false;
00021   if (p.z()<1) return false;
00022   if (p.x()+2>image.ni()) return false;
00023   if (p.y()+2>image.nj()) return false;
00024   if (p.z()+2>image.nk()) return false;
00025   return true;
00026 }
00027 
00028 //: True if grid of size nu * nv * nw (in steps of u,v,w) is entirely in the image.
00029 //  p defines centre of one size.
00030 template<class T>
00031 inline bool vimt3d_grid_in_image_ic(const vgl_point_3d<double>& im_p,
00032                                     const vgl_vector_3d<double>& im_u,
00033                                     const vgl_vector_3d<double>& im_v,
00034                                     const vgl_vector_3d<double>& im_w,
00035                                     unsigned nu, unsigned nv, unsigned nw,
00036                                     const vil3d_image_view<T>& image)
00037 {
00038   vgl_vector_3d<double> u1=(nu-1)*im_u;
00039   vgl_vector_3d<double> v1=(nv-1)*im_v;
00040   vgl_vector_3d<double> w1=(nw-1)*im_w;
00041   if (!vimt3d_point_in_image(im_p,image)) return false;
00042   if (!vimt3d_point_in_image(im_p+u1,image)) return false;
00043   if (!vimt3d_point_in_image(im_p+v1,image)) return false;
00044   if (!vimt3d_point_in_image(im_p+w1,image)) return false;
00045   if (!vimt3d_point_in_image(im_p+u1+v1,image)) return false;
00046   if (!vimt3d_point_in_image(im_p+u1+w1,image)) return false;
00047   if (!vimt3d_point_in_image(im_p+v1+w1,image)) return false;
00048   if (!vimt3d_point_in_image(im_p+u1+v1+w1,image)) return false;
00049 
00050   return true;
00051 }
00052 
00053 
00054 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in world coordinates.
00055 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00056 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00057 //  v[0]..v[np-1] are the values from point p.
00058 //  Samples are taken along direction w first. Samples
00059 //  outside the image are set to 0.
00060 template <class imType, class vecType>
00061 void vimt3d_sample_grid_trilin(vnl_vector<vecType>& vec,
00062                                const vimt3d_image_3d_of<imType>& image,
00063                                const vgl_point_3d<double>& p,
00064                                const vgl_vector_3d<double>& u,
00065                                const vgl_vector_3d<double>& v,
00066                                const vgl_vector_3d<double>& w,
00067                                unsigned nu, unsigned nv, unsigned nw)
00068 {
00069   // convert to image coordinates
00070   vgl_point_3d<double> im_p0 = image.world2im()(p);
00071   vgl_vector_3d<double> im_u = image.world2im()(p+u)-im_p0;
00072   vgl_vector_3d<double> im_v = image.world2im()(p+v)-im_p0;
00073   vgl_vector_3d<double> im_w = image.world2im()(p+w)-im_p0;
00074 
00075   // call image coordinate version of grid sampler
00076   vimt3d_sample_grid_trilin_ic(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00077 
00078   return;
00079 }
00080 
00081 
00082 //: Sample grid p+i.u+j.v+k.w in image coordinates using trilinear interpolation with NO CHECKS.
00083 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00084 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00085 //  v[0]..v[np-1] are the values from point p
00086 //  Samples are taken along direction w first
00087 //  Points outside image return zero.
00088 template <class imType, class vecType>
00089 inline void vimt3d_sample_grid_trilin_ic_no_checks(
00090   vnl_vector<vecType>& vec,
00091   const vil3d_image_view<imType>& image,
00092   const vgl_point_3d<double>& p0,
00093   const vgl_vector_3d<double>& u,
00094   const vgl_vector_3d<double>& v,
00095   const vgl_vector_3d<double>& w,
00096   unsigned nu, unsigned nv, unsigned nw)
00097 {
00098   unsigned np = image.nplanes();
00099   vcl_ptrdiff_t istep = image.istep();
00100   vcl_ptrdiff_t jstep = image.jstep();
00101   vcl_ptrdiff_t kstep = image.kstep();
00102   vcl_ptrdiff_t pstep = image.planestep();
00103 
00104   vec.set_size(nu*nv*nw*np);
00105   vecType* vc = vec.begin();
00106 
00107   vgl_point_3d<double> p1 = p0;
00108 
00109   if (np==1)
00110   {
00111     const imType* plane0 = image.origin_ptr();
00112     for (unsigned i=0;i<nu;++i,p1+=u)
00113     {
00114       vgl_point_3d<double> p2 = p1;
00115       for (unsigned j=0;j<nv;++j,p2+=v)
00116       {
00117         vgl_point_3d<double> p = p2;
00118         // Sample each row (along w)
00119         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00120           *vc = vil3d_trilin_interp_raw(p.x(),p.y(),p.z(),
00121                                         plane0,istep,jstep,kstep);
00122       }
00123     }
00124   }
00125   else
00126   {
00127     for (unsigned i=0;i<nu;++i,p1+=u)
00128     {
00129       vgl_point_3d<double> p2 = p1;
00130       for (unsigned j=0;j<nv;++j,p2+=v)
00131       {
00132         vgl_point_3d<double> p = p2;
00133         // Sample each row (along w)
00134         for (unsigned l=0;l<nw;++l,p+=w)
00135           for (unsigned k=0;k<np;++k,++vc)
00136             *vc = vil3d_trilin_interp_raw(p.x(),p.y(),p.z(),
00137                                           image.origin_ptr()+k*pstep,istep,jstep,kstep);
00138       }
00139     }
00140   }
00141 }
00142 
00143 //: Sample grid p+i.u+j.v+k.w safely in image coordinates using trilinear interpolation.
00144 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00145 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00146 //  v[0]..v[np-1] are the values from point p
00147 //  Samples are taken along direction w first
00148 //  Points outside image return zero.
00149 template <class imType, class vecType>
00150 inline void vimt3d_sample_grid_trilin_ic_safe(
00151   vnl_vector<vecType>& vec,
00152   const vil3d_image_view<imType>& image,
00153   const vgl_point_3d<double>& p0,
00154   const vgl_vector_3d<double>& u,
00155   const vgl_vector_3d<double>& v,
00156   const vgl_vector_3d<double>& w,
00157   unsigned nu, unsigned nv, unsigned nw)
00158 {
00159   unsigned np = image.nplanes();
00160   unsigned ni = image.ni();
00161   unsigned nj = image.nj();
00162   unsigned nk = image.nk();
00163   vcl_ptrdiff_t istep = image.istep();
00164   vcl_ptrdiff_t jstep = image.jstep();
00165   vcl_ptrdiff_t kstep = image.kstep();
00166   vcl_ptrdiff_t pstep = image.planestep();
00167 
00168   vec.set_size(nu*nv*nw*np);
00169   vecType* vc = vec.begin();
00170 
00171   vgl_point_3d<double> p1 = p0;
00172 
00173   if (np==1)
00174   {
00175     const imType* plane0 = image.origin_ptr();
00176     for (unsigned i=0;i<nu;++i,p1+=u)
00177     {
00178       vgl_point_3d<double> p2 = p1;
00179       for (unsigned j=0;j<nv;++j,p2+=v)
00180       {
00181         vgl_point_3d<double> p = p2;
00182         // Sample each row (along w)
00183         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00184           *vc = vil3d_trilin_interp_safe(p.x(),p.y(),p.z(),plane0,ni,nj,nk,istep,jstep,kstep);
00185       }
00186     }
00187   }
00188   else
00189   {
00190     for (unsigned i=0;i<nu;++i,p1+=u)
00191     {
00192       vgl_point_3d<double> p2 = p1;
00193       for (unsigned j=0;j<nv;++j,p2+=v)
00194       {
00195         vgl_point_3d<double> p = p2;
00196         // Sample each row (along w)
00197         for (unsigned l=0;l<nw;++l,p+=w)
00198           for (unsigned k=0;k<np;++k,++vc)
00199             *vc = vil3d_trilin_interp_safe(p.x(),p.y(),p.z(),
00200                                            image.origin_ptr()+k*pstep,ni,nj,nk,istep,jstep,kstep);
00201       }
00202     }
00203   }
00204 }
00205 
00206 //: Sample grid p+i.u+j.v+k.w safely in image coordinates using trilinear interpolation.
00207 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00208 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00209 //  v[0]..v[np-1] are the values from point p
00210 //  Samples are taken along direction w first
00211 //  Points outside image are set to the nearest voxel's value.
00212 template <class imType, class vecType>
00213 inline void vimt3d_sample_grid_trilin_ic_extend(
00214   vnl_vector<vecType>& vec,
00215   const vil3d_image_view<imType>& image,
00216   const vgl_point_3d<double>& p0,
00217   const vgl_vector_3d<double>& u,
00218   const vgl_vector_3d<double>& v,
00219   const vgl_vector_3d<double>& w,
00220   unsigned nu, unsigned nv, unsigned nw)
00221 {
00222   unsigned np = image.nplanes();
00223   unsigned ni = image.ni();
00224   unsigned nj = image.nj();
00225   unsigned nk = image.nk();
00226   vcl_ptrdiff_t istep = image.istep();
00227   vcl_ptrdiff_t jstep = image.jstep();
00228   vcl_ptrdiff_t kstep = image.kstep();
00229   vcl_ptrdiff_t pstep = image.planestep();
00230 
00231   vec.set_size(nu*nv*nw*np);
00232   vecType* vc = vec.begin();
00233 
00234   vgl_point_3d<double> p1 = p0;
00235 
00236   if (np==1)
00237   {
00238     const imType* plane0 = image.origin_ptr();
00239     for (unsigned i=0;i<nu;++i,p1+=u)
00240     {
00241       vgl_point_3d<double> p2 = p1;
00242       for (unsigned j=0;j<nv;++j,p2+=v)
00243       {
00244         vgl_point_3d<double> p = p2;
00245         // Sample each row (along w)
00246         for (unsigned k=0;k<nw;++k,p+=w,++vc)
00247           *vc = vil3d_trilin_interp_safe_extend(p.x(),p.y(),p.z(),
00248                                                 plane0,ni,nj,nk,istep,jstep,kstep);
00249       }
00250     }
00251   }
00252   else
00253   {
00254     for (unsigned i=0;i<nu;++i,p1+=u)
00255     {
00256       vgl_point_3d<double> p2 = p1;
00257       for (unsigned j=0;j<nv;++j,p2+=v)
00258       {
00259         vgl_point_3d<double> p = p2;
00260         // Sample each row (along w)
00261         for (unsigned l=0;l<nw;++l,p+=w)
00262           for (unsigned k=0;k<np;++k,++vc)
00263             *vc = vil3d_trilin_interp_safe_extend(p.x(),p.y(),p.z(),
00264                                                   image.origin_ptr()+k*pstep,ni,nj,nk,istep,jstep,kstep);
00265       }
00266     }
00267   }
00268 }
00269 
00270 
00271 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in world coordinates.
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. Samples
00276 //  outside the image are set to the value of the nearest voxel's value.
00277 template <class imType, class vecType>
00278 void vimt3d_sample_grid_trilin_extend(
00279   vnl_vector<vecType>& vec,
00280   const vimt3d_image_3d_of<imType>& image,
00281   const vgl_point_3d<double>& p,
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   // convert to image coordinates
00288   vgl_point_3d<double> im_p0 = image.world2im()(p);
00289   vgl_vector_3d<double> im_u = image.world2im()(p+u)-im_p0;
00290   vgl_vector_3d<double> im_v = image.world2im()(p+v)-im_p0;
00291   vgl_vector_3d<double> im_w = image.world2im()(p+w)-im_p0;
00292 
00293   // call image coordinate version of grid sampler
00294   if (vimt3d_grid_in_image_ic(im_p0,im_u,im_v,im_w,nu,nv,nw,image.image()))
00295     vimt3d_sample_grid_trilin_ic_no_checks(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00296   else
00297     vimt3d_sample_grid_trilin_ic_extend(vec,image.image(),im_p0,im_u,im_v,im_w,nu,nv,nw);
00298 
00299   return;
00300 }
00301 
00302 
00303 //: Sample grid p+i.u+j.v+k.w using trilinear interpolation in image coordinates.
00304 //  Profile points are p+i.u+j.v+k.w, where i=[0..nu-1],j=[0..nv-1], k=[0..nw-1]
00305 //  Vector v is resized to nu*nv*nw*np elements, where np=image.n_planes().
00306 //  v[0]..v[np-1] are the values from point p
00307 //  Samples are taken along direction w first.
00308 //  Samples outside the image are set to 0.
00309 template <class imType, class vecType>
00310 void vimt3d_sample_grid_trilin_ic(vnl_vector<vecType>& vec,
00311                                   const vil3d_image_view<imType>& image,
00312                                   const vgl_point_3d<double>& im_p,
00313                                   const vgl_vector_3d<double>& im_u,
00314                                   const vgl_vector_3d<double>& im_v,
00315                                   const vgl_vector_3d<double>& im_w,
00316                                   unsigned nu, unsigned nv, unsigned nw)
00317 {
00318   if (vimt3d_grid_in_image_ic(im_p,im_u,im_v,im_w,nu,nv,nw,image))
00319     vimt3d_sample_grid_trilin_ic_no_checks(vec,image,im_p,im_u,im_v,im_w,nu,nv,nw);
00320   else
00321     vimt3d_sample_grid_trilin_ic_safe(vec,image,im_p,im_u,im_v,im_w,nu,nv,nw);
00322 
00323   return;
00324 }
00325 
00326 
00327 #define VIMT3D_SAMPLE_GRID_TRILIN_INSTANTIATE( imType, vecType ) \
00328 template void vimt3d_sample_grid_trilin( \
00329   vnl_vector<vecType >& vec, \
00330   const vimt3d_image_3d_of<imType >& image, \
00331   const vgl_point_3d<double >& p, \
00332   const vgl_vector_3d<double >& u, \
00333   const vgl_vector_3d<double >& v, \
00334   const vgl_vector_3d<double >& w, \
00335   unsigned nu, unsigned nv, unsigned nw); \
00336 template void vimt3d_sample_grid_trilin_extend( \
00337   vnl_vector<vecType >& vec, \
00338   const vimt3d_image_3d_of<imType >& image, \
00339   const vgl_point_3d<double >& p, \
00340   const vgl_vector_3d<double >& u, \
00341   const vgl_vector_3d<double >& v, \
00342   const vgl_vector_3d<double >& w, \
00343   unsigned nu, unsigned nv, unsigned nw); \
00344 template void vimt3d_sample_grid_trilin_ic( \
00345   vnl_vector<vecType >& vec, \
00346   const vil3d_image_view<imType >& image, \
00347   const vgl_point_3d<double >& im_p, \
00348   const vgl_vector_3d<double >& im_u, \
00349   const vgl_vector_3d<double >& im_v, \
00350   const vgl_vector_3d<double >& im_w, \
00351   unsigned nu, unsigned nv, unsigned nw)
00352 
00353 #endif // vimt3d_sample_grid_trilin_txx_