contrib/mul/vil3d/algo/vil3d_convolve_1d.h
Go to the documentation of this file.
00001 // This is mul/vil3d/algo/vil3d_convolve_1d.h
00002 #ifndef vil3d_algo_convolve_1d_h_
00003 #define vil3d_algo_convolve_1d_h_
00004 //:
00005 // \file
00006 // \brief 1D Convolution with cunning boundary options
00007 // \author Ian Scott
00008 //
00009 // Note. The convolution operation is defined by
00010 //    $(f*g)(x) = \int f(x-y) g(y) dy$
00011 // i.e. the kernel g is reflected before the integration is performed.
00012 // If you don't want this to happen, the behaviour you want is not
00013 // called "convolution".
00014 
00015 #include <vcl_cassert.h>
00016 #include <vil/algo/vil_convolve_1d.h>
00017 
00018 //: Convolve kernel[i] (i in [k_lo,k_hi]) with srcT in i-direction
00019 // On exit dest_im(i,j) = sum src_m(i-x,j)*kernel(x)  (x=k_lo..k_hi)
00020 // \note  This function reverses the kernel. If you don't want the
00021 // kernel reversed, use vil_correlate_1d instead. The kernel must
00022 // not be larger than src_im.ni()
00023 // \param kernel should point to tap 0.
00024 // \param dest_im will be resized to size of src_im.
00025 //
00026 // If you want to convolve in all three directions, use the following approach:
00027 // verbatim
00028 //  vil3d_convolve_1d(                             src, smoothed1, ... );
00029 //
00030 //  vil3d_convolve_1d(vil3d_switch_axes_jki(smoothed1), smoothed2, ... );
00031 //  smoothed2_im = vil3d_switch_axes_kij(smoothed2);
00032 //
00033 //  vil3d_convolve_1d(vil3d_switch_axes_kij(smoothed2), smoothed3, ... );
00034 //  smoothed3_im = vil3d_switch_axes_jki(smoothed3);
00035 //
00036 // \endverbatim
00037 // \relatesalso vil3d_image_view
00038 
00039 template <class srcT, class destT, class kernelT, class accumT>
00040 inline void vil3d_convolve_1d(const vil3d_image_view<srcT>& src_im,
00041                               vil3d_image_view<destT>& dest_im,
00042                               const kernelT* kernel,
00043                               vcl_ptrdiff_t k_lo, vcl_ptrdiff_t k_hi,
00044                               accumT ac,
00045                               enum vil_convolve_boundary_option start_option,
00046                               enum vil_convolve_boundary_option end_option)
00047 {
00048   const unsigned n_i = src_im.ni(),
00049                  n_j = src_im.nj(),
00050                  n_k = src_im.nk(),
00051                  n_p = src_im.nplanes();
00052   assert(k_hi - k_lo +1 <= (int) n_i);
00053   const vcl_ptrdiff_t s_istep = src_im.istep(),
00054                     s_jstep = src_im.jstep(),
00055                     s_kstep = src_im.kstep(),
00056                     s_pstep = src_im.planestep();
00057 
00058   dest_im.set_size(n_i, n_j, n_k, n_p);
00059 
00060   const vcl_ptrdiff_t d_istep = dest_im.istep(),
00061                       d_jstep = dest_im.jstep(),
00062                       d_kstep = dest_im.kstep(),
00063                       d_pstep = dest_im.planestep();
00064 
00065   // Select first plane
00066   const srcT*  src_plane = src_im.origin_ptr();
00067   destT*     dest_plane = dest_im.origin_ptr();
00068   for (unsigned p=0; p<n_p; ++p, src_plane+=s_pstep, dest_plane+=d_pstep)
00069   {
00070     // Select first slice of p-th plane
00071     const srcT* src_slice = src_plane;
00072     destT*     dest_slice = dest_plane;
00073     for (unsigned k=0; k<n_k; ++k, src_slice+=s_kstep, dest_slice+=d_kstep)
00074     {
00075       // Apply convolution to each row in turn
00076       // First check if either istep is 1 for speed optimisation.
00077       const srcT* src_row = src_slice;
00078       destT*     dest_row = dest_slice;
00079 
00080       if (s_istep == 1)
00081       {
00082         if (d_istep == 1)
00083           for (unsigned int j=0; j<n_j; ++j, src_row+=s_jstep, dest_row+=d_jstep)
00084             vil_convolve_1d(src_row, n_i, 1, dest_row, 1,
00085                             kernel, k_lo, k_hi, ac, start_option, end_option);
00086         else
00087           for (unsigned int j=0; j<n_j; ++j, src_row+=s_jstep, dest_row+=d_jstep)
00088             vil_convolve_1d(src_row, n_i, 1, dest_row, d_istep,
00089                             kernel, k_lo, k_hi, ac, start_option, end_option);
00090       }
00091       else
00092       {
00093         if (d_istep == 1)
00094           for (unsigned int j=0; j<n_j; ++j, src_row+=s_jstep, dest_row+=d_jstep)
00095             vil_convolve_1d(src_row, n_i, s_istep, dest_row, 1,
00096                             kernel, k_lo, k_hi, ac, start_option, end_option);
00097         else
00098           for (unsigned int j=0; j<n_j; ++j, src_row+=s_jstep, dest_row+=d_jstep)
00099             vil_convolve_1d(src_row, n_i, s_istep, dest_row, d_istep,
00100                             kernel, k_lo, k_hi, ac, start_option, end_option);
00101       }
00102     }
00103   }
00104 }
00105 
00106 #endif // vil3d_algo_convolve_1d_h_
00107