contrib/brl/bseg/sdet/sdet_edge_champher.cxx
Go to the documentation of this file.
00001 //:
00002 // \file
00003 #include "sdet_edge_champher.h"
00004 
00005 //--------------------------------------------------------------
00006 //
00007 // Constructor and Destructor Functions
00008 //
00009 //--------------------------------------------------------------
00010 
00011 //:  Constructor
00012 sdet_edge_champher::sdet_edge_champher(vbl_array_2d<vtol_edge_2d_sptr>& edges)
00013 {
00014   xsize_ = edges.cols();
00015   ysize_ = edges.rows();
00016   //note the max value of unsigned char is -1
00017   distance_ = vbl_array_2d<unsigned char>(ysize_, xsize_, (unsigned char)-1 );
00018   edges_ = vbl_array_2d<vtol_edge_2d_sptr>(ysize_, xsize_, 0);
00019   // Extract the edgel data and write to the distance and orientation images
00020   this->initialize_arrays(edges);
00021   // Do the Chamfer 3-4 filtering
00022   this->chamfer_34();
00023 }
00024 
00025 
00026 //: Destructor
00027 sdet_edge_champher::~sdet_edge_champher()
00028 {
00029 }
00030 
00031 
00032 //-----------------------------------------------------------------------------
00033 //
00034 //: Copies the edge array and sets the distance at each edge location to 0
00035 //   Note that vbl_array has r, c -> y, x  index order
00036 //-----------------------------------------------------------------------------
00037 void
00038 sdet_edge_champher::initialize_arrays(vbl_array_2d<vtol_edge_2d_sptr>& edges)
00039 {
00040   for (int x=0; x<xsize_; x++)
00041     for (int y=0; y<ysize_; y++)
00042     {
00043       if ( edges.get(y,x) !=0 ) distance_[y][x] = 0;
00044       edges_[y][x] = edges.get(y,x);
00045     }
00046 }
00047 
00048 //:
00049 //-----------------------------------------------------------------------------
00050 //
00051 // Performs 3-4 Chamfer filtering on the distance_ image, and carries with
00052 // it information about the orientations.
00053 //
00054 //-----------------------------------------------------------------------------
00055 void sdet_edge_champher::chamfer_34()
00056 {
00057   this->forward_chamfer();
00058   this->backward_chamfer();
00059   this->compute_real_distances();
00060 }
00061 
00062 //-----------------------------------------------------------------------------
00063 //
00064 //: Determines the minimum of five ints.
00065 //
00066 //-----------------------------------------------------------------------------
00067 int sdet_edge_champher::minimum_5(int a, int b, int c, int d, int e)
00068 {
00069   if ( (a<=b) && (a<=c) && (a<=d) && (a<=e) )
00070     return 1;
00071   else if ( (b<=c) && (b<=d) && (b<=e) )
00072     return 2;
00073   else if ( (c<=d) && (c<=e) )
00074     return 3;
00075   else if ( d<=e )
00076     return 4;
00077   else
00078     return 5;
00079 }
00080 
00081 //-----------------------------------------------------------------------------
00082 //
00083 //: Performs a forward chamfer convolution on the distance_ and _edge images
00084 //
00085 //-----------------------------------------------------------------------------
00086 void sdet_edge_champher::forward_chamfer()
00087 {
00088   int i,j,val;
00089 
00090   for (j=1;j<xsize_-1;j++)
00091     for (i=1;i<ysize_-1;i++)
00092     {
00093       val =
00094         minimum_5(distance_[i-1][j-1]+4,distance_[i-1][j]+3,
00095                   distance_[i-1][j+1]+4,distance_[i][j-1]+3,
00096                   distance_[i][j]);
00097       switch (val)
00098       {
00099        case 1:
00100         distance_[i][j] = distance_[i-1][j-1]+4;
00101         edges_[i][j] = edges_[i-1][j-1];
00102         break;
00103 
00104        case 2:
00105         distance_[i][j] = distance_[i-1][j]+3;
00106         edges_[i][j] = edges_[i-1][j];
00107         break;
00108 
00109        case 3:
00110         distance_[i][j] = distance_[i-1][j+1]+4;
00111         edges_[i][j] = edges_[i-1][j+1];
00112         break;
00113 
00114        case 4:
00115         distance_[i][j] = distance_[i][j-1]+3;
00116         edges_[i][j] = edges_[i][j-1];
00117         break;
00118 
00119        default:
00120         break;
00121       }
00122     }
00123 }
00124 
00125 //-----------------------------------------------------------------------------
00126 //
00127 //: Performs a backward chamfer convolution on the distance_ and edges_ images
00128 //
00129 //-----------------------------------------------------------------------------
00130 void sdet_edge_champher::backward_chamfer()
00131 {
00132   int i,j,val;
00133 
00134   for (j=xsize_-2;j>0;j--)
00135     for (i=ysize_-2;i>0;i--)
00136     {
00137       val = minimum_5(distance_[i][j],distance_[i][j+1]+3,distance_[i+1][j-1]+4,
00138                       distance_[i+1][j]+3,distance_[i+1][j+1]+4 );
00139       switch (val)
00140       {
00141        case 2:
00142         distance_[i][j] = distance_[i][j+1]+3;
00143         edges_[i][j] = edges_[i][j+1];
00144         break;
00145 
00146        case 3:
00147         distance_[i][j] = distance_[i+1][j-1]+4;
00148         edges_[i][j] = edges_[i+1][j-1];
00149         break;
00150 
00151        case 4:
00152         distance_[i][j] = distance_[i+1][j]+3;
00153         edges_[i][j] = edges_[i+1][j];
00154         break;
00155 
00156        case 5:
00157         distance_[i][j] = distance_[i+1][j+1]+4;
00158         edges_[i][j] = edges_[i+1][j+1];
00159         break;
00160 
00161        default:
00162         break;
00163       }
00164     }
00165 }
00166 //:
00167 //-----------------------------------------------------------------------------
00168 //
00169 // The Chamfer 3-4 masks compute distance which are three times the actual
00170 // distance. Scale all values by three in the distance_ image.
00171 //
00172 //-----------------------------------------------------------------------------
00173 void sdet_edge_champher::compute_real_distances()
00174 {
00175   int x,y;
00176 
00177   for (x=0;x<xsize_;x++)
00178     for (y=0;y<ysize_;y++)
00179       distance_[y][x] = (unsigned char) distance_[y][x] / 3;
00180 }