Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

rsdl_borgefors.txx

Go to the documentation of this file.
00001 #ifndef rsdl_borgefors_txx_
00002 #define rsdl_borgefors_txx_
00003 //:
00004 //  \file
00005 
00006 #include "rsdl_borgefors.h"
00007 #include <vbl/vbl_array_2d.h>
00008 #include <vnl/vnl_math.h>
00009 
00010 #include <vcl_cassert.h>
00011 
00012 //********************* NOTE *************************
00013 // The map constructed is only valid 1 pixel inside it.
00014 // In other words, the 1st row and column and the last 
00015 // row and column are invalid. 
00016 //****************************************************
00017 template <class T>
00018 rsdl_borgefors<T>::rsdl_borgefors()
00019 {
00020   this->reset();
00021 }
00022 template <class T>
00023 rsdl_borgefors<T>::rsdl_borgefors(int org_x, int org_y,
00024                                   int size_x, int size_y,
00025                                   iterator_type  begin, iterator_type end, bool release_dist_map):
00026   org_x_(org_x), org_y_(org_y), size_x_(size_x), size_y_(size_y)
00027 {
00028   initialize(begin,end);
00029   if ( release_dist_map )
00030     distance_map_.clear();
00031 }
00032 
00033 template <class T>
00034 void
00035 rsdl_borgefors<T>::set(int org_x, int org_y,
00036                        int size_x, int size_y,
00037                        iterator_type  begin, iterator_type end, bool release_dist_map)
00038 {
00039   org_x_ = org_x;
00040   org_y_ = org_y;
00041   size_x_ = size_x;
00042   size_y_ = size_y;
00043 
00044   initialize(begin,end);
00045   if ( release_dist_map )
00046     distance_map_.clear();
00047 }
00048 
00049 template <class T>
00050 void
00051 rsdl_borgefors<T>::set(int org_x, int org_y,
00052                        int size_x, int size_y,
00053                        iterator_type  begin, iterator_type end,
00054                        vbl_array_2d<int> index_map,
00055                        vbl_array_2d<int>* distance_map)
00056 {
00057   // set origin and size
00058   org_x_ = org_x;
00059   org_y_ = org_y;
00060   size_x_ = size_x;
00061   size_y_ = size_y;
00062 
00063   // when the number of elements is large, 
00064   // memory allocation and deallocation are too many to aford
00065   // count the number first and reserve the size
00066   unsigned num=0;
00067   for( iterator_type i=begin; i!=end; ++i ) 
00068     ++num;
00069   
00070   // store ptrs of the internal objects to the data_
00071   data_.reserve( num );
00072   for (iterator_type i = begin; i!= end; ++i) {
00073     data_.push_back(i);
00074   }
00075 
00076   // set maps
00077   index_map_ = index_map;
00078   if ( distance_map )
00079     distance_map_ = *distance_map;
00080 
00081   is_valid_ = true;
00082 }
00083 
00084 template <class T>
00085 void
00086 rsdl_borgefors<T>::reset()
00087 {
00088   org_x_ = org_y_ = size_x_ = size_y_ = 0;
00089   data_.clear();
00090   distance_map_.clear();
00091   index_map_.clear();
00092   is_valid_ = false;
00093 }
00094 
00095 template <class T>
00096 bool
00097 rsdl_borgefors<T>::in_map(int x, int y) const
00098 {
00099   if ( x < org_x_ || x >= size_x_ + org_x_ ||
00100        y < org_y_ || y >= size_y_ + org_y_ )
00101     return false;
00102 
00103   int index = index_map_[ y - org_y_][x - org_x_];
00104   if (index < 0)
00105     return false;
00106 
00107   return true;
00108 }
00109 
00110 //: Returns the approximated distance data between (x,y) and closest data record.
00111 //  If (x,y) is out of range, -1 is returned instead.
00112 //
00113 template <class T>
00114 double
00115 rsdl_borgefors<T>::distance(int x, int y) const
00116 {
00117   assert( distance_map_.rows() == index_map_.rows() &&
00118           distance_map_.cols() == index_map_.cols() );
00119   assert( in_map(x,y) );
00120   return distance_map_[y - org_y_][x - org_x_]/3.0;
00121 }
00122 
00123 //: Returns the data located closest to (x,y). If (x,y) is out of range, it aborts.
00124 //  Therefore, should always check in_map(x,y) first.
00125 //
00126 template <class T>
00127 typename rsdl_borgefors<T>::const_iterator_type
00128 rsdl_borgefors<T>::nearest(int x, int y) const
00129 {
00130   assert( in_map(x,y) );
00131 
00132   int index = index_map_[y - org_y_][x - org_x_];
00133   return data_[index];
00134 }
00135 
00136 template <class T>
00137 void
00138 rsdl_borgefors<T>::origin(int& org_x, int& org_y) const
00139 {
00140   org_x = org_x_;
00141   org_y = org_y_;
00142 }
00143 
00144 template <class T>
00145 bool
00146 rsdl_borgefors<T>::operator==(const rsdl_borgefors<T> & rhs) const
00147 {
00148   return org_x_ == rhs.org_x_  &&  org_y_ == rhs.org_y_  &&
00149          size_x_ == rhs.size_x_ && size_y_ == rhs.size_y_ &&
00150          distance_map_ == rhs.distance_map_ && index_map_ == rhs.index_map_;
00151 }
00152 
00153 template <class T>
00154 void
00155 rsdl_borgefors<T>::initialize(iterator_type  begin, iterator_type end)
00156 {
00157   // when the number of elements is large, 
00158   // memory allocation and deallocation are too many to aford
00159   // count the number first and reserve the size
00160   unsigned num=0;
00161   for( iterator_type i=begin; i!=end; ++i ) 
00162     ++num;
00163   
00164   // 0. Store ptrs of the internal objects to the data_
00165   data_.reserve( num );
00166   for (iterator_type i = begin; i!= end; ++i) {
00167     data_.push_back(i);
00168   }
00169 
00170   // 1. Resize distance_map_ and index_map_ to accommodate the data and
00171   //    initialize the maps
00172   distance_map_.resize(size_y_ , size_x_ );
00173   index_map_.resize(size_y_ , size_x_ );
00174   int max_range = vnl_math_max( size_x_, size_y_) * 3;
00175   for (int i = 0; i < size_y_; i++)
00176     for (int j = 0; j < size_x_; j++) {
00177       distance_map_[i][j] = max_range ;
00178       index_map_[i][j] = -1;
00179     }
00180 
00181   // 2. Mark the data on the maps
00182   //
00183   for (unsigned int i = 0; i < data_.size(); ++i) {
00184     int x = vnl_math_rnd((*data_[i])[0] - org_x_);
00185     int y = vnl_math_rnd((*data_[i])[1] - org_y_);
00186     if ( x>= 0 && x < size_x_ && y>=0 && y < size_y_ )
00187       {
00188         distance_map_[y][x] = 0;
00189         index_map_[y][x] = i;
00190       }
00191   }
00192 
00193   // 3. Do the Chamfer 3-4 filtering
00194   //
00195   chamfer34();
00196 
00197   is_valid_ = true;
00198 
00199   return;
00200 }
00201 
00202 template <class T>
00203 void
00204 rsdl_borgefors<T>::chamfer34()
00205 {
00206    forward_chamfer();
00207    backward_chamfer();
00208    
00209    // TODO: two corners (0, size_y_-1) and (size_x_-1, 0) are not filled in
00210 }
00211 
00212 //: Determines the minimum of five ints.
00213 //
00214 template <class T>
00215 inline int
00216 rsdl_borgefors<T>::minimum5(int a, int b, int c, int d, int e) const
00217 {
00218   if ( a<=b && a<=c && a<=d && a<=e )
00219     return 1;
00220   else if ( b<=c && b<=d && b<=e )
00221     return 2;
00222   else if ( c<=d && c<=e )
00223     return 3;
00224   else if ( d<=e )
00225     return 4;
00226   else
00227     return 5;
00228 }
00229 
00230 //: Determines the minimum of four ints.
00231 //
00232 template <class T>
00233 inline int
00234 rsdl_borgefors<T>::minimum4(int a, int b, int c, int d) const
00235 {
00236   if ( a<=b && a<=c && a<=d )
00237     return 1;
00238   else if ( b<=c && b<=d )
00239     return 2;
00240   else if ( c<=d )
00241     return 3;
00242   else
00243     return 4;
00244 }
00245 
00246 //: Performs a forward chamfer convolution on the distance_map_ and update the index_map_ accordingly
00247 //
00248 template <class T>
00249 void
00250 rsdl_borgefors<T>::forward_chamfer()
00251 {
00252   for (int i=1; i<=size_y_-1; ++i)
00253     for (int j=1; j<size_x_-1; ++j)
00254       {
00255         const int val = minimum5(distance_map_[i-1][j-1]+4,distance_map_[i-1][j]+3,
00256                                  distance_map_[i-1][j+1]+4, distance_map_[i][j-1]+3,
00257                                  distance_map_[i][j]);
00258         switch (val)
00259           {
00260           case 1:
00261             distance_map_[i][j] = distance_map_[i-1][j-1]+4;
00262             index_map_[i][j] = index_map_[i-1][j-1];
00263             break;
00264 
00265           case 2:
00266             distance_map_[i][j] = distance_map_[i-1][j]+3;
00267             index_map_[i][j] = index_map_[i-1][j];
00268             break;
00269 
00270           case 3:
00271             distance_map_[i][j] = distance_map_[i-1][j+1]+4;
00272             index_map_[i][j] = index_map_[i-1][j+1];
00273             break;
00274 
00275           case 4:
00276             distance_map_[i][j] = distance_map_[i][j-1]+3;
00277             index_map_[i][j] = index_map_[i][j-1];
00278             break;
00279 
00280           case 5:
00281             break;
00282           }
00283       }
00284   
00285   // the last column is not filled in yet
00286   for (int i=1; i<=size_y_-1; ++i)
00287     {
00288       const int j = size_x_-1;
00289       
00290       const int val = minimum4(distance_map_[i-1][j-1]+4,distance_map_[i-1][j]+3,
00291                                distance_map_[i][j-1]+3, 
00292                                distance_map_[i][j]);
00293       switch (val)
00294         {
00295         case 1:
00296           distance_map_[i][j] = distance_map_[i-1][j-1]+4;
00297           index_map_[i][j] = index_map_[i-1][j-1];
00298           break;
00299 
00300         case 2:
00301           distance_map_[i][j] = distance_map_[i-1][j]+3;
00302           index_map_[i][j] = index_map_[i-1][j];
00303           break;
00304 
00305         case 3:
00306           distance_map_[i][j] = distance_map_[i][j-1]+3;
00307           index_map_[i][j] = index_map_[i][j-1];
00308           break;
00309 
00310         case 4:
00311           break;
00312         }
00313     }
00314 }
00315 
00316 //: Performs a forward chamfer convolution on the distance_map_ and update the index_map_ accordingly
00317 //
00318 template <class T>
00319 void
00320 rsdl_borgefors<T>::backward_chamfer()
00321 {
00322   for (int i=size_y_-2; i>=0; i--)
00323     for (int j=size_x_-2; j>0; j--)
00324       {
00325         const int val = minimum5(distance_map_[i][j],distance_map_[i][j+1]+3,
00326                                  distance_map_[i+1][j-1]+4, distance_map_[i+1][j]+3,
00327                                  distance_map_[i+1][j+1]+4 );
00328         switch (val)
00329           {
00330           case 1:
00331             break;
00332 
00333           case 2:
00334             distance_map_[i][j] = distance_map_[i][j+1]+3;
00335             index_map_[i][j] = index_map_[i][j+1];
00336             break;
00337 
00338           case 3:
00339             distance_map_[i][j] = distance_map_[i+1][j-1]+4;
00340             index_map_[i][j] = index_map_[i+1][j-1];
00341             break;
00342 
00343           case 4:
00344             distance_map_[i][j] = distance_map_[i+1][j]+3;
00345             index_map_[i][j] = index_map_[i+1][j];
00346             break;
00347 
00348           case 5:
00349             distance_map_[i][j] = distance_map_[i+1][j+1]+4;
00350             index_map_[i][j] = index_map_[i+1][j+1];
00351             break;
00352           }
00353       }
00354 
00355   // the first column is not filled in yet
00356   for (int i=size_y_-2; i>=0; i--)
00357     {
00358       const int j = 0;
00359       
00360         const int val = minimum4(distance_map_[i][j],distance_map_[i][j+1]+3,
00361                                  distance_map_[i+1][j]+3,
00362                                  distance_map_[i+1][j+1]+4 );
00363         switch (val)
00364           {
00365           case 1:
00366             break;
00367 
00368           case 2:
00369             distance_map_[i][j] = distance_map_[i][j+1]+3;
00370             index_map_[i][j] = index_map_[i][j+1];
00371             break;
00372 
00373           case 3:
00374             distance_map_[i][j] = distance_map_[i+1][j]+3;
00375             index_map_[i][j] = index_map_[i+1][j];
00376             break;
00377 
00378           case 4:
00379             distance_map_[i][j] = distance_map_[i+1][j+1]+4;
00380             index_map_[i][j] = index_map_[i+1][j+1];
00381             break;
00382           }
00383     }
00384 }
00385 
00386 
00387 #undef RSDL_BORGEFORS_INSTANTIATE
00388 #define RSDL_BORGEFORS_INSTANTIATE(REAL_T) \
00389 template class rsdl_borgefors<REAL_T >
00390 
00391 #endif // rsdl_borgefors_txx_

Generated on Thu Jan 10 14:49:34 2008 for contrib/rpl/rsdl by  doxygen 1.4.4