contrib/mul/vil3d/vil3d_resample_trilinear.txx

Go to the documentation of this file.
00001 // This is mul/vil3d/vil3d_resample_trilinear.txx
00002 #ifndef vil3d_resample_trilinear_txx_
00003 #define vil3d_resample_trilinear_txx_
00004 //:
00005 // \file
00006 // \brief Resample a 3D image by a different factor in each dimension
00007 // \author Kevin de Souza, Ian Scott
00008 
00009 #include "vil3d_resample_trilinear.h"
00010 
00011 #include <vil/vil_convert.h>
00012 #include <vil3d/vil3d_trilin_interp.h>
00013 #include <vil3d/vil3d_plane.h>
00014 #include <vcl_cassert.h>
00015 
00016 
00017 inline bool vil3d_grid_corner_in_image(double x0, double y0, double z0,
00018                                        const vil3d_image_view_base& image)
00019 {
00020   if (x0<0.0) return false;
00021   if (x0>image.ni()-1.0) return false;
00022   if (y0<0.0) return false;
00023   if (y0>image.nj()-1.0) return false;
00024   if (z0<0.0) return false;
00025   if (z0>image.nk()-1.0) return false;
00026   return true;
00027 }
00028 
00029 
00030 //  Sample grid of points in one image and place in another, using trilinear interpolation.
00031 //  dest_image(i,j,k,p) is sampled from the src_image at
00032 //  (x0+i.dx1+j.dx2+k.dx3, y0+i.dy1+j.dy2+k.dy3, z0+i.dz1+j.dz2+k.dz3),
00033 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1]
00034 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00035 //  Points outside image return value of nearest pixel.
00036 template <class S, class T>
00037 void vil3d_resample_trilinear_edge_extend(const vil3d_image_view<S>& src_image,
00038                                           vil3d_image_view<T>& dest_image,
00039                                           double x0, double y0, double z0,
00040                                           double dx1, double dy1, double dz1,
00041                                           double dx2, double dy2, double dz2,
00042                                           double dx3, double dy3, double dz3,
00043                                           int n1, int n2, int n3)
00044 {
00045   bool all_in_image =
00046     vil3d_grid_corner_in_image(x0,
00047                                y0,
00048                                z0,
00049                                src_image) &&
00050     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1,
00051                                y0 + (n1-1)*dy1,
00052                                z0 + (n1-1)*dz1,
00053                                src_image) &&
00054     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2,
00055                                y0 + (n2-1)*dy2,
00056                                z0 + (n2-1)*dz2,
00057                                src_image) &&
00058     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2,
00059                                y0 + (n1-1)*dy1 + (n2-1)*dy2,
00060                                z0 + (n1-1)*dz1 + (n2-1)*dz2,
00061                                src_image) &&
00062     vil3d_grid_corner_in_image(x0 + (n3-1)*dx3,
00063                                y0 + (n3-1)*dy3,
00064                                z0 + (n3-1)*dz3,
00065                                src_image) &&
00066     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n3-1)*dx3,
00067                                y0 + (n1-1)*dy1 + (n3-1)*dy3,
00068                                z0 + (n1-1)*dz1 + (n3-1)*dz3,
00069                                src_image) &&
00070     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2 + (n3-1)*dx3,
00071                                y0 + (n2-1)*dy2 + (n3-1)*dy3,
00072                                z0 + (n2-1)*dz2 + (n3-1)*dz3,
00073                                src_image) &&
00074     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3,
00075                                y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3,
00076                                z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3,
00077                                src_image);
00078 #ifndef NDEBUG
00079   // corners
00080   vcl_cout<<"src_image= "<<src_image<<vcl_endl
00081           <<"x0="<<x0<<vcl_endl
00082           <<"y0="<<y0<<vcl_endl
00083           <<"z0="<<z0<<vcl_endl
00084           <<"x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3="
00085           <<x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3<<vcl_endl
00086           <<"y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3="
00087           <<y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3<<vcl_endl
00088           <<"z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3="
00089           <<z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3<<vcl_endl;
00090 #endif
00091   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00092   // Rounds only if T is int, unsigned or kind of. Doesn't round if T
00093   // is float, double or kind of.
00094 
00095   const unsigned ni = src_image.ni();
00096   const unsigned nj = src_image.nj();
00097   const unsigned nk = src_image.nk();
00098   const unsigned np = src_image.nplanes();
00099   const vcl_ptrdiff_t istep = src_image.istep();
00100   const vcl_ptrdiff_t jstep = src_image.jstep();
00101   const vcl_ptrdiff_t kstep = src_image.kstep();
00102   const vcl_ptrdiff_t pstep = src_image.planestep();
00103   const S* plane0 = src_image.origin_ptr();
00104 
00105   dest_image.set_size(n1,n2,n3,np);
00106   const vcl_ptrdiff_t d_istep = dest_image.istep();
00107   const vcl_ptrdiff_t d_jstep = dest_image.jstep();
00108   const vcl_ptrdiff_t d_kstep = dest_image.kstep();
00109   const vcl_ptrdiff_t d_pstep = dest_image.planestep();
00110   T* d_plane0 = dest_image.origin_ptr();
00111 
00112   if (all_in_image)
00113   {
00114     if (np==1)
00115     {
00116       double xk=x0, yk=y0, zk=z0;
00117       T *slice = d_plane0;
00118       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00119       {
00120         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00121         T *row = slice;
00122         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00123         {
00124           double x=xj, y=yj, z=zj;  // Start of j-th row
00125           T *dpt = row;
00126           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00127             cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00128                                                               plane0,
00129                                                               istep, jstep, kstep ),
00130                                     *dpt);
00131         }
00132       }
00133     }
00134     else
00135     {
00136       double xk=x0, yk=y0, zk=z0;
00137       T *slice = d_plane0;
00138       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00139       {
00140         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00141         T *row = slice;
00142         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00143         {
00144           double x=xj, y=yj, z=zj;  // Start of j-th row
00145           T *dpt = row;
00146           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00147           {
00148             for (unsigned int p=0; p<np; ++p)
00149               cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00150                                                                 plane0+p*pstep,
00151                                                                 istep, jstep, kstep),
00152                                        dpt[p*d_pstep]);
00153           }
00154         }
00155       }
00156     }
00157   }
00158   else
00159   {
00160     // Use safe interpolation with edge-extension
00161     if (np==1)
00162     {
00163       double xk=x0, yk=y0, zk=z0;
00164       T *slice = d_plane0;
00165       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00166       {
00167         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00168         T *row = slice;
00169         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00170         {
00171           double x=xj, y=yj, z=zj;  // Start of j-th row
00172           T *dpt = row;
00173           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00174             cast_and_possibly_round( vil3d_trilin_interp_safe_extend( x, y, z,
00175                                                                       plane0,
00176                                                                       ni, nj, nk,
00177                                                                       istep, jstep, kstep),
00178                                      *dpt );
00179         }
00180       }
00181     }
00182     else
00183     {
00184       double xk=x0, yk=y0, zk=z0;
00185       T *slice = d_plane0;
00186       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00187       {
00188         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00189         T *row = slice;
00190         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00191         {
00192           double x=xj, y=yj, z=zj;  // Start of j-th row
00193           T *dpt = row;
00194           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00195           {
00196             for (unsigned int p=0; p<np; ++p)
00197               cast_and_possibly_round( vil3d_trilin_interp_safe_extend( x, y, z,
00198                                                                         plane0+p*pstep,
00199                                                                         ni, nj, nk,
00200                                                                         istep, jstep, kstep),
00201                                        dpt[p*d_pstep] );
00202           }
00203         }
00204       }
00205     }
00206   }
00207 }
00208 
00209 
00210 
00211 //  Sample grid of points in one image and place in another, using trilinear interpolation.
00212 //  dest_image(i,j,k,p) is sampled from the src_image at
00213 //  (x0+i.dx1+j.dx2+k.dx3, y0+i.dy1+j.dy2+k.dy3, z0+i.dz1+j.dz2+k.dz3),
00214 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1]
00215 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00216 //  Points outside image return zero or \a outval
00217 template <class S, class T>
00218 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00219                               vil3d_image_view<T>& dest_image,
00220                               double x0, double y0, double z0,
00221                               double dx1, double dy1, double dz1,
00222                               double dx2, double dy2, double dz2,
00223                               double dx3, double dy3, double dz3,
00224                               int n1, int n2, int n3,
00225                               T outval/*=0*/)
00226 {
00227   bool all_in_image =
00228     vil3d_grid_corner_in_image(x0,
00229                                y0,
00230                                z0,
00231                                src_image) &&
00232     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1,
00233                                y0 + (n1-1)*dy1,
00234                                z0 + (n1-1)*dz1,
00235                                src_image) &&
00236     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2,
00237                                y0 + (n2-1)*dy2,
00238                                z0 + (n2-1)*dz2,
00239                                src_image) &&
00240     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2,
00241                                y0 + (n1-1)*dy1 + (n2-1)*dy2,
00242                                z0 + (n1-1)*dz1 + (n2-1)*dz2,
00243                                src_image) &&
00244     vil3d_grid_corner_in_image(x0 + (n3-1)*dx3,
00245                                y0 + (n3-1)*dy3,
00246                                z0 + (n3-1)*dz3,
00247                                src_image) &&
00248     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n3-1)*dx3,
00249                                y0 + (n1-1)*dy1 + (n3-1)*dy3,
00250                                z0 + (n1-1)*dz1 + (n3-1)*dz3,
00251                                src_image) &&
00252     vil3d_grid_corner_in_image(x0 + (n2-1)*dx2 + (n3-1)*dx3,
00253                                y0 + (n2-1)*dy2 + (n3-1)*dy3,
00254                                z0 + (n2-1)*dz2 + (n3-1)*dz3,
00255                                src_image) &&
00256     vil3d_grid_corner_in_image(x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3,
00257                                y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3,
00258                                z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3,
00259                                src_image);
00260 #ifndef NDEBUG
00261   // corners
00262   vcl_cout<<"src_image= "<<src_image<<vcl_endl
00263           <<"x0="<<x0<<vcl_endl
00264           <<"y0="<<y0<<vcl_endl
00265           <<"z0="<<z0<<vcl_endl
00266           <<"x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3="
00267           <<x0 + (n1-1)*dx1 + (n2-1)*dx2 + (n3-1)*dx3<<vcl_endl
00268           <<"y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3="
00269           <<y0 + (n1-1)*dy1 + (n2-1)*dy2 + (n3-1)*dy3<<vcl_endl
00270           <<"z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3="
00271           <<z0 + (n1-1)*dz1 + (n2-1)*dz2 + (n3-1)*dz3<<vcl_endl;
00272 #endif
00273   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00274 
00275   const unsigned ni = src_image.ni();
00276   const unsigned nj = src_image.nj();
00277   const unsigned nk = src_image.nk();
00278   const unsigned np = src_image.nplanes();
00279   const vcl_ptrdiff_t istep = src_image.istep();
00280   const vcl_ptrdiff_t jstep = src_image.jstep();
00281   const vcl_ptrdiff_t kstep = src_image.kstep();
00282   const vcl_ptrdiff_t pstep = src_image.planestep();
00283   const S* plane0 = src_image.origin_ptr();
00284 
00285   dest_image.set_size(n1,n2,n3,np);
00286   const vcl_ptrdiff_t d_istep = dest_image.istep();
00287   const vcl_ptrdiff_t d_jstep = dest_image.jstep();
00288   const vcl_ptrdiff_t d_kstep = dest_image.kstep();
00289   const vcl_ptrdiff_t d_pstep = dest_image.planestep();
00290   T* d_plane0 = dest_image.origin_ptr();
00291 
00292   if (all_in_image)
00293   {
00294     if (np==1)
00295     {
00296       double xk=x0, yk=y0, zk=z0;
00297       T *slice = d_plane0;
00298       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00299       {
00300         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00301         T *row = slice;
00302         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00303         {
00304           double x=xj, y=yj, z=zj;  // Start of j-th row
00305           T *dpt = row;
00306           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00307             cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00308                                                               plane0,
00309                                                               istep, jstep, kstep),
00310                                      *dpt);
00311         }
00312       }
00313     }
00314     else
00315     {
00316       double xk=x0, yk=y0, zk=z0;
00317       T *slice = d_plane0;
00318       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00319       {
00320         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00321         T *row = slice;
00322         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00323         {
00324           double x=xj, y=yj, z=zj;  // Start of j-th row
00325           T *dpt = row;
00326           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00327           {
00328             for (unsigned int p=0; p<np; ++p)
00329               cast_and_possibly_round( vil3d_trilin_interp_raw( x, y, z,
00330                                                                 plane0+p*pstep,
00331                                                                 istep, jstep, kstep),
00332                                        dpt[p*d_pstep]);
00333           }
00334         }
00335       }
00336     }
00337   }
00338   else
00339   {
00340     // Use safe interpolation
00341     if (np==1)
00342     {
00343       double xk=x0, yk=y0, zk=z0;
00344       T *slice = d_plane0;
00345       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00346       {
00347         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00348         T *row = slice;
00349         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00350         {
00351           double x=xj, y=yj, z=zj;  // Start of j-th row
00352           T *dpt = row;
00353           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00354             cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00355                                                                plane0,
00356                                                                ni, nj, nk,
00357                                                                istep, jstep, kstep),
00358                                      *dpt);
00359         }
00360       }
00361     }
00362     else
00363     {
00364       double xk=x0, yk=y0, zk=z0;
00365       T *slice = d_plane0;
00366       for (int k=0; k<n3; ++k, xk+=dx3, yk+=dy3, zk+=dz3, slice+=d_kstep)
00367       {
00368         double xj=xk, yj=yk, zj=zk;  // Start of k-th slice
00369         T *row = slice;
00370         for (int j=0; j<n2; ++j, xj+=dx2, yj+=dy2, zj+=dz2, row+=d_jstep)
00371         {
00372           double x=xj, y=yj, z=zj;  // Start of j-th row
00373           T *dpt = row;
00374           for (int i=0; i<n1; ++i, x+=dx1, y+=dy1, z+=dz1, dpt+=d_istep)
00375           {
00376             for (unsigned int p=0; p<np; ++p)
00377               cast_and_possibly_round( vil3d_trilin_interp_safe( x, y, z,
00378                                                                  plane0+p*pstep,
00379                                                                  ni, nj, nk,
00380                                                                  istep, jstep, kstep),
00381                                        dpt[p*d_pstep]);
00382           }
00383         }
00384       }
00385     }
00386   }
00387 }
00388 
00389 
00390 //  Resample image to a specified dimensions (n1 * n2 * n3)
00391 template <class S, class T>
00392 void vil3d_resample_trilinear(const vil3d_image_view<S>& src_image,
00393                               vil3d_image_view<T>& dest_image,
00394                               int n1, int n2, int n3)
00395 {
00396   double f= 0.9999999; // so sampler doesn't go off edge of image
00397   double x0=0;
00398   double y0=0;
00399   double z0=0;
00400 
00401   double dx1=f*(src_image.ni()-1)*1.0/(n1-1);
00402   double dy1=0;
00403   double dz1=0;
00404 
00405   double dx2=0;
00406   double dy2=f*(src_image.nj()-1)*1.0/(n2-1);
00407   double dz2=0;
00408 
00409   double dx3=0;
00410   double dy3=0;
00411   double dz3=f*(src_image.nk()-1)*1.0/(n3-1);
00412 
00413   vil3d_resample_trilinear(src_image, dest_image, x0, y0, z0, dx1, dy1, dz1,
00414                            dx2, dy2, dz2, dx3, dy3, dz3, n1, n2, n3);
00415 }
00416 
00417 
00418 // Resample a 3D image by a different factor in each dimension.
00419 // Note: The upper image boundaries are extended.
00420 template <class T>
00421 void vil3d_resample_trilinear(const vil3d_image_view<T>& src_image,
00422                               vil3d_image_view<T>& dst_image,
00423                               const double dx,
00424                               const double dy,
00425                               const double dz)
00426 {
00427   assert (dx > 0.0 && dy > 0.0 && dz > 0.0);
00428 
00429   // Assume planes are the same for both images
00430   const unsigned np = src_image.nplanes();
00431 
00432   const unsigned sni = src_image.ni();
00433   const unsigned snj = src_image.nj();
00434   const unsigned snk = src_image.nk();
00435   const vcl_ptrdiff_t s_istep = src_image.istep();
00436   const vcl_ptrdiff_t s_jstep = src_image.jstep();
00437   const vcl_ptrdiff_t s_kstep = src_image.kstep();
00438   const vcl_ptrdiff_t s_pstep = src_image.planestep();
00439   const T* s_plane = src_image.origin_ptr();
00440 
00441   const unsigned dni = static_cast<unsigned>(sni*dx);
00442   const unsigned dnj = static_cast<unsigned>(snj*dy);
00443   const unsigned dnk = static_cast<unsigned>(snk*dz);
00444   dst_image.set_size(dni, dnj, dnk, np);
00445   const vcl_ptrdiff_t d_istep = dst_image.istep();
00446   const vcl_ptrdiff_t d_jstep = dst_image.jstep();
00447   const vcl_ptrdiff_t d_kstep = dst_image.kstep();
00448   const vcl_ptrdiff_t d_pstep = dst_image.planestep();
00449   T* d_plane = dst_image.origin_ptr();
00450 
00451   // Use this to convert from double to T with appropriate rounding
00452   vil_convert_round_pixel<double, T> cast_and_possibly_round;
00453 
00454   // Loop over all voxels in the destination image
00455   // and sample from the corresponding point in the source image
00456   // (except near upper boundaries).
00457   for (unsigned p=0; p<np; ++p, s_plane+=s_pstep, d_plane+=d_pstep)
00458   {
00459     T* d_slice = d_plane;
00460     for (unsigned k=0; k<static_cast<unsigned>(dnk-dz); ++k, d_slice+=d_kstep)
00461     {
00462       T* d_row = d_slice;
00463       for (unsigned j=0; j<static_cast<unsigned>(dnj-dy); ++j, d_row+=d_jstep)
00464       {
00465         T* d_pix = d_row;
00466         for (unsigned i=0; i<static_cast<unsigned>(dni-dx); ++i, d_pix+=d_istep)
00467         {
00468           cast_and_possibly_round( vil3d_trilin_interp_raw( i/dx, j/dy, k/dz,
00469                                                             s_plane,
00470                                                             s_istep, s_jstep, s_kstep),
00471                                    *d_pix);
00472         }
00473         // Process the pixels near the upper i boundary - safe_extend interpolation
00474         for (unsigned i=static_cast<unsigned>(dni-dx); i<dni; ++i, d_pix+=d_istep)
00475         {
00476           cast_and_possibly_round( vil3d_trilin_interp_safe_extend(i/dx, j/dy, k/dz,
00477                                                                    s_plane,
00478                                                                    sni, snj, snk,
00479                                                                    s_istep, s_jstep, s_kstep),
00480                                    *d_pix);
00481         }
00482       }
00483 
00484       // Process the pixels near the upper j boundary - safe_extend interpolation
00485       for (unsigned j=static_cast<unsigned>(dnj-dy); j<dnj; ++j, d_row+=d_jstep)
00486       {
00487         T* d_pix = d_row;
00488         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00489         {
00490           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00491                                                                     s_plane,
00492                                                                     sni, snj, snk,
00493                                                                     s_istep, s_jstep, s_kstep),
00494                                    *d_pix);
00495         }
00496       }
00497     }
00498 
00499     // Process the pixels near the upper k boundary - safe_extend interpolation
00500     for (unsigned k=static_cast<unsigned>(dnk-dz); k<dnk; ++k, d_slice+=d_kstep)
00501     {
00502       T* d_row = d_slice;
00503       for (unsigned j=0; j<dnj; ++j, d_row+=d_jstep)
00504       {
00505         T* d_pix = d_row;
00506         for (unsigned i=0; i<dni; ++i, d_pix+=d_istep)
00507         {
00508           cast_and_possibly_round( vil3d_trilin_interp_safe_extend( i/dx, j/dy, k/dz,
00509                                                                     s_plane,
00510                                                                     sni, snj, snk,
00511                                                                     s_istep, s_jstep, s_kstep),
00512                                    *d_pix);
00513         }
00514       }
00515     }
00516   }
00517 }
00518 
00519 
00520 template <class T>
00521 void vil3d_resample_trilinear_scale_2(
00522   const vil3d_image_view<T>& src_im,
00523   vil3d_image_view<T>& dest_im)
00524 {
00525   // Assume planes are the same for both images
00526   const unsigned np = src_im.nplanes();
00527 
00528   const unsigned ni = src_im.ni();
00529   const unsigned nj = src_im.nj();
00530   const unsigned nk = src_im.nk();
00531   dest_im.set_size(ni*2-1, nj*2-1, nk*2-1, np);
00532 
00533   for (unsigned p = 0; p<np; ++p)
00534   {
00535     const vil3d_image_view<T> src = vil3d_plane(src_im, p);
00536     vil3d_image_view<T> dest = vil3d_plane(dest_im, p);
00537 
00538     for (unsigned k=0; k<nk-1; ++k)
00539     {
00540       for (unsigned j=0; j<nj-1; ++j)
00541       {
00542         // Do all except last slice.
00543         for (unsigned i=0; i<ni-1; ++i)
00544         {
00545           // s0-s7 are the values at 8 neighbouring positions (on a cube) in src.
00546           // d0-d7 are the values at 8 neighbouring positions (on a cube of 1/8 the above cube's size) in dest.
00547           // They are aligned so that s0 = d0.
00548           // d6t2 is the value of d6 time 2, etc.
00549           T s0 = src(i,j,k);
00550           T s1 = src(i+1, j  , k  );
00551           T s2 = src(i,   j+1, k  );
00552           T s3 = src(i+1, j+1, k  );
00553           T s4 = src(i  , j  , k+1);
00554           T s5 = src(i+1, j  , k+1);
00555           T s6 = src(i  , j+1, k+1);
00556           T s7 = src(i+1, j+1, k+1);
00557                                     dest(2*i  , 2*j  , 2*k  ) = s0;
00558           T d1t2 = s0+s1;           dest(2*i+1, 2*j  , 2*k  ) = d1t2/2;
00559           T d2t2 = s0+s2;           dest(2*i  , 2*j+1, 2*k  ) = d2t2/2;
00560           T d4t2 = s0+s4;           dest(2*i  , 2*j  , 2*k+1) = d4t2/2;
00561           T d3t4 = d2t2 + s1+s3;    dest(2*i+1, 2*j+1, 2*k  ) = d3t4/4;
00562           T d5t4 = d4t2 + s1+s5;    dest(2*i+1, 2*j  , 2*k+1) = d5t4/4;
00563           T d6t4 = d4t2 + s2+s6;    dest(2*i  , 2*j+1, 2*k+1) = d6t4/4;
00564                                     dest(2*i+1, 2*j+1, 2*k+1) = (d6t4 + s1+s3+s5+s7)/8;
00565         }
00566         T s0 = src(ni-1, j  , k  );
00567         T s2 = src(ni-1, j+1, k  );
00568         T s4 = src(ni-1, j  , k+1);
00569         T s6 = src(ni-1, j+1, k+1);
00570         dest(ni*2-2, j*2  , k*2  ) = s0;
00571         dest(ni*2-2, j*2+1, k*2  ) = (s0 + s2)/2;
00572         dest(ni*2-2, j*2  , k*2+1) = (s0 + s4)/2;
00573         dest(ni*2-2, j*2+1, k*2+1) = (s0 + s2 + s4 + s6)/4;
00574       }
00575       // Do last plane
00576       for (unsigned i=0; i<ni-1; ++i)
00577       {
00578         T s0 = src(i  , nj-1, k  );
00579         T s1 = src(i+1, nj-1, k  );
00580         T s4 = src(i  , nj-1, k+1);
00581         T s5 = src(i+1, nj-1, k+1);
00582         dest(i*2  , nj*2-2, k*2  ) = s0;
00583         dest(i*2+1, nj*2-2, k*2  ) = (s0 + s1)/2;
00584         dest(i*2  , nj*2-2, k*2+1) = (s0 + s4)/2;
00585         dest(i*2+1, nj*2-2, k*2+1) = (s0 + s1 + s4 + s5)/4;
00586       }
00587       T s0 = src(ni-1, nj-1, k);
00588       dest(ni*2-2, nj*2-2, k*2  ) = s0;
00589       dest(ni*2-2, nj*2-2, k*2+1) = (s0 + src(ni-1, nj-1, k+1))/2;
00590     }
00591     // Do last plane
00592     for (unsigned j=0; j<nj-1; ++j)
00593     {
00594       for (unsigned i=0; i<ni-1; ++i)
00595       {
00596         T s0 = src(i  , j  , nk-1);
00597         T s1 = src(i+1, j  , nk-1);
00598         T s2 = src(i  , j+1, nk-1);
00599         T s3 = src(i+1, j+1, nk-1);
00600         dest(i*2  , j*2  , nk*2-2) = s0;
00601         dest(i*2+1, j*2  , nk*2-2) = (s0 + s1)/2;
00602         dest(i*2  , j*2+1, nk*2-2) = (s0 + s2)/2;
00603         dest(i*2+1, j*2+1, nk*2-2) = (s0 + s1 + s2 + s3)/4;
00604       }
00605       T s0 = src(ni-1, j, nk-1);
00606       dest(ni*2-2, j*2  , nk*2-2) = s0;
00607       dest(ni*2-2, j*2+1, nk*2-2) = (s0 + src(ni-1, j+1, nk-1))/2;
00608     }
00609     for (unsigned i=0; i<ni-1; ++i)
00610     {
00611       T s0 = src(i, nj-1, nk-1);
00612       dest(i*2  , nj*2-2, nk*2-2) = s0;
00613       dest(i*2+1, nj*2-2, nk*2-2) = (s0 + src(i+1, nj-1, nk-1))/2;
00614     }
00615     dest(ni*2-2, nj*2-2, nk*2-2) = src(ni-1, nj-1, nk-1);
00616   }
00617 }
00618 
00619 
00620 #define VIL3D_RESAMPLE_TRILINEAR_INSTANTIATE( T, S ) \
00621 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00622                                        vil3d_image_view< T >& dest_image, \
00623                                        double x0, double y0, double z0, \
00624                                        double dx1, double dy1, double dz1, \
00625                                        double dx2, double dy2, double dz2, \
00626                                        double dx3, double dy3, double dz3, \
00627                                        int n1, int n2, int n3, \
00628                                        T outval); \
00629 template void vil3d_resample_trilinear_edge_extend(const vil3d_image_view< S >& src_image, \
00630                                                    vil3d_image_view< T >& dest_image, \
00631                                                    double x0, double y0, double z0, \
00632                                                    double dx1, double dy1, double dz1, \
00633                                                    double dx2, double dy2, double dz2, \
00634                                                    double dx3, double dy3, double dz3, \
00635                                                    int n1, int n2, int n3); \
00636 template void vil3d_resample_trilinear(const vil3d_image_view< S >& src_image, \
00637                                        vil3d_image_view< T >& dest_image, \
00638                                        int n1, int n2, int n3); \
00639 template void vil3d_resample_trilinear(const vil3d_image_view< T >& src_image, \
00640                                        vil3d_image_view< T >& dst_image, \
00641                                        const double dx, \
00642                                        const double dy, \
00643                                        const double dz); \
00644 template void vil3d_resample_trilinear_scale_2(const vil3d_image_view< T >& src_image, \
00645                                                vil3d_image_view< T >& dst_image)
00646 
00647 #endif // vil3d_resample_trilinear_txx_

Generated on Mon Nov 23 05:15:07 2009 for contrib/mul/vil3d by  doxygen 1.5.1