contrib/mul/vimt/algo/vimt_find_troughs.h
Go to the documentation of this file.
00001 // This is mul/vimt/algo/vimt_find_troughs.h
00002 #ifndef vimt_find_troughs_h_
00003 #define vimt_find_troughs_h_
00004 //:
00005 // \file
00006 // \brief Find troughs in image
00007 // \author Tim Cootes
00008 
00009 #include <vimt/vimt_image_2d_of.h>
00010 #include <vgl/vgl_point_2d.h>
00011 
00012 //: True if pixel at \p *im is strictly below its 8 neighbours
00013 //  The image pixel (first argument) should \e not be a border pixel!
00014 template <class T>
00015 inline bool vimt_is_trough_3x3(const T* im, vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step)
00016 {
00017   T v = *im;
00018   if (v>=im[i_step]) return false;
00019   if (v>=im[-i_step]) return false;
00020   if (v>=im[j_step]) return false;
00021   if (v>=im[-j_step]) return false;
00022   if (v>=im[i_step+j_step]) return false;
00023   if (v>=im[i_step-j_step]) return false;
00024   if (v>=im[j_step-i_step]) return false;
00025   if (v>=im[-i_step-j_step]) return false;
00026   return true;
00027 }
00028 
00029 //: Return image co-ordinates of all points in image strictly below their 8 neighbours
00030 // \param clear_list: If true (the default) then empty list before adding new examples
00031 template <class T>
00032 inline void vimt_find_image_troughs_3x3(vcl_vector<vgl_point_2d<unsigned> >& troughs,
00033                                         const vil_image_view<T>& image,
00034                                         unsigned plane=0, bool clear_list=true)
00035 {
00036   if (clear_list) troughs.resize(0);
00037   unsigned ni=image.ni(),nj=image.nj();
00038   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00039   const T* row = image.top_left_ptr()+plane*image.planestep()+istep+jstep;
00040   for (unsigned j=1;j<nj-1;++j,row+=jstep) // do not run over border
00041   {
00042     const T* pixel = row;
00043     for (unsigned i=1;i<ni-1;++i,pixel+=istep) // do not run over border
00044       if (vimt_is_trough_3x3(pixel,istep,jstep))
00045         troughs.push_back(vgl_point_2d<unsigned>(i,j));
00046   }
00047 }
00048 
00049 //: Return image co-ordinates of all points in image strictly below their 8 neighbours
00050 // \param clear_list: If true (the default) then empty list before adding new examples
00051 template <class T>
00052 inline void vimt_find_image_troughs_3x3(vcl_vector<vgl_point_2d<unsigned> >& troughs,
00053                                         vcl_vector<T>& trough_value,
00054                                         const vil_image_view<T>& image,
00055                                         unsigned plane=0, bool clear_list=true)
00056 {
00057   if (clear_list) troughs.resize(0);
00058   unsigned ni=image.ni(),nj=image.nj();
00059   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00060   const T* row = image.top_left_ptr()+plane*image.planestep()+istep+jstep;
00061   for (unsigned j=1;j<nj-1;++j,row+=jstep) // do not run over border
00062   {
00063     const T* pixel = row;
00064     for (unsigned i=1;i<ni-1;++i,pixel+=istep) // do not run over border
00065       if (vimt_is_trough_3x3(pixel,istep,jstep))
00066       {
00067         troughs.push_back(vgl_point_2d<unsigned>(i,j));
00068         trough_value.push_back(*pixel);
00069       }
00070   }
00071 }
00072 
00073 
00074 //: Return world co-ordinates of all points in image strictly below their 8 neighbours
00075 // \param clear_list: If true (the default) then empty list before adding new examples
00076 template <class T>
00077 inline void vimt_find_world_troughs_3x3(vcl_vector<vgl_point_2d<double> >& troughs,
00078                                         const vimt_image_2d_of<T>& image,
00079                                         unsigned plane=0, bool clear_list=true)
00080 {
00081   if (clear_list) troughs.resize(0);
00082   const vil_image_view<T>& im = image.image();
00083   vimt_transform_2d im2w = image.world2im().inverse();
00084   unsigned ni=im.ni(),nj=im.nj();
00085   vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00086   const T* row = im.top_left_ptr()+plane*im.planestep()+istep+jstep;
00087   for (unsigned j=1;j<nj-1;++j,row+=jstep) // do not run over border
00088   {
00089     const T* pixel = row;
00090     for (unsigned i=1;i<ni-1;++i,pixel+=istep) // do not run over border
00091       if (vimt_is_trough_3x3(pixel,istep,jstep)) troughs.push_back(im2w(i,j));
00092   }
00093 }
00094 
00095 //: Return image co-ordinates of minimum value in image
00096 //  (Or first one found if multiple equivalent minima)
00097 template <class T>
00098 inline
00099 vgl_point_2d<unsigned> vimt_find_min(const vil_image_view<T>& im, unsigned plane=0)
00100 {
00101   vgl_point_2d<unsigned> p(0,0);
00102   T min_val = im(0,0,plane);
00103   unsigned ni=im.ni(),nj=im.nj();
00104   vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00105   const T* row = im.top_left_ptr()+plane*im.planestep();
00106   for (unsigned j=0;j<nj;++j,row+=jstep)
00107   {
00108     const T* pixel = row;
00109     for (unsigned i=0;i<ni;++i,pixel+=istep)
00110       if (*pixel<min_val)
00111       {
00112         min_val = *pixel;
00113         p = vgl_point_2d<unsigned>(i,j);
00114       }
00115   }
00116   return p;
00117 }
00118 
00119 //: Return world co-ordinates of minimum value in image
00120 //  (Or first one found if multiple equivalent minima)
00121 template <class T>
00122 inline
00123 vgl_point_2d<double> vimt_find_min(const vimt_image_2d_of<T>& image,unsigned plane=0)
00124 {
00125   vgl_point_2d<unsigned> im_p = vimt_find_min(image.image(),plane);
00126   return image.world2im().inverse()(im_p.x(),im_p.y());
00127 }
00128 
00129 #endif // vimt_find_troughs_h_