contrib/mul/vil3d/algo/vil3d_quad_distance_function.h
Go to the documentation of this file.
00001 #ifndef vil3d_quad_distance_function_h_
00002 #define vil3d_quad_distance_function_h_
00003 //:
00004 //  \file
00005 //  \brief Functions to compute quadratic distance functions
00006 //  \author Tim Cootes
00007 
00008 #include <vil3d/vil3d_image_view.h>
00009 #include <vil3d/vil3d_plane.h>
00010 #include <vil3d/vil3d_switch_axes.h>
00011 #include <vil/algo/vil_quad_distance_function.h>
00012 #include <vcl_cassert.h>
00013 
00014 //: Apply quadratic distance transform along each row of src
00015 //
00016 //  dest(x,y,z)=min_i (src(x+i,y,z)+ai(i^2))
00017 template<class srcT, class destT>
00018 inline void vil3d_quad_distance_function_i(const vil3d_image_view<srcT>& src,
00019                                            double ai,
00020                                            vil3d_image_view<destT>& dest)
00021 {
00022   assert(src.nplanes()==1);
00023   unsigned int ni=src.ni(),nj=src.nj(),nk=src.nk();
00024   dest.set_size(ni,nj,nk);
00025   vcl_ptrdiff_t s_istep = src.istep(),   s_jstep = src.jstep(), s_kstep = src.kstep();
00026   vcl_ptrdiff_t d_istep = dest.istep(),  d_jstep = dest.jstep(), d_kstep = dest.kstep();
00027 
00028   const srcT* s_plane = src.origin_ptr();
00029   destT*      d_plane = dest.origin_ptr();
00030 
00031   vcl_vector<double> x,y,z;
00032 
00033   // Apply transform along i direction
00034   for (unsigned k=0;k<nk;++k, s_plane+=s_kstep, d_plane+=d_kstep)
00035   {
00036     const srcT* s_row = s_plane;
00037     destT* d_row = d_plane;
00038     for (unsigned int j=0;j<nj;++j, s_row+=s_jstep, d_row+=d_jstep)
00039     {
00040       vil_quad_envelope(s_row,s_istep,ni,x,y,z,ai);
00041       vil_sample_quad_envelope(x,y,z,ai,d_row,d_istep,ni);
00042     }
00043   }
00044 }
00045 
00046 
00047 //: Apply quadratic distance transform
00048 //
00049 //  dest(x,y,z)=min_i,j,k (src(x+i,y+j,z+k)+ai(i^2)+aj(j^2)+ak(k^2))
00050 template<class srcT, class destT>
00051 inline void vil3d_quad_distance_function(const vil3d_image_view<srcT>& src,
00052                                        double ai, double aj, double ak,
00053                                        vil3d_image_view<destT>& dest)
00054 {
00055   assert(src.nplanes()==1);
00056 
00057   unsigned int ni=src.ni(),nj=src.nj(),nk=src.nk();
00058   vil3d_image_view<destT> tmp(ni,nj,nk);  // Intermediate result
00059 
00060   // Apply along i and store in dest temporarily
00061   vil3d_quad_distance_function_i(src,ai,dest);
00062 
00063   // Apply along j by switching axes, storing result in tmp
00064   vil3d_image_view<destT> tmp_j1 = vil3d_switch_axes_jik(dest);
00065   vil3d_image_view<destT> tmp_j2 = vil3d_switch_axes_jik(tmp);
00066   vil3d_quad_distance_function_i(tmp_j1,aj,tmp_j2);
00067 
00068   // Apply along k by switching axes, storing result in dest
00069   vil3d_image_view<destT> tmp_k1 = vil3d_switch_axes_kij(tmp);
00070   vil3d_image_view<destT> tmp_k2 = vil3d_switch_axes_kij(dest);
00071   vil3d_quad_distance_function_i(tmp_k1,ak,tmp_k2);
00072 }
00073 
00074 //: Apply quadratic distance transform along i, storing relative position of minima
00075 //
00076 //  dest(x,y,z)=min_i (src(x+i,y,z)+ai(i^2))
00077 //  (pos(x,y,0)) gives the position (x+i,y,z) leading to minima
00078 template<class srcT, class destT, class posT>
00079 inline void vil3d_quad_distance_function_i(const vil3d_image_view<srcT>& src,
00080                                            double ai,
00081                                            vil3d_image_view<destT>& dest,
00082                                            vil3d_image_view<posT>& pos)
00083 {
00084   assert(src.nplanes()==1);
00085   unsigned int ni=src.ni(), nj=src.nj(), nk=src.nk();
00086   dest.set_size(ni,nj,nk);
00087   pos.set_size(ni,nj,nk,1);
00088   vcl_ptrdiff_t s_istep = src.istep(),  s_jstep = src.jstep(),  s_kstep = src.kstep();
00089   vcl_ptrdiff_t d_istep = dest.istep(), d_jstep = dest.jstep(), d_kstep = dest.kstep();
00090   vcl_ptrdiff_t  p_istep = pos.istep(), p_jstep = pos.jstep(),  p_kstep = pos.kstep();
00091 
00092   const srcT* s_plane = src.origin_ptr();
00093   destT*      d_plane = dest.origin_ptr();
00094   posT*       p_plane  = pos.origin_ptr();
00095 
00096   vcl_vector<double> x,y,z;
00097 
00098   // Apply transform along i direction to get tmp
00099   for (unsigned k=0;k<nk;++k,s_plane+=s_kstep,d_plane+=d_kstep,p_plane+=p_kstep)
00100   {
00101     const srcT* s_row = s_plane;
00102     destT*      d_row = d_plane;
00103     posT*       p_row = p_plane;
00104     for (unsigned j=0;j<nj;++j,s_row+=s_jstep,d_row+=d_jstep,p_row+=p_jstep)
00105     {
00106      vil_quad_envelope(s_row,s_istep,ni,x,y,z,ai);
00107      vil_sample_quad_envelope_with_pos(x,y,z,ai,d_row,d_istep,ni,p_row,p_istep);
00108     }
00109   }
00110 }
00111 
00112 //: Apply quadratic distance transform, storing relative position of minima
00113 //
00114 //  dest(x,y,z)=min_i,j,k (src(x+i,y+j,z+k)+ai(i^2)+aj(j^2)+ak(k^2))
00115 //  (pos(x,y,0),pos(x,y,1),pos(x,y,2))
00116 //  gives the position (x+i,y+j,z+k) leading to minima
00117 template<class srcT, class destT, class posT>
00118 inline void vil3d_quad_distance_function(const vil3d_image_view<srcT>& src,
00119                                        double ai, double aj, double ak,
00120                                        vil3d_image_view<destT>& dest,
00121                                        vil3d_image_view<posT>& pos)
00122 {
00123   assert(src.nplanes()==1);
00124   unsigned int ni=src.ni(), nj=src.nj(), nk=src.nk();
00125   pos.set_size(ni,nj,nk,3);
00126 
00127   // Apply transformation along i
00128   vil3d_image_view<destT> tmp_i(ni,nj,nk);
00129   vil3d_image_view<posT>  pos_i(ni,nj,nk);
00130   vil3d_quad_distance_function_i(src,ai,tmp_i,pos_i);
00131 
00132   // Apply transformation along j by switching axes
00133   vil3d_image_view<destT> tmp_j(ni,nj,nk);
00134   vil3d_image_view<posT>  pos_j(ni,nj,nk);
00135   vil3d_image_view<destT> tmp_i1 = vil3d_switch_axes_jik(tmp_i);
00136   vil3d_image_view<destT> tmp_j1 = vil3d_switch_axes_jik(tmp_j);
00137   vil3d_image_view<posT>  pos_j1 = vil3d_switch_axes_jik(pos_j);
00138   vil3d_quad_distance_function_i(tmp_i1,aj,tmp_j1,pos_j1);
00139 
00140   // Apply transformation along k by switching axes
00141   dest.set_size(ni,nj,nk);
00142   vil3d_image_view<posT>  pos_k = vil3d_plane(pos,2);
00143   vil3d_image_view<destT> tmp_k = vil3d_switch_axes_kij(tmp_j);
00144   vil3d_image_view<destT> dest_k = vil3d_switch_axes_kij(dest);
00145   vil3d_image_view<posT>  pos_k1 = vil3d_switch_axes_kij(pos_k);
00146   vil3d_quad_distance_function_i(tmp_k,ak,dest_k,pos_k1);
00147 
00148   // Now deduce the relative positions
00149   for (unsigned k=0;k<nk;++k)
00150     for (unsigned j=0;j<nj;++j)
00151       for (unsigned i=0;i<ni;++i)
00152       {
00153         pos(i,j,k,1)=pos_j(i,j,pos_k(i,j,k));
00154         pos(i,j,k,0)=pos_i(i,pos(i,j,k,1),pos_k(i,j,k));
00155       }
00156 }
00157 
00158 #endif