contrib/mul/vil3d/algo/vil3d_world_gradients.txx
Go to the documentation of this file.
00001 // This is mul/vil3d/algo/vil3d_world_gradients.txx
00002 #ifndef vil3d_world_gradients_txx_
00003 #define vil3d_world_gradients_txx_
00004 //:
00005 // \file
00006 // \brief Given image gradients compute world gradients and gradient magnitude
00007 // \author Tim Cootes
00008 
00009 #include "vil3d_world_gradients.h"
00010 #include <vil3d/algo/vil3d_fill_border.h>
00011 #include <vil3d/vil3d_transform.h>
00012 #include <vil3d/vil3d_plane.h>
00013 #include <vcl_cmath.h>
00014 #include <vcl_cassert.h>
00015 
00016 //: Functor class to scale by s
00017 class vil3d_math_scale_functor
00018 {
00019  private:
00020   double s_;
00021  public:
00022   vil3d_math_scale_functor(double s) : s_(s) {}
00023   float operator()(vxl_byte x) const { return float(s_*x); }
00024   float operator()(unsigned x) const { return float(s_*x); }
00025   float operator()(short x) const { return float(s_*x); }
00026   float operator()(int x) const { return float(s_*x); }
00027   float operator()(float x) const { return float(s_*x); }
00028   float operator()(double x) const { return float(s_*x); }
00029 };
00030 
00031 //: Given image gradients compute world gradients and gradient magnitude
00032 //  Input gradient images are assumed to be un-normalised pixel gradients
00033 //  (ie no scaling has been done to take account of world pixel widths).
00034 //  Divides each by corresponding pixel dimension to give gradient in world units
00035 //  (ie intensity change per unit world length) in world_grad (3 plane image)
00036 //  The gradient magnitude output is in units of intensity change per world length
00037 //  (ie it does take account of voxel sizes).
00038 //
00039 //  Note: Currently assumes single plane only.
00040 //  1 pixel border around output set to zero.
00041 //
00042 // \relatesalso vil3d_image_view
00043 template<class srcT, class destT>
00044 void vil3d_world_gradients(const vil3d_image_view<srcT>& grad_i,
00045                            const vil3d_image_view<srcT>& grad_j,
00046                            const vil3d_image_view<srcT>& grad_k,
00047                            double voxel_width_i,
00048                            double voxel_width_j,
00049                            double voxel_width_k,
00050                            vil3d_image_view<destT>& world_grad,
00051                            vil3d_image_view<destT>& grad_mag)
00052 {
00053   assert(grad_i.nplanes()==grad_j.nplanes());
00054   assert(grad_i.nplanes()==grad_k.nplanes());
00055   assert(grad_i.nplanes()==1);
00056   unsigned ni = grad_i.ni(), nj = grad_i.nj(), nk = grad_i.nk();
00057   assert(ni>2 && nj>2 && nk>2);
00058   assert(grad_j.ni()==ni && grad_j.nj()==nj && grad_j.nk()==nk);
00059   assert(grad_k.ni()==ni && grad_k.nj()==nj && grad_k.nk()==nk);
00060   world_grad.set_size(ni,nj,nk,3);
00061   grad_mag.set_size(ni,nj,nk,1);
00062 
00063   vil3d_image_view<destT> w_grad_i=vil3d_plane(world_grad,0);
00064   vil3d_image_view<destT> w_grad_j=vil3d_plane(world_grad,1);
00065   vil3d_image_view<destT> w_grad_k=vil3d_plane(world_grad,2);
00066 
00067   vil3d_transform(grad_i,w_grad_i,vil3d_math_scale_functor(1.0/voxel_width_i));
00068   vil3d_transform(grad_j,w_grad_j,vil3d_math_scale_functor(1.0/voxel_width_j));
00069   vil3d_transform(grad_k,w_grad_k,vil3d_math_scale_functor(1.0/voxel_width_k));
00070 
00071   // Fill 1 voxel border with zero
00072   vil3d_fill_border(grad_mag,1,1,1,destT(0));
00073 
00074   const vcl_ptrdiff_t gi_istep = w_grad_i.istep(), gi_jstep = w_grad_i.jstep(),
00075                       gi_kstep = w_grad_i.kstep();
00076   const vcl_ptrdiff_t gj_istep = w_grad_j.istep(), gj_jstep = w_grad_j.jstep(),
00077                       gj_kstep = w_grad_j.kstep();
00078   const vcl_ptrdiff_t gk_istep = w_grad_k.istep(), gk_jstep = w_grad_k.jstep(),
00079                       gk_kstep = w_grad_k.kstep();
00080   const vcl_ptrdiff_t gm_istep = grad_mag.istep(), gm_jstep = grad_mag.jstep(),
00081                       gm_kstep = grad_mag.kstep();
00082 
00083   unsigned ihi=ni-2;
00084   unsigned jhi=nj-2;
00085   unsigned khi=nk-2;
00086 
00087   // Scaling to allow for relative size of voxels
00088   double c2i=1.0/(voxel_width_i*voxel_width_i);
00089   double c2j=1.0/(voxel_width_j*voxel_width_j);
00090   double c2k=1.0/(voxel_width_k*voxel_width_k);
00091 
00092   // Compute gradient magnitude at every point
00093   const srcT * gi_slice = &w_grad_i(1,1,1);
00094   const srcT * gj_slice = &w_grad_j(1,1,1);
00095   const srcT * gk_slice = &w_grad_k(1,1,1);
00096   destT * gm_slice = &grad_mag(1,1,1);
00097 
00098   for (unsigned k=1; k<=khi; ++k, gi_slice+=gi_kstep, gj_slice+=gj_kstep,
00099                                   gk_slice+=gk_kstep, gm_slice+=gm_kstep)
00100   {
00101     const srcT* gi_row=gi_slice;
00102     const srcT* gj_row=gj_slice;
00103     const srcT* gk_row=gk_slice;
00104     destT *gm_row = gm_slice;
00105 
00106     for (unsigned j=2; j<=jhi; ++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00107                                     gk_row+=gk_jstep, gm_row+=gm_jstep)
00108     {
00109       const srcT* pgi = gi_row;
00110       const srcT* pgj = gj_row;
00111       const srcT* pgk = gk_row;
00112       destT *pgm = gm_row;
00113       for (unsigned i=2; i<=ihi; ++i, pgi+=gi_istep, pgj+=gj_istep,
00114                                       pgk+=gk_istep, pgm+=gm_istep)
00115       {
00116         *pgm=destT(vcl_sqrt(double(c2i*pgi[0]*pgi[0] + c2j*pgj[0]*pgj[0] + c2k*pgk[0]*pgk[0])));
00117       }
00118     }
00119   }
00120 }
00121 
00122 #undef VIL3D_WORLD_GRADIENTS_INSTANTIATE
00123 #define VIL3D_WORLD_GRADIENTS_INSTANTIATE(srcT, destT) \
00124 template void vil3d_world_gradients(const vil3d_image_view<srcT >& grad_i,\
00125                                     const vil3d_image_view<srcT >& grad_j,\
00126                                     const vil3d_image_view<srcT >& grad_k,\
00127                                     double voxel_width_i,\
00128                                     double voxel_width_j,\
00129                                     double voxel_width_k,\
00130                                     vil3d_image_view<destT >& world_grad,\
00131                                     vil3d_image_view<destT >& grad_mag)
00132 
00133 #endif // vil3d_world_gradients_txx_