00001
00002 #ifndef ipts_scale_space_peaks_h_
00003 #define ipts_scale_space_peaks_h_
00004
00005
00006
00007
00008
00009 #include <vimt/algo/vimt_find_peaks.h>
00010 #include <vgl/vgl_point_2d.h>
00011 #include <vgl/vgl_vector_2d.h>
00012 #include <vgl/vgl_point_3d.h>
00013 #include <vimt/vimt_image_pyramid.h>
00014 #include <vcl_cmath.h>
00015 #include <vcl_cassert.h>
00016
00017
00018 template <class T>
00019 inline bool ipts_is_above_3x3(T value, const T* im,
00020 vcl_ptrdiff_t i_step, vcl_ptrdiff_t j_step)
00021 {
00022 if (value<=im[0]) return false;
00023 if (value<=im[i_step]) return false;
00024 if (value<=im[-i_step]) return false;
00025 if (value<=im[j_step]) return false;
00026 if (value<=im[-j_step]) return false;
00027 if (value<=im[i_step+j_step]) return false;
00028 if (value<=im[i_step-j_step]) return false;
00029 if (value<=im[j_step-i_step]) return false;
00030 if (value<=im[-i_step-j_step]) return false;
00031 return true;
00032 }
00033
00034
00035
00036 template<class T>
00037 inline void ipts_scale_space_peaks_2d(vcl_vector<vgl_point_3d<double> >& peak_pts,
00038 const vimt_image_2d_of<T>& image_below,
00039 const vimt_image_2d_of<T>& image,
00040 const vimt_image_2d_of<T>& image_above,
00041 T threshold = 0,
00042 bool clear_list = true)
00043 {
00044 if (clear_list) { peak_pts.resize(0); }
00045 unsigned ni=image.image().ni(),nj=image.image().nj();
00046 vcl_ptrdiff_t istep = image.image().istep(),jstep=image.image().jstep();
00047 assert(istep!=0);
00048 const T* row = &image.image()(2,2,0);
00049
00050 const vil_image_view<T>& im_below = image_below.image();
00051 const vil_image_view<T>& im_above = image_above.image();
00052
00053 vimt_transform_2d to_base = image.world2im().inverse();
00054 vimt_transform_2d to_above = image_above.world2im() * to_base;
00055 vimt_transform_2d to_below = image_below.world2im() * to_base;
00056
00057
00058 vgl_vector_2d<double> dx(1,0),dw;
00059 dw = image.world2im().delta(vgl_point_2d<double>(0,0),dx);
00060 double scale = 1.0/vcl_sqrt(dw.x()*dw.x()+dw.y()*dw.y());
00061
00062
00063
00064 for (unsigned j=2;j<nj-2;++j,row+=jstep)
00065 {
00066 const T* pixel = row;
00067 for (unsigned i=2;i<ni-2;++i,pixel+=istep)
00068 {
00069 if (*pixel>threshold && vimt_is_peak_3x3(pixel,istep,jstep))
00070 {
00071
00072
00073 vgl_point_2d<double> p0 = to_below(i,j);
00074
00075 const T* pixel_below=&im_below(int(p0.x()+0.5),int(p0.y()+0.5));
00076 if (ipts_is_above_3x3(*pixel,pixel_below,
00077 im_below.istep(),im_below.jstep()) )
00078 {
00079
00080
00081 vgl_point_2d<double> p1 = to_above(i,j);
00082 if (p1.x()>0.5 && p1.y()>0.5
00083 && p1.x()<im_above.ni()-2 && p1.y()<im_above.nj()-2)
00084 {
00085 const T* pixel_above=&im_above(int(p1.x()+0.5),int(p1.y()+0.5));
00086 if (ipts_is_above_3x3(*pixel,pixel_above,
00087 im_above.istep(),im_above.jstep()))
00088 {
00089 vgl_point_2d<double> p = to_base(i,j);
00090 peak_pts.push_back(vgl_point_3d<double>(p.x(),p.y(),scale));
00091 }
00092 }
00093 }
00094 }
00095 }
00096 }
00097 }
00098
00099
00100
00101
00102 template<class T>
00103 inline void ipts_scale_space_peaks_2d(vcl_vector<vgl_point_2d<double> >& peak_pts,
00104 vcl_vector<T>& peak_values,
00105 const vimt_image_2d_of<T>& image0,
00106 const vimt_image_2d_of<T>& image1,
00107 T threshold)
00108 {
00109 vcl_vector<vgl_point_2d<double> > peak_pts0;
00110 vcl_vector<T> peak_values0;
00111 vimt_find_world_peaks_3x3(peak_pts0,peak_values0,image0);
00112
00113
00114 peak_pts.resize(0);
00115 peak_values.resize(0);
00116 vimt_transform_2d w2i1 = image1.world2im();
00117 unsigned ni2 = image1.image().ni()-2;
00118 unsigned nj2 = image1.image().nj()-2;
00119 vcl_ptrdiff_t istep = image1.image().istep(), jstep=image1.image().jstep();
00120 for (unsigned i=0;i<peak_pts0.size();++i)
00121 {
00122 if (peak_values0[i]>threshold)
00123 {
00124 vgl_point_2d<double> p1 = w2i1(peak_pts0[i]);
00125 if (p1.x()>0.5 && p1.y()>0.5 && p1.x()<ni2 && p1.y()<nj2)
00126 {
00127 const T* pixel=&image1.image()(int(p1.x()+0.5),int(p1.y()+0.5));
00128 if (ipts_is_above_3x3(peak_values0[i],pixel,istep,jstep))
00129 {
00130 peak_pts.push_back(peak_pts0[i]);
00131 peak_values.push_back(peak_values0[i]);
00132 }
00133 }
00134 }
00135 }
00136 }
00137
00138
00139
00140
00141 template<class T>
00142 inline void ipts_scale_space_peaks_2d(vcl_vector<vgl_point_3d<double> >& peak_pts,
00143 const vimt_image& image0,
00144 const vimt_image& image1,
00145 T threshold)
00146 {
00147 const vimt_image_2d_of<T>& im0 =
00148 dynamic_cast<const vimt_image_2d_of<T>&>(image0);
00149 const vimt_image_2d_of<T>& im1 =
00150 dynamic_cast<const vimt_image_2d_of<T>&>(image1);
00151 vcl_vector<vgl_point_2d<double> > peak_pts0;
00152 vcl_vector<T> peak_values0;
00153
00154 ipts_scale_space_peaks_2d(peak_pts0,peak_values0,im0,im1,threshold);
00155
00156
00157 vgl_vector_2d<double> dx(1,0),dw;
00158 dw = im0.world2im().delta(vgl_point_2d<double>(0,0),dx);
00159 double scale = 1.0/vcl_sqrt(dw.x()*dw.x()+dw.y()*dw.y());
00160
00161 for (unsigned i=0;i<peak_pts0.size();++i)
00162 {
00163 vgl_point_3d<double> p(peak_pts0[i].x(),peak_pts0[i].y(),scale);
00164 peak_pts.push_back(p);
00165 }
00166 }
00167
00168
00169
00170
00171
00172 template<class T>
00173 inline void ipts_scale_space_peaks_2d(vcl_vector<vgl_point_3d<double> >& peak_pts,
00174 const vimt_image_pyramid& image_pyr,
00175 T threshold)
00176 {
00177 peak_pts.resize(0);
00178
00179
00180 if (image_pyr.n_levels()>1)
00181 ipts_scale_space_peaks_2d(peak_pts,image_pyr(0),image_pyr(1),threshold);
00182
00183 for (int L=image_pyr.lo()+1;L<image_pyr.hi();++L)
00184 {
00185 const vimt_image_2d_of<T>& im_below =
00186 dynamic_cast<const vimt_image_2d_of<T>&>(image_pyr(L-1));
00187 const vimt_image_2d_of<T>& image =
00188 dynamic_cast<const vimt_image_2d_of<T>&>(image_pyr(L));
00189 const vimt_image_2d_of<T>& im_above =
00190 dynamic_cast<const vimt_image_2d_of<T>&>(image_pyr(L+1));
00191
00192 ipts_scale_space_peaks_2d(peak_pts,im_below,image,im_above,threshold,false);
00193 }
00194 }
00195
00196 #endif // ipts_scale_space_peaks_h_