00001 #ifndef rsdl_borgefors_txx_
00002 #define rsdl_borgefors_txx_
00003
00004
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
00013
00014
00015
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
00058 org_x_ = org_x;
00059 org_y_ = org_y;
00060 size_x_ = size_x;
00061 size_y_ = size_y;
00062
00063
00064
00065
00066 unsigned num=0;
00067 for( iterator_type i=begin; i!=end; ++i )
00068 ++num;
00069
00070
00071 data_.reserve( num );
00072 for (iterator_type i = begin; i!= end; ++i) {
00073 data_.push_back(i);
00074 }
00075
00076
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
00111
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
00124
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
00158
00159
00160 unsigned num=0;
00161 for( iterator_type i=begin; i!=end; ++i )
00162 ++num;
00163
00164
00165 data_.reserve( num );
00166 for (iterator_type i = begin; i!= end; ++i) {
00167 data_.push_back(i);
00168 }
00169
00170
00171
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
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
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
00210 }
00211
00212
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
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
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
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
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
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_