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