contrib/mul/vil3d/algo/vil3d_gauss_reduce.txx
Go to the documentation of this file.
00001 // This is mul/vil3d/algo/vil3d_gauss_reduce.txx
00002 #ifndef vil3d_gauss_reduce_txx_
00003 #define vil3d_gauss_reduce_txx_
00004 //:
00005 // \file
00006 // \brief Functions to smooth and sub-sample 3D images in one direction
00007 //
00008 //  These are not templated because
00009 //  - Each type tends to need a slightly different implementation
00010 //  - Let's not have too many templates.
00011 // \author Tim Cootes
00012 
00013 #include "vil3d_gauss_reduce.h"
00014 //
00015 #include <vil/algo/vil_gauss_reduce.h>
00016 
00017 //: Smooth and subsample single plane src_im in i to produce dest_im
00018 //  Applies 1-5-8-5-1 filter in i, then samples
00019 //  every other pixel.  Fills [0,(ni+1)/2-1][0,nj-1][0,nk-1] elements of dest
00020 //  Assumes dest_im has sufficient data allocated.
00021 //
00022 //  By applying three times we can obtain a full gaussian smoothed and
00023 //  sub-sampled 3D image
00024 template<class T>
00025 void vil3d_gauss_reduce_i(const T* src_im,
00026                           unsigned src_ni, unsigned src_nj, unsigned src_nk,
00027                           vcl_ptrdiff_t s_i_step, vcl_ptrdiff_t s_j_step,
00028                           vcl_ptrdiff_t s_k_step,
00029                           T* dest_im,
00030                           vcl_ptrdiff_t d_i_step, vcl_ptrdiff_t d_j_step,
00031                           vcl_ptrdiff_t d_k_step)
00032 {
00033   for (unsigned k=0;k<src_nk;++k)
00034   {
00035     vil_gauss_reduce_1plane(src_im, src_ni,src_nj, s_i_step,s_j_step,
00036                             dest_im,d_i_step, d_j_step);
00037     dest_im += d_k_step;
00038     src_im  += s_k_step;
00039   }
00040 }
00041 
00042 
00043 //: Smooth and subsample src_im to produce dest_im
00044 //  Applies filter in i,j and k directions, then samples every other pixel.
00045 //  Resulting image is (ni+1)/2 x (nj+1)/2 x (nk+1)/2
00046 template<class T>
00047 void vil3d_gauss_reduce(const vil3d_image_view<T>& src_im,
00048                               vil3d_image_view<T>& dest_im,
00049                               vil3d_image_view<T>& work_im1,
00050                               vil3d_image_view<T>& work_im2)
00051 {
00052   unsigned ni = src_im.ni();
00053   unsigned nj = src_im.nj();
00054   unsigned nk = src_im.nk();
00055   unsigned n_planes = src_im.nplanes();
00056 
00057   // Output image size
00058   unsigned ni2 = (ni+1)/2;
00059   unsigned nj2 = (nj+1)/2;
00060   unsigned nk2 = (nk+1)/2;
00061 
00062   if (work_im1.ni()<ni2 || work_im1.nj()<nj || work_im1.nk()<nk)
00063     work_im1.set_size(ni2, nj, nk, 1 ); // Only need one plane for this image (the larger of the work images)
00064 
00065   if (work_im2.ni()<ni2 || work_im2.nj()<nj2 || work_im2.nk()<nk || work_im2.nplanes()<n_planes)
00066     work_im2.set_size(ni2, nj2, nk, n_planes);
00067 
00068 
00069   // Smooth and subsample in i, result in work_im1
00070   for (unsigned p=0;p<n_planes;++p)
00071   {
00072     vil3d_gauss_reduce_i(
00073       src_im.origin_ptr()+p*src_im.planestep(), ni, nj, nk,
00074       src_im.istep(), src_im.jstep(), src_im.kstep(),
00075       work_im1.origin_ptr(), work_im1.istep(), work_im1.jstep(), work_im1.kstep());
00076 
00077   // Smooth and subsample in j (by implicitly transposing), result in work_im2
00078     vil3d_gauss_reduce_i(
00079       work_im1.origin_ptr() ,nj, ni2, nk,
00080       work_im1.jstep(), work_im1.istep(), work_im1.kstep(),
00081       work_im2.origin_ptr()+p*work_im2.planestep(),
00082       work_im2.jstep() ,work_im2.istep(), work_im2.kstep());
00083   }
00084   // Can resize output now, in case it is the same as the input.
00085   dest_im.set_size(ni2, nj2, nk2, n_planes);
00086 
00087   // Smooth and subsample in k (by implicitly transposing)
00088   for (unsigned p=0; p<n_planes; ++p)
00089     vil3d_gauss_reduce_i(
00090       work_im2.origin_ptr()+p*work_im2.planestep(), nk, ni2, nj2,
00091       work_im2.kstep(), work_im2.istep() ,work_im2.jstep(),
00092       dest_im.origin_ptr()+p*dest_im.planestep(),
00093       dest_im.kstep(), dest_im.istep(), dest_im.jstep());
00094 }
00095 
00096 
00097 //: Smooth and subsample src_im along i and j to produce dest_im
00098 //  Applies filter in i,j directions, then samples every other pixel.
00099 //  Resulting image is (ni+1)/2 x (nj+1)/2 x nk
00100 template<class T>
00101 void vil3d_gauss_reduce_ij(const vil3d_image_view<T>& src_im,
00102                                  vil3d_image_view<T>& dest_im,
00103                                  vil3d_image_view<T>& work_im1)
00104 {
00105   unsigned ni = src_im.ni();
00106   unsigned nj = src_im.nj();
00107   unsigned nk = src_im.nk();
00108   unsigned n_planes = src_im.nplanes();
00109 
00110   // Output image size
00111   unsigned ni2 = (ni+1)/2;
00112   unsigned nj2 = (nj+1)/2;
00113   unsigned nk2 = nk;
00114 
00115   if (work_im1.ni()<ni2 || work_im1.nj()<nj || work_im1.nk()<nk)
00116     work_im1.set_size(ni2,nj,nk);
00117   dest_im.set_size(ni2,nj2,nk2,n_planes);
00118 
00119   for (unsigned p=0;p<n_planes;++p)
00120   {
00121     // Smooth and subsample in i, result in work_im1
00122     vil3d_gauss_reduce_i(
00123       src_im.origin_ptr()+p*src_im.planestep(),ni,nj,nk,
00124       src_im.istep(),src_im.jstep(),src_im.kstep(),
00125       work_im1.origin_ptr(),work_im1.istep(),work_im1.jstep(),work_im1.kstep());
00126 
00127     // Smooth and subsample in j (by implicitly transposing), result in dest_im
00128     vil3d_gauss_reduce_i(
00129       work_im1.origin_ptr(),nj,ni2,nk,
00130       work_im1.jstep(),work_im1.istep(),work_im1.kstep(),
00131       dest_im.origin_ptr()+p*dest_im.planestep(),
00132       dest_im.jstep(),dest_im.istep(),dest_im.kstep());
00133   }
00134 }
00135 
00136 
00137 //: Smooth and subsample src_im along i and k to produce dest_im
00138 //  Applies filter in i,k directions, then samples every other pixel.
00139 //  Resulting image is (ni+1)/2 x nj x (nk+1)/2
00140 template<class T>
00141 void vil3d_gauss_reduce_ik(const vil3d_image_view<T>& src_im,
00142                                  vil3d_image_view<T>& dest_im,
00143                                  vil3d_image_view<T>& work_im1)
00144 {
00145   unsigned ni = src_im.ni();
00146   unsigned nj = src_im.nj();
00147   unsigned nk = src_im.nk();
00148   unsigned n_planes = src_im.nplanes();
00149 
00150   // Output image size
00151   unsigned ni2 = (ni+1)/2;
00152   unsigned nj2 = nj;
00153   unsigned nk2 = (nk+1)/2;
00154 
00155   if (work_im1.ni()<ni2 || work_im1.nj()<nj || work_im1.nk()<nk)
00156     work_im1.set_size(ni2,nj,nk);
00157   dest_im.set_size(ni2,nj2,nk2,n_planes);
00158 
00159   for (unsigned p=0;p<n_planes;++p)
00160   {
00161     // Smooth and subsample in i, result in work_im1
00162     vil3d_gauss_reduce_i(
00163       src_im.origin_ptr()+p*src_im.planestep(),ni,nj,nk,
00164       src_im.istep(),src_im.jstep(),src_im.kstep(),
00165       work_im1.origin_ptr(),work_im1.istep(),work_im1.jstep(),work_im1.kstep());
00166 
00167     // Smooth and subsample in k (by implicitly transposing), result in dest_im
00168     vil3d_gauss_reduce_i(
00169         work_im1.origin_ptr(),nk,ni2,nj,
00170         work_im1.kstep(),work_im1.istep(),work_im1.jstep(),
00171         dest_im.origin_ptr()+p*dest_im.planestep(),
00172         dest_im.kstep(),dest_im.istep(),dest_im.jstep());
00173   }
00174 }
00175 
00176 
00177 //: Smooth and subsample src_im along j and k to produce dest_im
00178 //  Applies filter in j,k directions, then samples every other pixel.
00179 //  Resulting image is ni x (nj+1)/2 x (nk+1)/2
00180 template<class T>
00181 void vil3d_gauss_reduce_jk(const vil3d_image_view<T>& src_im,
00182                                  vil3d_image_view<T>& dest_im,
00183                                  vil3d_image_view<T>& work_im1)
00184 {
00185   unsigned ni = src_im.ni();
00186   unsigned nj = src_im.nj();
00187   unsigned nk = src_im.nk();
00188   unsigned n_planes = src_im.nplanes();
00189 
00190   // Output image size
00191   unsigned ni2 = ni;
00192   unsigned nj2 = (nj+1)/2;
00193   unsigned nk2 = (nk+1)/2;
00194 
00195   if (work_im1.ni()<ni || work_im1.nj()<nj2 || work_im1.nk()<nk)
00196     work_im1.set_size(ni,nj2,nk);
00197 
00198   dest_im.set_size(ni2,nj2,nk2,n_planes);
00199 
00200   for (unsigned p=0;p<n_planes;++p)
00201   {
00202     // Smooth and subsample in j (by implicitly transposing), result in work_im1
00203     vil3d_gauss_reduce_i(
00204       src_im.origin_ptr()+p*src_im.planestep(),nj,ni,nk,
00205       src_im.jstep(),src_im.istep(),src_im.kstep(),
00206       work_im1.origin_ptr(),work_im1.jstep(),work_im1.istep(),work_im1.kstep());
00207 
00208     // Smooth and subsample in k (by implicitly transposing), result in dest_im
00209     vil3d_gauss_reduce_i(
00210       work_im1.origin_ptr(),nk,ni,nj2,
00211       work_im1.kstep(),work_im1.istep(),work_im1.jstep(),
00212       dest_im.origin_ptr()+p*dest_im.planestep(),
00213       dest_im.kstep(),dest_im.istep(),dest_im.jstep());
00214   }
00215 }
00216 
00217 
00218 #undef VIL3D_GAUSS_REDUCE_INSTANTIATE
00219 #define VIL3D_GAUSS_REDUCE_INSTANTIATE(T) \
00220 template void vil3d_gauss_reduce_i(const T* src_im,   \
00221                                    unsigned src_ni, unsigned src_nj, unsigned src_nk, \
00222                                    vcl_ptrdiff_t s_i_step, vcl_ptrdiff_t s_j_step,  \
00223                                    vcl_ptrdiff_t s_k_step,  \
00224                                    T* dest_im,  \
00225                                    vcl_ptrdiff_t d_i_step,  \
00226                                    vcl_ptrdiff_t d_j_step, vcl_ptrdiff_t d_k_step); \
00227 template void vil3d_gauss_reduce(const vil3d_image_view<T >& src_im, \
00228                                  vil3d_image_view<T >& dest_im,  \
00229                                  vil3d_image_view<T >& work_im1, \
00230                                  vil3d_image_view<T >& work_im2);  \
00231 template void vil3d_gauss_reduce_ij(const vil3d_image_view<T >& src_im,  \
00232                                     vil3d_image_view<T >& dest_im, \
00233                                     vil3d_image_view<T >& work_im1); \
00234 template void vil3d_gauss_reduce_ik(const vil3d_image_view<T >& src_im,  \
00235                                     vil3d_image_view<T >& dest_im, \
00236                                     vil3d_image_view<T >& work_im1); \
00237 template void vil3d_gauss_reduce_jk(const vil3d_image_view<T >& src_im,  \
00238                                     vil3d_image_view<T >& dest_im, \
00239                                     vil3d_image_view<T >& work_im1)
00240 
00241 #endif // vil3d_gauss_reduce_txx_