contrib/mul/vimt3d/vimt3d_resample_trilinear.h
Go to the documentation of this file.
00001 // This is mul/vimt3d/vimt3d_resample_trilinear.h
00002 #ifndef vimt3d_resample_trilinear_h_
00003 #define vimt3d_resample_trilinear_h_
00004 //:
00005 // \file
00006 // \brief Resample a 3D image by a different factor in each dimension
00007 // \author Kevin de Souza
00008 
00009 #include <vgl/vgl_point_3d.h>
00010 #include <vgl/vgl_vector_3d.h>
00011 #include <vil3d/vil3d_image_view.h>
00012 #include <vil3d/algo/vil3d_gauss_reduce.h>
00013 #include <vil3d/vil3d_resample_trilinear.h>
00014 #include <vimt3d/vimt3d_image_3d_of.h>
00015 
00016 //: Resample a 3D image by a factor of 2 in each dimension.
00017 // \p dst_image has size 2*src.image().n?()-1 in each direction.
00018 // Transform is modified by an appropriate scaling of 0.5
00019 // Interpolated values are truncated when the type T is smaller than double.
00020 // \sa vil3d_resample_trilinear_scale_2()
00021 template <class T>
00022 void vimt3d_resample_trilinear_scale_2(
00023   const vimt3d_image_3d_of<T>& src,
00024   vimt3d_image_3d_of<T>& dst)
00025 {
00026   vil3d_resample_trilinear_scale_2(src.image(), dst.image());
00027 
00028   vimt3d_transform_3d scaling;
00029   scaling.set_zoom_only(2.0, 2.0, 2.0, 0.0, 0.0, 0.0);
00030   dst.set_world2im(scaling * src.world2im());
00031 }
00032 
00033 
00034 //: Sample grid of points in one image and place in another, using trilinear interpolation.
00035 //  dest_image(i,j,k,p) is sampled from the src_image at p+i.u+j.v+k.w,
00036 //  where i=[0..n1-1], j=[0..n2-1], k=[0..n3-1] in world co-ordinates.
00037 //
00038 //  dest_image resized to (n1,n2,n3,src_image.nplanes())
00039 //
00040 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00041 //
00042 //  Points outside image return zero or \a outval
00043 template <class sType, class dType>
00044 inline void vimt3d_resample_trilinear(
00045   const vimt3d_image_3d_of<sType>& src_image,
00046   vimt3d_image_3d_of<dType>& dest_image,
00047   const vgl_point_3d<double>& p,
00048   const vgl_vector_3d<double>& u,
00049   const vgl_vector_3d<double>& v,
00050   const vgl_vector_3d<double>& w,
00051   int n1, int n2, int n3,
00052   dType outval=0, double edge_tol=0)
00053 {
00054   const vimt3d_transform_3d& s_w2i = src_image.world2im();
00055   vgl_point_3d<double> im_p = s_w2i(p);
00056   vgl_vector_3d<double> im_u = s_w2i.delta(p, u);
00057   vgl_vector_3d<double> im_v = s_w2i.delta(p, v);
00058   vgl_vector_3d<double> im_w = s_w2i.delta(p, w);
00059 
00060   vil3d_resample_trilinear(src_image.image(),dest_image.image(),
00061                            im_p.x(), im_p.y(), im_p.z(),
00062                            im_u.x(), im_u.y(), im_u.z(),
00063                            im_v.x(), im_v.y(), im_v.z(),
00064                            im_w.x(), im_w.y(), im_w.z(),
00065                            n1, n2, n3,
00066                            outval, edge_tol);
00067 
00068   // Point (i,j,k) in dest corresponds to p+i.u+j.v+k.w,
00069   // an affine transformation for image to world
00070   vimt3d_transform_3d d_i2w;
00071   d_i2w.set_affine(p,u,v,w);
00072   d_i2w.simplify();
00073   dest_image.set_world2im(d_i2w.inverse());
00074 }
00075 
00076 
00077 //: Sample grid of points in one image and place in another, using trilinear interpolation.
00078 //  dest_image(i,j,k,p) is sampled from the src_image at
00079 //  p+i.u+j.v+k.w, where i=[0..nk-1], j=[0..nj-1], k=[0..nk-1] in world co-ordinates.
00080 //
00081 //  dest_image resized to (ni,nj,nk,src_image.nplanes())
00082 //
00083 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00084 //
00085 //  Points outside image return the value of the nearest valid pixel.
00086 // \relatesalso vimt3d_image_3d_of
00087 template <class sType, class dType>
00088 inline void vimt3d_resample_trilin_edge_extend(
00089   const vimt3d_image_3d_of<sType>& src_image,
00090   vimt3d_image_3d_of<dType>& dest_image,
00091   const vgl_point_3d<double>& p,
00092   const vgl_vector_3d<double>& u,
00093   const vgl_vector_3d<double>& v,
00094   const vgl_vector_3d<double>& w,
00095   int ni, int nj, int nk)
00096 {
00097   const vimt3d_transform_3d& s_w2i = src_image.world2im();
00098   vgl_point_3d<double> im_p = s_w2i(p);
00099   vgl_vector_3d<double> im_u = s_w2i.delta(p, u);
00100   vgl_vector_3d<double> im_v = s_w2i.delta(p, v);
00101   vgl_vector_3d<double> im_w = s_w2i.delta(p, w);
00102 
00103   vil3d_resample_trilinear_edge_extend(src_image.image(),dest_image.image(),
00104                                        im_p.x(),im_p.y(),im_p.z(), im_u.x(),im_u.y(),im_u.z(),
00105                                        im_v.x(),im_v.y(),im_v.z(), im_w.x(),im_w.y(),im_w.z(), ni,nj,nk);
00106 
00107   // Point (i,j,k) in dest corresponds to p+i.u+j.v+k.w,
00108   // an affine transformation for image to world
00109   vimt3d_transform_3d d_i2w;
00110   d_i2w.set_affine(p,u,v,w);
00111   d_i2w.simplify();
00112   dest_image.set_world2im(d_i2w.inverse());
00113 }
00114 
00115 
00116 //: Resample an image using appropriate smoothing if the resolution changes significantly.
00117 //  dest_image(i,j,k,p) is sampled from the src_image at
00118 //  p+i.u+j.v+k.w, where i=[0..ni-1], j=[0..nj-1], k=[0..nk-1] in world co-ordinates.
00119 //
00120 //  dest_image resized to (ni,nj,nk,src_image.nplanes())
00121 //
00122 //  dest_image.world2im() set up so that the world co-ordinates in src and dest match
00123 //
00124 //  Points outside image return the value of the nearest valid pixel.
00125 // \relatesalso vimt3d_image_3d_of
00126 template <class sType, class dType>
00127 inline void vimt3d_resample_trilin_smoothing_edge_extend(
00128   const vimt3d_image_3d_of<sType>& src_image,
00129   vimt3d_image_3d_of<dType>& dest_image,
00130   const vgl_point_3d<double>& p,
00131   const vgl_vector_3d<double>& u,
00132   const vgl_vector_3d<double>& v,
00133   const vgl_vector_3d<double>& w,
00134   int ni, int nj, int nk)
00135 {
00136   vimt3d_transform_3d scaling;
00137   scaling.set_zoom_only(0.5,0,0,0);
00138 
00139   vimt3d_image_3d_of<sType> im = src_image;
00140   vgl_vector_3d<double> im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v)
00141     + im.world2im().delta(p, w);
00142 
00143   // If step length (in pixels) >> 1, smooth and reduce image x2.
00144   // Don't use strict Nyqusit limit.
00145   // Since we are just using factor 2 smoothing and reduction,
00146   // we have to tradeoff aliasing with information loss.
00147   while (im_d.length() > 1.33*1.732 && im.image().ni() > 5 && im.image().nj() > 5 && im.image().nk() > 5)
00148   {
00149     vimt3d_image_3d_of<sType> dest;
00150     vil3d_image_view<sType> work1, work2;
00151     vil3d_gauss_reduce(im.image(), dest.image(), work1, work2);
00152 
00153     dest.set_world2im(scaling * im.world2im());
00154 
00155     // re-establish loop invariant
00156     im = dest;
00157     im_d = im.world2im().delta(p, u) + im.world2im().delta(p, v) + im.world2im().delta(p, w);
00158   }
00159 
00160   vimt3d_resample_trilin_edge_extend(im, dest_image, p, u, v, w, ni, nj, nk);
00161 }
00162 
00163 //: Resample src, using the grid defined by dest.
00164 //  Smooths appropriately if the resolution changes significantly.
00165 //  dest(i,j,k,p) is sampled from src at the wc grid defined by
00166 //  the world co-ords of the pixel centres in dest.
00167 //
00168 //  dest is not resized, nor has its world2im transform modified.
00169 //
00170 //  Points outside src return the value of the nearest valid pixel.
00171 // \relatesalso vimt3d_image_3d_of
00172 template <class sType, class dType>
00173 inline void vimt3d_resample_trilin_smoothing_edge_extend(
00174   const vimt3d_image_3d_of<sType>& src,
00175   vimt3d_image_3d_of<dType>& dest)
00176 {
00177   vimt3d_transform_3d orig_w2i = dest.world2im();
00178   vimt3d_transform_3d i2w = orig_w2i.inverse();
00179 
00180   vimt3d_resample_trilin_smoothing_edge_extend(
00181     src, dest,
00182     i2w.origin(),
00183     i2w.delta(vgl_point_3d<double>(0,0,0), vgl_vector_3d<double>(1,0,0)),
00184     i2w.delta(vgl_point_3d<double>(0,0,0), vgl_vector_3d<double>(0,1,0)),
00185     i2w.delta(vgl_point_3d<double>(0,0,0), vgl_vector_3d<double>(0,0,1)),
00186     dest.image().ni(), dest.image().nj(), dest.image().nk() );
00187 
00188   dest.world2im() = orig_w2i;
00189 }
00190 
00191 
00192 #endif // vimt3d_resample_trilinear_h_