contrib/mul/vimt/algo/vimt_find_peaks.h
Go to the documentation of this file.
00001 // This is mul/vimt/algo/vimt_find_peaks.h
00002 #ifndef vimt_find_peaks_h_
00003 #define vimt_find_peaks_h_
00004 //:
00005 // \file
00006 // \brief Find peaks in image
00007 // \author Tim Cootes, VP (Sept03)
00008 
00009 #include <vimt/vimt_image_2d_of.h>
00010 #include <vgl/vgl_point_2d.h>
00011 
00012 //: True if pixel at *im is strictly above 8 neighbours
00013 template <class T>
00014 inline bool vimt_is_peak_3x3(const T* im, vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step)
00015 {
00016   T v = *im;
00017   return v>im[i_step] &&
00018          v>im[-i_step] &&
00019          v>im[j_step] &&
00020          v>im[-j_step] &&
00021          v>im[i_step+j_step] &&
00022          v>im[i_step-j_step] &&
00023          v>im[j_step-i_step] &&
00024          v>im[-i_step-j_step];
00025 }
00026 
00027 //: True if pixel at *im is strictly above its neighbours in a 2*radius+1 neighbourhood
00028 template <class T>
00029 inline bool vimt_is_peak(const T* im, int radius, vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step)
00030 {
00031   T v = *im;
00032   for (int i=-radius; i<radius+1; i++)
00033     for (int j=-radius; j<radius+1; j++)
00034       if (i!=0 || j!=0)
00035         if (v<=im[i_step*i+j_step*j]) return false;      // One of the
00036   return true;
00037 }
00038 
00039 
00040 //: Return image co-ordinates of all points in image strictly above their 8 neighbours
00041 // \param clear_list: If true (the default) then empty list before adding new examples
00042 template <class T>
00043 inline void vimt_find_image_peaks_3x3(vcl_vector<vgl_point_2d<unsigned> >& peaks,
00044                                       const vil_image_view<T>& image,
00045                                       unsigned plane=0, bool clear_list=true)
00046 {
00047   if (clear_list) peaks.resize(0);
00048   unsigned ni=image.ni(),nj=image.nj();
00049   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00050   const T* row = image.top_left_ptr()+plane*image.planestep()+istep+jstep;
00051   for (unsigned j=1;j<nj-1;++j,row+=jstep)
00052   {
00053     const T* pixel = row;
00054     for (unsigned i=1;i<ni-1;++i,pixel+=istep)
00055       if (vimt_is_peak_3x3(pixel,istep,jstep)) peaks.push_back(vgl_point_2d<unsigned>(i,j));
00056   }
00057 }
00058 
00059 //: Return image co-ordinates of all points in image strictly above their 8 neighbours
00060 // \param peak_value: Value at peak
00061 // \param clear_list: If true (the default) then empty list before adding new examples
00062 template <class T>
00063 inline void vimt_find_image_peaks_3x3(vcl_vector<vgl_point_2d<unsigned> >& peaks,
00064                                       vcl_vector<T>& peak_value,
00065                                       const vil_image_view<T>& image,
00066                                       unsigned plane=0, bool clear_list=true)
00067 {
00068   if (clear_list) { peaks.resize(0); peak_value.resize(0); }
00069   unsigned ni=image.ni(),nj=image.nj();
00070   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00071   const T* row = image.top_left_ptr()+plane*image.planestep()+istep+jstep;
00072   for (unsigned j=1;j<nj-1;++j,row+=jstep)
00073   {
00074     const T* pixel = row;
00075     for (unsigned i=1;i<ni-1;++i,pixel+=istep)
00076       if (vimt_is_peak_3x3(pixel,istep,jstep))
00077       {
00078         peaks.push_back(vgl_point_2d<unsigned>(i,j));
00079         peak_value.push_back(*pixel);
00080       }
00081   }
00082 }
00083 
00084 //: Return image co-ordinates of all points in image strictly above their neighbours
00085 //  In a 2*radius+1 x 2*radius+1 neighbourhood of pixels (e.g. r=2 equivalent to 5x5; default: r=1)
00086 // \param peak_value: Value at peak
00087 // \param clear_list: If true (the default) then empty list before adding new examples
00088 template <class T>
00089 inline void vimt_find_image_peaks(vcl_vector<vgl_point_2d<unsigned> >& peaks,
00090                                   vcl_vector<T>& peak_value,
00091                                   const vil_image_view<T>& image,
00092                                   unsigned radius=1,
00093                                   unsigned plane=0, bool clear_list=true)
00094 {
00095   if (clear_list) { peaks.resize(0); peak_value.resize(0); }
00096   unsigned ni=image.ni(),nj=image.nj();
00097   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00098   const T* row = image.top_left_ptr()+plane*image.planestep()+radius*istep+radius*jstep;
00099   for (unsigned j=radius;j<nj-radius;++j,row+=jstep)
00100   {
00101     const T* pixel = row;
00102     for (unsigned i=radius;i<ni-radius;++i,pixel+=istep)
00103       if (vimt_is_peak(pixel,radius,istep,jstep))
00104       {
00105         peaks.push_back(vgl_point_2d<unsigned>(i,j));
00106         peak_value.push_back(*pixel);
00107       }
00108   }
00109 }
00110 
00111 //: Return image co-ordinates of all points in image strictly above their neighbours
00112 //  In a 2*radius+1 x 2*radius+1 neighbourhood of pixels (e.g. r=2 equivalent to 5x5; default: r=1)
00113 //  Additionally, only peaks of the value higher than threshold (thresh) are returned.
00114 // \param peak_value: Value at peak
00115 // \param clear_list: If true (the default) then empty list before adding new examples
00116 template <class T>
00117 inline void vimt_find_image_peaks(vcl_vector<vgl_point_2d<unsigned> >& peaks,
00118                                   vcl_vector<T>& peak_value,
00119                                   const vil_image_view<T>& image,
00120                                   T thresh, unsigned radius=1,
00121                                   unsigned plane=0, bool clear_list=true)
00122 {
00123   if (clear_list) { peaks.resize(0); peak_value.resize(0); }
00124   unsigned ni=image.ni(),nj=image.nj();
00125   vcl_ptrdiff_t istep = image.istep(),jstep=image.jstep();
00126   // Getting to the location of the starting point in the image (radius,radius)
00127   const T* row = image.top_left_ptr()+plane*image.planestep()+radius*istep+radius*jstep;
00128   for (unsigned j=radius;j<nj-radius;++j,row+=jstep)
00129   {
00130     const T* pixel = row;
00131     for (unsigned i=radius;i<ni-radius;++i,pixel+=istep)
00132     {
00133       if (*pixel>thresh)
00134       {
00135         if (vimt_is_peak(pixel,radius,istep,jstep))
00136         {
00137           peaks.push_back(vgl_point_2d<unsigned>(i,j));
00138           peak_value.push_back(*pixel);
00139         }
00140       }
00141     }
00142   }
00143 }
00144 
00145 //: Return world co-ordinates of all points in image strictly above their 8 neighbours
00146 // \param clear_list: If true (the default) then empty list before adding new examples
00147 template <class T>
00148 inline void vimt_find_world_peaks_3x3(vcl_vector<vgl_point_2d<double> >& peaks,
00149                                       const vimt_image_2d_of<T>& image,
00150                                       unsigned plane=0, bool clear_list=true)
00151 {
00152   if (clear_list) peaks.resize(0);
00153   const vil_image_view<T>& im = image.image();
00154   vimt_transform_2d im2w = image.world2im().inverse();
00155   unsigned ni=im.ni(),nj=im.nj();
00156   vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00157   const T* row = im.top_left_ptr()+plane*im.planestep()+istep+jstep;
00158   for (unsigned j=1;j<nj-1;++j,row+=jstep)
00159   {
00160     const T* pixel = row;
00161     for (unsigned i=1;i<ni-1;++i,pixel+=istep)
00162       if (vimt_is_peak_3x3(pixel,istep,jstep)) peaks.push_back(im2w(i,j));
00163   }
00164 }
00165 
00166 //: Return world co-ordinates of all points in image strictly above their 8 neighbours
00167 // \param peak_pos: Position of each peak
00168 // \param peak_value: Value at peak
00169 // \param clear_list: If true (the default) then empty list before adding new examples
00170 template <class T>
00171 inline void vimt_find_world_peaks_3x3(vcl_vector<vgl_point_2d<double> >& peak_pos,
00172                                       vcl_vector<T>& peak_value,
00173                                       const vimt_image_2d_of<T>& image,
00174                                       unsigned plane=0, bool clear_list=true)
00175 {
00176   if (clear_list) { peak_pos.resize(0); peak_value.resize(0); }
00177   const vil_image_view<T>& im = image.image();
00178   vimt_transform_2d im2w = image.world2im().inverse();
00179   unsigned ni=im.ni(),nj=im.nj();
00180   vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00181   const T* row = im.top_left_ptr()+plane*im.planestep()+istep+jstep;
00182   for (unsigned j=1;j<nj-1;++j,row+=jstep)
00183   {
00184     const T* pixel = row;
00185     for (unsigned i=1;i<ni-1;++i,pixel+=istep)
00186       if (vimt_is_peak_3x3(pixel,istep,jstep))
00187       {
00188         peak_pos.push_back(im2w(i,j));
00189         peak_value.push_back(*pixel);
00190       }
00191   }
00192 }
00193 
00194 //: Return image co-ordinates of maximum value in image
00195 //  (Or first one found if multiple equivalent maxima)
00196 template <class T>
00197 inline
00198 vgl_point_2d<unsigned> vimt_find_max(const vil_image_view<T>& im, unsigned plane=0)
00199 {
00200   vgl_point_2d<unsigned> p(0,0);
00201   T max_val = im(0,0,plane);
00202   unsigned ni=im.ni(),nj=im.nj();
00203   vcl_ptrdiff_t istep = im.istep(),jstep=im.jstep();
00204   const T* row = im.top_left_ptr()+plane*im.planestep();
00205   for (unsigned j=0;j<nj;++j,row+=jstep)
00206   {
00207     const T* pixel = row;
00208     for (unsigned i=0;i<ni;++i,pixel+=istep)
00209       if (*pixel>max_val)
00210       {
00211         max_val = *pixel;
00212         p = vgl_point_2d<unsigned>(i,j);
00213       }
00214   }
00215   return p;
00216 }
00217 
00218 //: Return world co-ordinates of maximum value in image
00219 //  (Or first one found if multiple equivalent maxima)
00220 template <class T>
00221 inline
00222 vgl_point_2d<double> vimt_find_max(const vimt_image_2d_of<T>& image,unsigned plane=0)
00223 {
00224   vgl_point_2d<unsigned> im_p = vimt_find_max(image.image(),plane);
00225   return image.world2im().inverse()(im_p.x(),im_p.y());
00226 }
00227 
00228 
00229 #endif // vimt_find_peaks_h_