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