00001 #ifndef rgrl_matcher_pseudo_int_3d_txx_
00002 #define rgrl_matcher_pseudo_int_3d_txx_
00003
00004 #include "rgrl_matcher_pseudo_int_3d.h"
00005 #include "rgrl_feature_face_region.h"
00006 #include "rgrl_feature_trace_region.h"
00007 #include <rgrl/rgrl_cast.h>
00008 #include <rgrl/rgrl_match_set.h>
00009 #include <rgrl/rgrl_macros.h>
00010 #include <vnl/vnl_matrix.h>
00011 #include <vnl/vnl_math.h>
00012 #include <vnl/vnl_vector.h>
00013 #include <vnl/vnl_int_3.h>
00014 #include <vnl/vnl_inverse.h>
00015 #include <vil3d/vil3d_trilin_interp.h>
00016 #include <vbl/vbl_bounding_box.h>
00017 #include <vbl/vbl_array_2d.h>
00018 #include <vbl/vbl_array_3d.h>
00019 #include <vcl_cassert.h>
00020
00021 static const double max_response_value = 1.0e30;
00022
00023
00024 #if defined ( MY_DEBUG )
00025 # include <vcl_iostream.h>
00026
00027
00028 # define DBG(x) x
00029 #else
00030 # define DBG(x)
00031 #endif
00032
00033
00034 inline
00035 void
00036 pixel_to_physical( vnl_int_3 const& pixel_loc,
00037 vnl_double_3 & point,
00038 vnl_double_3 const& spacing_ratio )
00039 {
00040 for ( unsigned i = 0; i < 3; ++i )
00041 point[ i ] = spacing_ratio[ i ] * double(pixel_loc[ i ]);
00042 }
00043
00044
00045 inline
00046 void
00047 physical_to_pixel( vnl_double_3 const& point,
00048 vnl_int_3 & pixel_loc,
00049 vnl_double_3 const& spacing_ratio )
00050 {
00051 for ( unsigned i = 0; i < 3; ++i )
00052 pixel_loc[ i ] = (int) vnl_math_rnd( point[ i ] / spacing_ratio[ i ] );
00053 }
00054
00055
00056 inline
00057 void
00058 physical_to_pixel( vnl_double_3 const& point,
00059 vnl_double_3 & pixel_loc,
00060 vnl_double_3 const& spacing_ratio )
00061 {
00062 for ( unsigned i = 0; i < 3; ++i )
00063 pixel_loc[ i ] = point[ i ] / spacing_ratio[ i ] ;
00064 }
00065
00066
00067 template <class PixelType>
00068 inline
00069 bool
00070 pixel_in_range( vil3d_image_view< PixelType > const& image,
00071 rgrl_mask_sptr const& mask,
00072 vnl_int_3 const& location )
00073 {
00074
00075
00076
00077
00078
00079
00080 if ( location[ 0 ] < 0 || location[ 0 ] > (int)image.ni()-1 ||
00081 location[ 1 ] < 0 || location[ 1 ] > (int)image.nj()-1 ||
00082 location[ 2 ] < 0 || location[ 2 ] > (int)image.nk()-1 )
00083 return false;
00084
00085 if ( mask ) {
00086
00087 static vnl_vector< double > loc_dbl( 2 );
00088 for ( unsigned i = 0; i < 2; ++i )
00089 loc_dbl[ i ] = double(location[ i ]);
00090
00091
00092 if ( !mask->inside( loc_dbl ) )
00093 return false;
00094 }
00095 return true;
00096 }
00097
00098 template <class PixelType>
00099 inline
00100 bool
00101 physical_in_range( vil3d_image_view< PixelType > const& image,
00102 rgrl_mask_sptr const& mask,
00103 vnl_double_3 const& location,
00104 vnl_double_3 const& spacing_ratio )
00105 {
00106 vnl_double_3 pixel_loc;
00107 physical_to_pixel( location, pixel_loc, spacing_ratio );
00108
00109
00110
00111
00112 if ( pixel_loc[ 0 ] < 0 || pixel_loc[ 0 ] > (double)(image.ni()-1) ||
00113 pixel_loc[ 1 ] < 0 || pixel_loc[ 1 ] > (double)(image.nj()-1) ||
00114 pixel_loc[ 2 ] < 0 || pixel_loc[ 2 ] > (double)(image.nk()-1) )
00115 return false;
00116
00117 if ( mask ) {
00118
00119 static vnl_vector< double > loc_dbl( 2 );
00120 loc_dbl [0] = pixel_loc[0];
00121 loc_dbl [1] = pixel_loc[1];
00122
00123 if ( !mask->inside( loc_dbl ) )
00124 return false;
00125 }
00126 return true;
00127 }
00128
00129 template <class PixelType>
00130 rgrl_matcher_pseudo_int_3d< PixelType > ::
00131 rgrl_matcher_pseudo_int_3d( vil3d_image_view<PixelType> const& from_image,
00132 vil3d_image_view<PixelType> const& to_image,
00133 vnl_vector< double > const& from_spacing_ratio,
00134 vnl_vector< double > const& to_spacing_ratio,
00135 rgrl_evaluator_sptr evaluator,
00136 rgrl_mask_sptr mask )
00137 : from_image_( from_image ),
00138 to_image_( to_image ),
00139 mask_( mask ),
00140 evaluator_( evaluator ),
00141 from_spacing_ratio_( from_spacing_ratio ),
00142 to_spacing_ratio_( to_spacing_ratio )
00143 {
00144 assert( from_spacing_ratio.size() == 3 );
00145 assert( to_spacing_ratio.size() == 3 );
00146 }
00147
00148
00149 template <class PixelType>
00150 rgrl_match_set_sptr
00151 rgrl_matcher_pseudo_int_3d< PixelType > ::
00152 compute_matches( rgrl_feature_set const& from_set,
00153 rgrl_feature_set const& to_set,
00154 rgrl_view const& current_view,
00155 rgrl_transformation const& current_xform,
00156 rgrl_scale const& current_scale,
00157 rgrl_match_set_sptr const& )
00158 {
00159 vcl_cerr << "compute_matches()\n";
00160
00161 typedef vcl_vector<rgrl_feature_sptr> f_vector_type;
00162 typedef f_vector_type::iterator f_iterator_type;
00163
00164
00165 rgrl_match_set_sptr matches_sptr
00166 = new rgrl_match_set( from_set.type(), to_set.type(), from_set.label(), to_set.label() );
00167
00168
00169 f_vector_type from;
00170 from_set.features_in_region( from, current_view.region() );
00171
00172
00173 rgrl_mapped_pixel_vector_type mapped_pixels;
00174
00175
00176 f_vector_type matched_to_features;
00177 vcl_vector<double> match_weights;
00178
00179
00180 matches_sptr->reserve( from.size() );
00181
00182 for ( f_iterator_type fitr = from.begin(); fitr != from.end(); ++fitr )
00183 {
00184
00185
00186
00187 matched_to_features.clear();
00188 match_weights.clear();
00189
00190
00191 rgrl_feature_sptr mapped_feature = (*fitr)->transform( current_xform );
00192
00193
00194
00195 if ( !physical_in_range( to_image_, mask_, mapped_feature->location(), to_spacing_ratio_ ) ) {
00196
00197
00198
00199
00200
00201 matches_sptr
00202 -> add_feature_matches_and_weights( *fitr, mapped_feature, matched_to_features,
00203 match_weights );
00204 DebugMacro(3, " skip match from: " << (*fitr)->location() << ", to: " << mapped_feature->location() << '\n' );
00205 continue;
00206 }
00207
00208
00209
00210
00211
00212 mapped_pixels.clear();
00213
00214 DBG(
00215 if ( (*fitr)->is_type( rgrl_feature_trace_region::type_id() ) ) {
00216 vcl_cout << "\nfrom :\n" << (*fitr)->location()
00217 << " normal: "
00218 << rgrl_cast<rgrl_feature_trace_region *> ( *fitr )->normal_subspace().get_column(0)
00219 << "\nto :\n" << mapped_feature->location()
00220 << " normal: "
00221 << rgrl_cast<rgrl_feature_trace_region *> ( mapped_feature )->normal_subspace().get_column(0)
00222 << vcl_endl;
00223 }
00224 else if ( (*fitr)->is_type( rgrl_feature_face_region::type_id() ) ) {
00225 vcl_cout << "\nfrom :\n" << (*fitr)->location()
00226 << " normal: "
00227 << rgrl_cast<rgrl_feature_face_region *> ( *fitr )->normal()
00228 << "\nto :\n" << mapped_feature->location()
00229 << " normal: "
00230 << rgrl_cast<rgrl_feature_face_region *> ( mapped_feature )->normal()
00231 << vcl_endl;
00232 }
00233 );
00234
00235 this -> map_region_intensities( current_xform, (*fitr), mapped_pixels );
00236
00237
00238 if ( mapped_pixels.size() == 0 ) {
00239
00240
00241
00242
00243
00244 matches_sptr
00245 -> add_feature_matches_and_weights( *fitr, mapped_feature, matched_to_features,
00246 match_weights );
00247 vcl_cout << " from point : " << (*fitr)->location()
00248 << " to point : " << mapped_feature->location()
00249 << " doesn't have proper matches\n" << vcl_endl;
00250 continue;
00251 }
00252
00253 this -> slide_window( mapped_feature, mapped_pixels, current_scale,
00254 matched_to_features, match_weights );
00255
00256
00257
00258
00259
00260 matches_sptr
00261 -> add_feature_matches_and_weights( *fitr, mapped_feature, matched_to_features, match_weights );
00262 }
00263
00264 vcl_cout << " number of from points : " << matches_sptr->from_size() << vcl_endl;
00265 assert( matches_sptr->from_size() == from.size() );
00266 return matches_sptr;
00267 }
00268
00269
00270 template <class PixelType>
00271 void
00272 rgrl_matcher_pseudo_int_3d<PixelType> ::
00273 map_region_intensities( rgrl_transformation const& trans,
00274 rgrl_feature_sptr feature_sptr,
00275 rgrl_mapped_pixel_vector_type & mapped_pixels) const
00276 {
00277 if ( feature_sptr -> is_type( rgrl_feature_face_region::type_id() ) )
00278 {
00279 rgrl_feature_face_region * face_ptr =
00280 rgrl_cast<rgrl_feature_face_region *> ( feature_sptr );
00281 this -> map_region_intensities( face_ptr -> pixel_coordinates_ratio( from_spacing_ratio_.as_ref() ), trans,
00282 feature_sptr, mapped_pixels );
00283 }
00284 else
00285 {
00286 rgrl_feature_trace_region * trace_ptr =
00287 rgrl_cast<rgrl_feature_trace_region *> ( feature_sptr );
00288 this -> map_region_intensities( trace_ptr -> pixel_coordinates_ratio( from_spacing_ratio_.as_ref() ), trans,
00289 feature_sptr, mapped_pixels );
00290 }
00291 }
00292
00293
00294 template <class PixelType>
00295 void
00296 rgrl_matcher_pseudo_int_3d<PixelType> ::
00297 map_region_intensities( vcl_vector< vnl_vector<int> > const& pixel_locations,
00298 rgrl_transformation const& trans,
00299 rgrl_feature_sptr feature_sptr,
00300 rgrl_mapped_pixel_vector_type & mapped_pixels) const
00301 {
00302 DebugMacro( 1, " number of pixel coorindates: " << pixel_locations.size() << vcl_endl );
00303
00304 if ( pixel_locations.empty() ) return;
00305
00306
00307 assert ( feature_sptr -> location() . size() == 3 );
00308 vnl_double_3 physical_loc;
00309 vnl_int_3 current_pixel_loc;
00310
00311
00312
00313 vbl_bounding_box<double,3> box;
00314 mapped_info mapped_pt;
00315 mapped_pt.pixel_ = vnl_double_3( 0.0, 0.0, 0.0 );
00316 vcl_vector< mapped_info > direct_mapped_pts;
00317 direct_mapped_pts.reserve( pixel_locations.size() );
00318 for ( unsigned int i=0; i<pixel_locations.size(); ++i )
00319 {
00320 current_pixel_loc = pixel_locations[i];
00321
00322 if ( !pixel_in_range( from_image_, mask_, current_pixel_loc ) )
00323 continue;
00324
00325
00326 pixel_to_physical( current_pixel_loc, physical_loc, from_spacing_ratio_ );
00327
00328
00329
00330 vnl_double_3 mapped_physical_pt;
00331 trans.map_location( physical_loc, mapped_physical_pt.as_ref().non_const() );
00332
00333 if ( !physical_in_range( to_image_, mask_, mapped_physical_pt, to_spacing_ratio_ ) )
00334 continue;
00335
00336
00337 mapped_pt.physical_ = mapped_physical_pt;
00338 physical_to_pixel( mapped_physical_pt, mapped_pt.pixel_, to_spacing_ratio_ );
00339
00340 mapped_pt.in_ = from_image_( current_pixel_loc[0], current_pixel_loc[1], current_pixel_loc[2], 0 );
00341 direct_mapped_pts.push_back( mapped_pt );
00342
00343
00344 box.update( mapped_pt.pixel_[0], mapped_pt.pixel_[1], mapped_pt.pixel_[2] );
00345 }
00346
00347
00348 if ( box.empty() ) return;
00349
00350 vnl_int_3 origin, dim;
00351 origin[0] = (int)vcl_floor(box.xmin());
00352 origin[1] = (int)vcl_floor(box.ymin());
00353 origin[2] = (int)vcl_floor(box.zmin());
00354 dim[0] = 1+(int)vcl_ceil(box.xmax()) - (int)vcl_floor(box.xmin());
00355 dim[1] = 1+(int)vcl_ceil(box.ymax()) - (int)vcl_floor(box.ymin());
00356 dim[2] = 1+(int)vcl_ceil(box.zmax()) - (int)vcl_floor(box.zmin());
00357
00358 DebugMacro( 1, "Origin: " << origin << " Dim: " << dim << vcl_endl );
00359
00360 vbl_array_3d<double> wgted_sum( dim[0], dim[1], dim[2] );
00361 vbl_array_3d<double> wgts( dim[0], dim[1], dim[2] );
00362 wgted_sum.fill( 0.0 );
00363 wgts.fill( 0.0 );
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 for (typename vcl_vector<mapped_info>::const_iterator it=direct_mapped_pts.begin();
00375 it!=direct_mapped_pts.end(); ++it) {
00376 vnl_int_3 ceil, floor;
00377 vnl_double_3 diff_floor;
00378 for (unsigned i=0; i<3; i++) {
00379 floor[i] = (int)vcl_floor( it->pixel_[i] ) - origin[i];
00380 ceil [i] = (int)vcl_ceil ( it->pixel_[i] ) - origin[i];
00381 diff_floor[i] = it->pixel_[i] - origin[i] - floor[i];
00382 }
00383
00384 double wgt;
00385 for (int i=floor[0]; i<=ceil[0]; i++)
00386 for (int j=floor[1]; j<=ceil[1]; j++)
00387 for (int k=floor[2]; k<=ceil[2]; k++) {
00388
00389
00390 wgt = vcl_abs( floor[0]+1-i-diff_floor(0) ) *
00391 vcl_abs( floor[1]+1-j-diff_floor(1) ) *
00392 vcl_abs( floor[2]+1-k-diff_floor(2) );
00393 wgts(i,j,k) += wgt;
00394 wgted_sum(i,j,k) += wgt* double(it->in_);
00395 }
00396 }
00397
00398
00399 mapped_pixels.reserve( pixel_locations.size() );
00400 rgrl_mapped_pixel_type mapped_pixel;
00401 mapped_pixel . weight = 1.0;
00402 for (int i=0; i<dim[0]; ++i)
00403 for (int j=0; j<dim[1]; ++j)
00404 for (int k=0; k<dim[2]; ++k)
00405 if ( wgts(i,j,k) >= 1e-8 ) {
00406 mapped_pixel.intensity = wgted_sum(i,j,k) / wgts(i,j,k);
00407 mapped_pixel.location[0] = i + origin[0];
00408 mapped_pixel.location[1] = j + origin[1];
00409 mapped_pixel.location[2] = k + origin[2];
00410
00411
00412 mapped_pixels.push_back( mapped_pixel );
00413 }
00414 DebugMacro(1, "Total mapped pixels at integer locations: " << mapped_pixels.size() << vcl_endl );
00415 }
00416
00417 inline
00418 double
00419 sub_pixel( vcl_vector< double > const& responses )
00420 {
00421 assert( 0 );
00422 assert( responses.size() == 3 );
00423
00424
00425
00426
00427 vnl_matrix < double > A ( 3, 3 );
00428 vnl_matrix < double > S ( 3, 1 ) ;
00429
00430 for ( unsigned i = 0; i < 3; ++i ) {
00431
00432 int r = i - 1;
00433 A( i, 0 ) = r * r;
00434 A( i, 1 ) = r;
00435 A( i, 2 ) = 1;
00436 S( i, 0 ) = responses[ i ];
00437 }
00438
00439 vnl_matrix< double > inv = vnl_inverse(A);
00440 vnl_matrix< double > X = inv * S;
00441 assert( X.columns() == 1 );
00442
00443
00444
00445 if ( X[ 0 ][ 0 ] <= 1.0e-5 )
00446 return 0;
00447
00448
00449
00450
00451 double best_index = -X[ 1 ][ 0 ] / ( 2 * X[ 0 ][ 0 ] );
00452
00453 DBG( vcl_cout << " best_index = " << best_index << '\n' ) ;
00454
00455 assert( best_index <= 1 && best_index >= -1 );
00456
00457 return best_index;
00458 }
00459
00460
00461
00462 template <class PixelType>
00463 void
00464 rgrl_matcher_pseudo_int_3d<PixelType> ::
00465 slide_window(rgrl_feature_sptr mapped_feature,
00466 rgrl_mapped_pixel_vector_type const & mapped_pixels,
00467 rgrl_scale const & current_scale,
00468 vcl_vector< rgrl_feature_sptr > & matched_to_features,
00469 vcl_vector< double > & match_weights ) const
00470 {
00471
00472 unsigned int dim = mapped_feature -> location().size();
00473
00474 const double scale_multiplier = 4;
00475
00476 DebugMacro(2, " geometric scale = " << current_scale.geometric_scale() << vcl_endl );
00477
00478 vnl_matrix< double > normal_space;
00479
00480 if ( mapped_feature -> is_type( rgrl_feature_face_region::type_id() ) )
00481 {
00482 rgrl_feature_face_region * face_ptr =
00483 rgrl_cast<rgrl_feature_face_region *> ( mapped_feature );
00484 normal_space.set_size( dim, 1 );
00485 normal_space.set_column ( 0, face_ptr -> normal() );
00486 }
00487 else
00488 {
00489 rgrl_feature_trace_region * trace_ptr =
00490 rgrl_cast<rgrl_feature_trace_region *> ( mapped_feature );
00491 normal_space = trace_ptr -> normal_subspace();
00492 }
00493
00494 vnl_vector<double> match_location(3, 0.0);
00495 double min_response = 0.0;
00496 double second_derivative = 0.0;
00497 double max_length = scale_multiplier * current_scale.geometric_scale();
00498 if ( max_length < 1 ) max_length = 1;
00499
00500
00501
00502
00503
00504 if ( normal_space . columns() == 1 )
00505 {
00506 vnl_double_3 physical_basis = normal_space.get_column(0);
00507 vnl_double_3 pixel_basis;
00508 physical_to_pixel( physical_basis, pixel_basis, to_spacing_ratio_ );
00509
00510
00511 vcl_vector< discrete_shift_node > discrete_offsets;
00512
00513
00514
00515 sample_pixels_along_direction( discrete_offsets, pixel_basis, max_length );
00516
00517
00518 assert( discrete_offsets.size() > 1 );
00519 DebugMacro(2, " shift vector length: " << discrete_offsets.size() );
00520
00521
00522 const int max_offset = (discrete_offsets.size()-1)/2;
00523
00524 vcl_vector<double> responses( 2*max_offset+1, 0.0 );
00525 bool is_best_initialized = false;
00526 int best_offset = 0;
00527
00528
00529
00530 for ( int abs_offset = 0; abs_offset <= max_offset; ++abs_offset )
00531 {
00532 int offset = abs_offset;
00533 do {
00534 int i = offset + max_offset;
00535 responses[i] = this -> compute_response( mapped_pixels, discrete_offsets[i].shift_ );
00536 DebugMacro(2, " response at offset " << discrete_offsets[i].shift_
00537 << " ( i = " << i << " ) : " << responses[ i ] << vcl_endl );
00538
00539
00540
00541 if ( (!is_best_initialized || responses[i] < min_response ) &&
00542 responses[ i ] != max_response_value )
00543 {
00544 is_best_initialized = true;
00545 min_response = responses[i];
00546 best_offset = offset;
00547 }
00548 offset = -offset;
00549 } while ( offset < 0 );
00550 }
00551
00552 DebugMacro(2, " the best offset = " << discrete_offsets[best_offset+max_offset].shift_ << vcl_endl );
00553 if ( !is_best_initialized )
00554 {
00555 DebugMacro(1, "For mapped feature: " << mapped_feature->location()
00556 << ", the slide window is invalid." << vcl_endl );
00557 return;
00558 }
00559
00560
00561
00562
00563
00564 int deriv_loc = best_offset;
00565 if ( deriv_loc == -max_offset ) ++ deriv_loc;
00566 else if ( deriv_loc == max_offset ) -- deriv_loc;
00567 int index = deriv_loc + max_offset;
00568 DebugMacro(3, " the proper offset = " << deriv_loc << vcl_endl );
00569
00570
00571 const vnl_int_3& best = discrete_offsets[best_offset+max_offset].shift_;
00572 match_location = mapped_feature->location();
00573 for (unsigned int i=0; i<3; i++)
00574 match_location[i] += double(best[i]);
00575 DebugMacro(2, "best match :\n" << match_location << vcl_endl );
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 if ( responses[ index - 1 ] == max_response_value )
00588 index ++;
00589 else if ( responses[ index + 1 ] == max_response_value )
00590 index--;
00591
00592 double a1, a2, a3, d1, d2, sumd;
00593
00594 if ( index > 0 && index+1 < (int)responses.size() &&
00595 responses[ index ] != max_response_value &&
00596 index + 1 <= 2*max_offset &&
00597 index - 1 >= -2*max_offset &&
00598 responses[ index + 1 ] != max_response_value &&
00599 responses[ index - 1 ] != max_response_value )
00600 {
00601 d2 = discrete_offsets[ index+1 ].step_ - discrete_offsets[ index ].step_;
00602 d1 = discrete_offsets[ index ].step_ - discrete_offsets[ index-1 ].step_;
00603 sumd = d1+d2;
00604 a1 = 2.0/(d1*sumd);
00605 a3 = 2.0/(d2*sumd);
00606 a2 = -2.0/(d1*d2);
00607
00608
00609 second_derivative = vcl_abs( a1*responses[ index-1 ] +
00610 a2*responses[ index ] +
00611 a3*responses[ index + 1] );
00612 DebugMacro(3, " 2nd Derivative(at " << index
00613 << "): d1=" << d1 << " d2=" << d2
00614 << "\n a1=" << a1 <<" a2=" << a2
00615 << " a3=" << a3
00616 << "\n res1 " << responses[ index-1 ]
00617 << " res2 " << responses[ index ]
00618 << " res3 " << responses[ index+1 ]
00619 << "\n deriv=" << second_derivative << vcl_endl ) ;
00620 }
00621 else
00622 {
00623 second_derivative = 0;
00624 DebugMacro(2, "index=" << index << ", max_offset=" << max_offset
00625 << ", responses[index-1]=" << responses[index-1]
00626 << ", responses[index+1]=" << responses[index+1] << '\n'
00627 << " neighbors' responses are not valid. Set the second_derivative = 0\n" );
00628 }
00629 }
00630 else if ( normal_space . columns() == 2 )
00631 {
00632
00633 vnl_vector<double> basis1 = normal_space . get_column(0);
00634 vnl_vector<double> basis2 = normal_space . get_column(1);
00635
00636 DebugMacro(2, "normal basis :\n" << basis1 << " and " << basis2 << vcl_endl );
00637
00638
00639 vcl_vector< discrete_shift_node > offset1, offset2;
00640
00641
00642 sample_pixels_along_direction( offset1, basis1, max_length );
00643 sample_pixels_along_direction( offset2, basis2, max_length );
00644 const int max_offset1 = (offset1.size()-1) / 2;
00645 const int max_offset2 = (offset2.size()-1) / 2;
00646
00647
00648 vbl_array_2d<double> responses( 2*max_offset1+1, 2*max_offset2+1, 0.0 );
00649 bool is_best_initialized = false;
00650 int best_off1 = 0, best_off2 = 0;
00651
00652
00653
00654
00655 for ( int off1 = -max_offset1, i=0; off1 <= max_offset1; ++off1, ++i )
00656 {
00657 for ( int off2 = -max_offset2, j=0; off2 <= max_offset2; ++off2, ++j )
00658 {
00659 responses(i,j) = this -> compute_response( mapped_pixels, offset1[i].shift_ + offset2[j].shift_ );
00660
00661 if ( ( !is_best_initialized || responses(i,j) < min_response )
00662 && responses(i,j) != max_response_value )
00663 {
00664 is_best_initialized = true;
00665 min_response = responses(i,j);
00666 best_off1 = off1;
00667 best_off2 = off2;
00668 }
00669 }
00670 }
00671 if ( !is_best_initialized )
00672 {
00673 DebugMacro(1, "For mapped feature: " << mapped_feature->location()
00674 << ", the slide window is invalid." << vcl_endl );
00675 return;
00676 }
00677
00678 const vnl_int_3& best1 = offset1[best_off1+max_offset1].shift_;
00679 const vnl_int_3& best2 = offset2[best_off2+max_offset2].shift_;
00680 match_location = mapped_feature->location();
00681 for (unsigned int i=0; i<3; i++)
00682 match_location[i] += double(best1[i]) + double(best2[i]);
00683
00684
00685
00686 assert( 0 );
00687 #if 0 // commented out
00688
00689
00690
00691
00692 int idx1 = 0, idx2 = 0;
00693 int deriv_loc1 = best_off1;
00694 if ( deriv_loc1 == -max_offset ) ++deriv_loc1;
00695 else if ( deriv_loc1 == max_offset ) --deriv_loc1;
00696 idx1 = deriv_loc1 + max_offset;
00697 idx2 = best_off2 + max_offset;
00698
00699
00700
00701
00702
00703
00704
00705 double sub_offset1;
00706
00707 if ( best_off1 == max_offset || best_off1 == -max_offset )
00708 sub_offset1 = best_off1;
00709 else if ( responses[ idx1 - 1 ][ idx2 ] == max_response_value ||
00710 responses[ idx1 + 1 ][ idx2 ] == max_response_value )
00711 {
00712 sub_offset1 = idx1 - max_offset;
00713 }
00714 else
00715 {
00716 vcl_vector< double > responses_for_sub_pixel( 3 );
00717 responses_for_sub_pixel[ 0 ] = responses[ idx1 - 1 ][ idx2 ];
00718 responses_for_sub_pixel[ 1 ] = responses[ idx1 ][ idx2 ];
00719 responses_for_sub_pixel[ 2 ] = responses[ idx1 + 1 ][ idx2 ];
00720 sub_offset1 = sub_pixel( responses_for_sub_pixel ) + idx1 - max_offset;
00721
00722
00723 if ( sub_offset1 < -max_offset ) sub_offset1 = -max_offset;
00724 if ( sub_offset1 > max_offset ) sub_offset1 = max_offset;
00725 DBG( vcl_cout << " sub_offset1 = " << sub_offset1 << " in [ "
00726 << -max_offset << " , " << max_offset << " ] " << vcl_endl );
00727 }
00728
00729 double second_d1 = vnl_math_abs( responses[ idx1-1 ][ idx2 ] + responses[ idx1+1 ][ idx2 ]
00730 - 2 * responses[ idx1 ][ idx2 ] );
00731
00732 int deriv_loc2 = best_off2;
00733 if ( deriv_loc2 == -max_offset ) ++deriv_loc2;
00734 else if ( deriv_loc2 == max_offset ) --deriv_loc2;
00735 idx2 = deriv_loc2 + max_offset;
00736 idx1 = best_off1 + max_offset;
00737 double sub_offset2;
00738 if ( best_off2 == max_offset || best_off2 == -max_offset )
00739 sub_offset2 = best_off2;
00740 else if ( responses[ idx1 ][ idx2 - 1 ] == max_response_value ||
00741 responses[ idx1 ][ idx2 + 1 ] == max_response_value )
00742 {
00743 sub_offset2 = idx2 - max_offset;
00744 }
00745 else
00746 {
00747 vcl_vector< double > responses_for_sub_pixel( 3 );
00748 responses_for_sub_pixel[ 0 ] = responses[ idx1 ][ idx2 - 1 ];
00749 responses_for_sub_pixel[ 1 ] = responses[ idx1 ][ idx2 ];
00750 responses_for_sub_pixel[ 2 ] = responses[ idx1 ][ idx2 + 1 ];
00751 sub_offset2 = sub_pixel( responses_for_sub_pixel ) + idx2 - max_offset;
00752 if ( sub_offset2 < -max_offset ) sub_offset2 = -max_offset;
00753 if ( sub_offset2 > max_offset ) sub_offset2 = max_offset;
00754 DBG( vcl_cout << " sub_offset2 = " << sub_offset2 << " in [ "
00755 << -max_offset << " , " << max_offset << " ] " << vcl_endl; );
00756 }
00757
00758 double second_d2 = vnl_math_abs( responses[ idx1 ][ idx2-1 ] + responses[ idx1 ][ idx2+1 ]
00759 - 2 * responses[ idx1 ][ idx2 ] );
00760
00761 second_derivative = vnl_math_min( second_d1, second_d2 );
00762 match_location = mapped_location + basis1 * sub_offset1 + basis2 * sub_offset2;
00763 DBG( vcl_cout << "best match :\n" << match_location << vcl_endl );
00764 #endif // 0
00765 } else {
00766 vcl_cerr << "Code doesn't handle a normal subspace of greater than two dimenions.\n";
00767 assert( false );
00768 }
00769 matched_to_features . clear();
00770 match_weights . clear();
00771 rgrl_feature_sptr mf_ptr;
00772 if ( mapped_feature -> is_type( rgrl_feature_face_region::type_id() ) )
00773 {
00774 rgrl_feature_face_region * face_ptr =
00775 rgrl_cast<rgrl_feature_face_region *> ( mapped_feature );
00776 mf_ptr = new rgrl_feature_face_region( match_location, face_ptr -> normal() );
00777 } else
00778 {
00779 rgrl_feature_trace_region * trace_ptr =
00780 rgrl_cast<rgrl_feature_trace_region *> ( mapped_feature );
00781 mf_ptr = new rgrl_feature_trace_region( match_location, trace_ptr -> tangent() );
00782 }
00783
00784
00785 matched_to_features . push_back( mf_ptr );
00786 double weight = second_derivative / (1.0 + min_response);
00787 assert( weight >= 0.0 );
00788
00789 DebugMacro(2, "second derivative: " << second_derivative
00790 << "\nmin_response: " << min_response << "\nweight : " << weight << vcl_endl );
00791 match_weights.push_back( weight );
00792 }
00793
00794 template <class PixelType>
00795 double
00796 rgrl_matcher_pseudo_int_3d<PixelType> ::
00797 compute_response( rgrl_mapped_pixel_vector_type const& mapped_pixels,
00798 vnl_int_3 const& shift ) const
00799 {
00800 const unsigned size = mapped_pixels.size();
00801
00802
00803
00804
00805 vcl_vector< double > a;
00806 vcl_vector< double > b;
00807 vcl_vector< double > weights;
00808 double intensity;
00809 vnl_int_3 loc;
00810
00811
00812 a.reserve( size );
00813 b.reserve( size );
00814 weights.reserve( size );
00815
00816 for ( unsigned i = 0; i < size; ++i )
00817 {
00818 loc = mapped_pixels[i].location + shift;
00819
00820
00821 if ( !pixel_in_range( to_image_, mask_, loc ) ) {
00822 DebugMacro(2, "out of range: " << loc << " ( shift: " << shift << " )\n" );
00823 return max_response_value;
00824 }
00825
00826
00827 a.push_back( (double)(mapped_pixels[i].intensity) );
00828
00829 intensity = to_image_( loc[0], loc[1], loc[2] );
00830 b.push_back( intensity );
00831
00832 weights.push_back( mapped_pixels[i].weight );
00833 }
00834
00835
00836 double val = evaluator_->evaluate( a, b, weights );
00837
00838 return val;
00839 }
00840
00841
00842
00843 template<class PixelType>
00844 void
00845 rgrl_matcher_pseudo_int_3d<PixelType>::
00846 sample_pixels_along_direction( vcl_vector<discrete_shift_node>& two_dir_shifts,
00847 vnl_double_3 dir,
00848 double max_length ) const
00849 {
00850
00851
00852
00853
00854
00855 dir /= 2.0 * dir.magnitude();
00856 max_length *= 2.0;
00857
00858 DebugMacro(2, "normal basis :\n" << dir << vcl_endl );
00859
00860
00861
00862 vnl_int_3 prev, current;
00863 double len;
00864 double abs_ele;
00865 vcl_vector<discrete_shift_node> locs;
00866 locs.reserve( int(2*max_length) );
00867
00868
00869 const double epsilon = 1.0/(100*max_length);
00870 const double min_step_size = 1.0/(2*max_length);
00871 prev=vnl_int_3(0, 0, 0);
00872 locs.push_back( discrete_shift_node(prev, 0) );
00873 len = 1e-10;
00874 while ( len < max_length )
00875 {
00876 double delta_len, min_delta_len = 1e10;
00877 int min_index = 0;
00878 for (unsigned i=0; i<3; i++) {
00879 abs_ele = vcl_abs( dir[i] );
00880
00881 if ( abs_ele < min_step_size )
00882 continue;
00883
00884
00885 delta_len = vcl_ceil( len * abs_ele ) / abs_ele - len;
00886 if ( delta_len < min_delta_len && delta_len > 0 )
00887 {
00888 min_index = i;
00889 min_delta_len = delta_len;
00890 }
00891 }
00892
00893 assert( min_delta_len > 0.0 );
00894
00895 if ( len+min_delta_len > max_length )
00896 break;
00897
00898
00899 current = prev;
00900 if ( dir[min_index] < 0 )
00901 current[min_index] -= 1;
00902 else
00903 current[min_index] += 1;
00904
00905
00906
00907
00908 locs.push_back( discrete_shift_node( current, (len+min_delta_len)/2 ) );
00909 prev = current;
00910
00911
00912
00913 len += min_delta_len+epsilon;
00914 }
00915
00916
00917 two_dir_shifts.clear();
00918 two_dir_shifts.reserve( locs.size()*2-1 );
00919
00920 for (int i=locs.size()-1; i>0; i--)
00921 two_dir_shifts.push_back( - locs[i] );
00922
00923
00924 for (unsigned int i=0; i<locs.size(); i++)
00925 two_dir_shifts.push_back( locs[i] );
00926 }
00927
00928 #endif // rgrl_matcher_pseudo_int_3d_txx_