core/vil/algo/vil_orientations.cxx
Go to the documentation of this file.
00001 #include "vil_orientations.h"
00002 //:
00003 // \file
00004 // \brief Functions to compute orientations and gradient magnitude
00005 // \author Tim Cootes
00006 
00007 #include <vcl_cassert.h>
00008 #include <vcl_cmath.h>
00009 
00010 //: Compute orientation (in radians) and gradient magnitude at each pixel
00011 void vil_orientations(const vil_image_view<float>& grad_i,
00012                       const vil_image_view<float>& grad_j,
00013                       vil_image_view<float>& orient_im,
00014                       vil_image_view<float>& grad_mag)
00015 {
00016   assert(grad_i.nplanes()==1 && grad_j.nplanes()==1);
00017   unsigned ni = grad_i.ni(), nj = grad_j.nj();
00018   assert(grad_j.ni()==ni && grad_j.nj()==nj);
00019   orient_im.set_size(ni,nj,1);
00020   grad_mag.set_size(ni,nj,1);
00021 
00022   const vcl_ptrdiff_t gi_istep = grad_i.istep(), gi_jstep = grad_i.jstep();
00023   const vcl_ptrdiff_t gj_istep = grad_j.istep(), gj_jstep = grad_j.jstep();
00024   const vcl_ptrdiff_t o_istep = orient_im.istep(), o_jstep = orient_im.jstep();
00025   const vcl_ptrdiff_t gm_istep = grad_mag.istep(), gm_jstep = grad_mag.jstep();
00026 
00027   const float * gi_row = &grad_i(0,0);
00028   const float * gj_row = &grad_j(0,0);
00029   float * o_row  = &orient_im(0,0);
00030   float * gm_row = &grad_mag(0,0);
00031 
00032   for (unsigned j=0;j<nj;++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00033                               o_row+=o_jstep, gm_row+=gm_jstep)
00034   {
00035     const float* pgi = gi_row;
00036     const float* pgj = gj_row;
00037     float *po = o_row;
00038     float *pgm = gm_row;
00039     for (unsigned i=0;i<ni;++i, pgi+=gi_istep, pgj+=gj_istep,
00040                                 po+=o_istep, pgm+=gm_istep)
00041     {
00042       *po  = vcl_atan2(*pgj,*pgi);
00043       *pgm = vcl_sqrt(pgi[0]*pgi[0] + pgj[0]*pgj[0]);
00044     }
00045   }
00046 }
00047 
00048 //: Compute discrete orientation and gradient magnitude at each pixel
00049 //  Computes orientation at each pixel and scales to range [0,n_orientations-1].
00050 //  Orientation of i corresponds to angles in range [(i-0.5)dA,(i+0.5)dA]
00051 //  where dA=2*pi/n_orientations.
00052 //  Images assumed to be single plane
00053 void vil_orientations(const vil_image_view<float>& grad_i,
00054                       const vil_image_view<float>& grad_j,
00055                       vil_image_view<vxl_byte>& orient_im,
00056                       vil_image_view<float>& grad_mag,
00057                       unsigned n_orientations)
00058 {
00059   assert(grad_i.nplanes()==1 && grad_j.nplanes()==1);
00060   assert(n_orientations<=256);
00061   unsigned ni = grad_i.ni(), nj = grad_j.nj();
00062   assert(grad_j.ni()==ni && grad_j.nj()==nj);
00063   orient_im.set_size(ni,nj,1);
00064   grad_mag.set_size(ni,nj,1);
00065 
00066   const vcl_ptrdiff_t gi_istep = grad_i.istep(), gi_jstep = grad_i.jstep();
00067   const vcl_ptrdiff_t gj_istep = grad_j.istep(), gj_jstep = grad_j.jstep();
00068   const vcl_ptrdiff_t o_istep = orient_im.istep(), o_jstep = orient_im.jstep();
00069   const vcl_ptrdiff_t gm_istep = grad_mag.istep(), gm_jstep = grad_mag.jstep();
00070 
00071   const float * gi_row = &grad_i(0,0);
00072   const float * gj_row = &grad_j(0,0);
00073   vxl_byte * o_row  = &orient_im(0,0);
00074   float * gm_row = &grad_mag(0,0);
00075 
00076   float scale = (2*n_orientations-1)/(6.28319f);
00077 
00078   for (unsigned j=0;j<nj;++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00079                               o_row+=o_jstep, gm_row+=gm_jstep)
00080   {
00081     const float* pgi = gi_row;
00082     const float* pgj = gj_row;
00083     vxl_byte *po = o_row;
00084     float *pgm = gm_row;
00085     for (unsigned i=0;i<ni;++i, pgi+=gi_istep, pgj+=gj_istep,
00086                                 po+=o_istep, pgm+=gm_istep)
00087     {
00088       // In order to ensure bins are centred at k*2pi/n_orientation points,
00089       // compute position in twice angle range, then adjust.
00090       int A2 = int((vcl_atan2(*pgj,*pgi)+3.14159)*scale);
00091       *po  = vxl_byte(((A2+1)/2)%n_orientations);
00092       *pgm = vcl_sqrt(pgi[0]*pgi[0] + pgj[0]*pgj[0]);
00093     }
00094   }
00095 }
00096 
00097 //: Compute discrete orientation and gradient magnitude at edge pixels
00098 //  Computes orientation at each pixel and scales to range [0,n_orientations].
00099 //  If gradient magnitude is less than grad_threshold, then orientation
00100 //  of zero is set, meaning undefined orientation.
00101 //
00102 //  Orientation of i>0 corresponds to angles in range [(i-1.5)dA,(i-0.5)dA]
00103 //  where dA=2*pi/n_orientations.
00104 //
00105 //  Images assumed to be single plane
00106 void vil_orientations_at_edges(const vil_image_view<float>& grad_i,
00107                                const vil_image_view<float>& grad_j,
00108                                vil_image_view<vxl_byte>& orient_im,
00109                                vil_image_view<float>& grad_mag,
00110                                float grad_threshold,
00111                                unsigned n_orientations)
00112 {
00113   assert(grad_i.nplanes()==1 && grad_j.nplanes()==1);
00114   assert(n_orientations<=256);
00115   unsigned ni = grad_i.ni(), nj = grad_j.nj();
00116   assert(grad_j.ni()==ni && grad_j.nj()==nj);
00117   orient_im.set_size(ni,nj,1);
00118   grad_mag.set_size(ni,nj,1);
00119 
00120   const vcl_ptrdiff_t gi_istep = grad_i.istep(), gi_jstep = grad_i.jstep();
00121   const vcl_ptrdiff_t gj_istep = grad_j.istep(), gj_jstep = grad_j.jstep();
00122   const vcl_ptrdiff_t o_istep = orient_im.istep(), o_jstep = orient_im.jstep();
00123   const vcl_ptrdiff_t gm_istep = grad_mag.istep(), gm_jstep = grad_mag.jstep();
00124 
00125   const float * gi_row = &grad_i(0,0);
00126   const float * gj_row = &grad_j(0,0);
00127   vxl_byte * o_row  = &orient_im(0,0);
00128   float * gm_row = &grad_mag(0,0);
00129 
00130   float scale = (2*n_orientations-1)/(6.28319f);
00131 
00132   for (unsigned j=0;j<nj;++j, gi_row+=gi_jstep, gj_row+=gj_jstep,
00133                               o_row+=o_jstep, gm_row+=gm_jstep)
00134   {
00135     const float* pgi = gi_row;
00136     const float* pgj = gj_row;
00137     vxl_byte *po = o_row;
00138     float *pgm = gm_row;
00139     for (unsigned i=0;i<ni;++i, pgi+=gi_istep, pgj+=gj_istep,
00140                                 po+=o_istep, pgm+=gm_istep)
00141     {
00142       *pgm = vcl_sqrt(pgi[0]*pgi[0] + pgj[0]*pgj[0]);
00143       if (*pgm<grad_threshold) *po=0;
00144       else
00145       {
00146         // In order to ensure bins are centred at k*2pi/n_orientation points,
00147         // compute position in twice angle range, then adjust.
00148         int A2 = int((vcl_atan2(*pgj,*pgi)+3.14159)*scale);
00149         *po  = vxl_byte(1+((A2+1)/2)%n_orientations);
00150       }
00151     }
00152   }
00153 }