contrib/oxl/osl/osl_canny_nms.cxx
Go to the documentation of this file.
00001 // This is oxl/osl/osl_canny_nms.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "osl_canny_nms.h"
00010 #include <vcl_cmath.h>
00011 #include <vnl/vnl_math.h>
00012 
00013 //: returns number of edgels found [?]
00014 unsigned int osl_canny_nms(int xsize_, int ysize_,
00015                            float * const * dx_, float * const * dy_, float const * const * grad_,
00016                            float * const *thick_, float * const * theta_)
00017 {
00018   const float k = float(vnl_math::deg_per_rad);
00019   unsigned int n_edgels_NMS = 0; // return value for this function
00020 
00021   for (int y=ysize_-2; y>0; --y) {
00022     for (int x=xsize_-2; x>0; --x) {
00023       float del;
00024       if (vcl_fabs(dx_[x][y])>vcl_fabs(dy_[x][y])) {
00025         if    (grad_[x][y]<=grad_[x+1][y  ] || grad_[x][y]<grad_[x-1][y  ])
00026           continue;
00027       }
00028       else if (grad_[x][y]<=grad_[x  ][y-1] || grad_[x][y]<grad_[x  ][y+1])
00029         continue;
00030 
00031       // we have an edge
00032       float thick = grad_[x][y];
00033       float theta = k*(float)vcl_atan2(dx_[x][y],dy_[x][y]);
00034       // theta not to be used to define theta_[x][y]. Only to define orient.
00035       int orient = ( (int) (theta+202.5) ) / 45; orient %= 8;
00036 
00037       float newx = 0.0f, newy = 0.0f; // Initialise
00038 
00039       // Identify quadrant:
00040       //                     3   2   1
00041       //
00042       //                     4   *   0
00043       //
00044       //                     5   6   7
00045       switch (orient)
00046       {
00047        case 0:   // sort of horizontal
00048        case 4:
00049         newx=x+0.5f;   // pixel centre
00050         del  =  grad_[x][y-1]-grad_[x][y+1];
00051         del /= (grad_[x][y+1]+grad_[x][y-1]-2*grad_[x][y])*2;
00052         if (del>0.5f) continue;
00053         newy=y+del+0.5f;
00054         break;
00055        case 2:   // sort of vertical
00056        case 6:
00057         newy=y+0.5f;
00058         del  = grad_[x-1][y]-grad_[x+1][y];
00059         del /= (grad_[x-1][y]+grad_[x+1][y]-2*grad_[x][y])*2;
00060         if (del>0.5f) continue;
00061         newx=x+del+0.5f;
00062         break;
00063        case 1:   // sort of left diagonal
00064        case 5:
00065         if (grad_[x][y]<=grad_[x+1][y-1] || grad_[x][y]<grad_[x-1][y+1])
00066           continue;
00067         del  = grad_[x-1][y+1]-grad_[x+1][y-1];
00068         del /= (grad_[x-1][y+1]+grad_[x+1][y-1]-2*grad_[x][y])*2;
00069         if (del>0.5f) continue;
00070         newy=y-del+0.5f;
00071         newx=x+del+0.5f;
00072         break;
00073        case 3:   // sort of right diagonal
00074        case 7:
00075         if (grad_[x][y]<=grad_[x-1][y-1] || grad_[x][y]<grad_[x+1][y+1])
00076           continue;
00077         del  = grad_[x+1][y+1]-grad_[x-1][y-1];
00078         del /= (grad_[x+1][y+1]+grad_[x-1][y-1]-2*grad_[x][y])*2;
00079         if (del>0.5f) continue;
00080         newy=y-del+0.5f;
00081         newx=x-del+0.5f;
00082         break;
00083        default: // this cannot be reached
00084         break;
00085       }   // end switch
00086 
00087       // theta_[x][y] as defined in the next line is compatible with
00088       //  the convention in TargetJr.
00089       //  The minus sign in front of dy_[x][y] is to change the way
00090       //  dy_ is defined in this osl_canny_ox (i.e, we want it to be
00091       //  [y(i+1) - y(i-1)] rather than [y(i-1) - y(i+1)]).
00092       //   See ComputeGradient above.
00093       //  theta_[x][y] now stores the normal to the edge tangent.
00094       //  Before it stored the tangent to the edge.
00095       //  theta_[x][y] = theta;  // This how it was defined previously
00096       theta_[x][y] = k*(float)vcl_atan2(-dy_[x][y],dx_[x][y]);
00097 
00098       thick_[x][y] = thick;
00099       dx_[x][y] = newx;
00100       dy_[x][y] = newy;
00101 
00102       ++n_edgels_NMS;
00103     }   // end for x
00104   }   // end for y
00105   return n_edgels_NMS;
00106 }