40 #include <Core/ITKCommon/extrema.hxx>
41 #include <Core/ITKCommon/pyramid.hxx>
42 #include <Core/ITKCommon/Transform/itkLegendrePolynomialTransform.h>
43 #include <Core/ITKCommon/common.hxx>
55 error_(std::numeric_limits<double>::max()),
68 assert(a != NULL && b != NULL);
72 inline bool operator < (
const match_t & match)
const
75 assert(a_ != NULL && b_ != NULL);
77 return error_ < match.error_;
95 extern image_t::Pointer
96 load_image(
const bfs::path & fn_load,
97 const unsigned int & shrink_factor,
98 const double & pixel_spacing);
106 const unsigned int index,
107 const bfs::path & fn_load,
108 const image_t * image,
109 const mask_t * image_mask,
110 const unsigned int & descriptor_version,
111 unsigned int num_scales = 1,
112 const bool & generate_keys =
true,
113 const bfs::path & fn_debug =
"");
121 std::list<match_t> & ab_list,
122 std::list<const match_t *> & ab,
123 const double & percentage_to_keep);
129 prefilter_matches_v1(
const bfs::path & fn_prefix,
130 const double & peak_ratio_threshold,
131 const std::list<const match_t *> & complete,
132 std::list<const match_t *> & filtered);
138 prefilter_matches_v2(
const bfs::path & fn_prefix,
139 const double & distortion_threshold,
140 const std::list<const match_t *> & complete,
141 std::list<const match_t *> & filtered);
147 rematch_keys(
const bfs::path & fn_prefix,
150 const std::list<descriptor_t> & a,
151 const std::list<descriptor_t> & b,
152 const base_transform_t * t_ab,
153 const double & window_radius,
154 std::list<match_t> & ab);
160 rematch_keys(
const bfs::path & fn_prefix,
163 const base_transform_t * t_ab,
164 const double & window_radius,
165 std::list<match_t> & ab_list,
166 std::list<const match_t *> & ab,
167 const double & percentage_to_keep);
170 bestfit_stats(
const std::vector<const match_t *> & ab,
171 const std::list<unsigned int> & inliers);
177 template <
class transform_t>
179 solve_for_parameters(
181 const unsigned int & start_with_degree,
182 const unsigned int & degrees_included,
185 const std::vector<const match_t *> & ab,
188 const std::list<unsigned int> & bestfit)
190 std::vector<image_t::PointType> uv(bestfit.size());
191 std::vector<image_t::PointType> xy(bestfit.size());
193 unsigned int position = 0;
194 for (std::list<unsigned int>::const_iterator i = bestfit.begin();
198 const unsigned int & index = *i;
199 const match_t * match = ab[index];
200 const image_t::PointType & a_uv = match->a_->extrema_->local_coords_;
201 const image_t::PointType & b_xy = match->b_->extrema_->local_coords_;
208 t_ab->solve_for_parameters(start_with_degree, degrees_included, uv, xy);
214 template <
class transform_t>
216 refine_inliers(
const transform_t * t_ab,
218 const std::vector<const match_t *> & ab,
219 std::vector<bool> & is_inlier,
220 std::list<unsigned int> & inliers,
221 double & model_quality)
224 const unsigned int & num_matches = ab.size();
226 const double inlier_threshold = t * t;
227 double inlier_error = 0.0;
228 double total_error = 0.0;
231 bool removed_inliers =
false;
232 bool added_inliers =
false;
233 for (
unsigned int i = 0; i < num_matches; i++)
238 const image_t::PointType & a_uv = match->a_->extrema_->local_coords_;
239 const image_t::PointType & b_xy = match->b_->extrema_->local_coords_;
241 image_t::PointType a_xy = t_ab->TransformPoint(a_uv);
242 double dx = (a_xy[0] - b_xy[0]);
243 double dy = (a_xy[1] - b_xy[1]);
244 double d2 = dx * dx + dy * dy;
251 if (d2 <= inlier_threshold)
259 inliers.push_back(i);
261 added_inliers =
true;
264 else if (is_inlier[i])
267 is_inlier[i] =
false;
268 removed_inliers =
true;
272 const unsigned int & inliers_count = inliers.size();
274 if (inliers_count > 0)
277 model_quality = double(inliers_count);
290 return removed_inliers || added_inliers;
296 template <
class transform_t>
299 const unsigned int & k,
300 const unsigned int & n,
301 const unsigned int & d,
305 const transform_t * initial_t_ab,
306 const unsigned int & start_with_degree,
307 const unsigned int & degrees_included,
310 const std::vector<const match_t *> & ab,
313 typename transform_t::ParametersType & best_params,
314 std::list<unsigned int> & bestfit,
315 double & bestquality)
317 const double initial_bestquality = bestquality;
318 best_params = initial_t_ab->GetParameters();
320 typename transform_t::Pointer t_ab = transform_t::New();
321 t_ab->SetFixedParameters(initial_t_ab->GetFixedParameters());
322 t_ab->SetParameters(initial_t_ab->GetParameters());
325 const unsigned int & num_matches = ab.size();
328 if (num_matches < n)
return false;
329 if (degrees_included == 0)
return false;
332 std::vector<image_t::PointType> uv(n);
333 std::vector<image_t::PointType> xy(n);
335 bool start_with_bestfit = bestfit.size() > 0;
337 for (
unsigned int i = 0; i < k; i++)
339 std::list<unsigned int> inliers;
340 std::vector<bool> is_inlier;
341 is_inlier.assign(num_matches,
false);
343 if (!start_with_bestfit)
346 for (
unsigned int j = 0; j < n; j++)
355 double nx = double(num_matches);
366 index = std::min(num_matches - 1, (
unsigned int)(x));
367 if (!is_inlier[index])
break;
370 inliers.push_back(index);
371 is_inlier[index] =
true;
373 const match_t * match = ab[index];
374 uv[j] = match->a_->extrema_->local_coords_;
375 xy[j] = match->b_->extrema_->local_coords_;
379 t_ab->solve_for_parameters(start_with_degree, degrees_included, uv, xy);
384 std::list<unsigned int>::const_iterator iter = bestfit.begin();
385 for (
unsigned int j = 0; j < bestfit.size(); j++, ++iter)
387 const unsigned int &
id = *iter;
388 inliers.push_back(
id);
389 is_inlier[id] =
true;
392 solve_for_parameters<transform_t>(t_ab,
397 start_with_bestfit =
false;
401 double model_quality = std::numeric_limits<double>::max();
402 bool inliers_were_altered = refine_inliers<transform_t>(t_ab,
409 if (model_quality > bestquality)
413 double quality = model_quality;
414 for (
unsigned int j = 0; j < 100 && inliers_were_altered; j++)
416 if (inliers.size() < n)
break;
419 solve_for_parameters<transform_t>(t_ab,
426 inliers_were_altered = refine_inliers<transform_t>(t_ab,
434 if (quality > bestquality && inliers.size() >= n)
436 solve_for_parameters<transform_t>(t_ab,
443 bestquality = quality;
444 best_params = t_ab->GetParameters();
446 std::cout <<
"FIXME: quality: " << bestquality
447 <<
", iteration: " << i << std::endl;
452 return initial_bestquality < bestquality;
465 template <
typename transform_t>
466 typename transform_t::Pointer
467 match(
const unsigned int order,
470 const bfs::path & fn_debug)
473 const double t = 2.0 * a.octave_[0].L_[0]->GetSpacing()[0]
474 * (1.0 + integer_power<double>(2.0, a.octaves()));
477 std::cout <<
"matching " << a.fn_data_ <<
" to " << b.fn_data_ << std::endl;
478 std::list<match_t> ab_list;
479 std::list<const match_t *> ab_sorted;
480 match_keys(a, b, ab_list, ab_sorted, 1.0);
482 std::cout <<
"pre-filtering the key matches, t: " << t << std::endl;
483 std::list<const match_t *> ab_sorted_filtered;
485 prefilter_matches_v2(fn_debug, 0.1, ab_sorted, ab_sorted_filtered);
489 const unsigned int k = 33333;
490 std::cout <<
"RANSAC will try " << k <<
" iterations (instead of "
491 << 20 * ab_sorted.size() <<
")" << std::endl;
494 visualize_matches_v2(a, b, ab_sorted_filtered, fn_debug);
498 typename transform_t::Pointer t_ab =
499 setup_transform<transform_t, image_t>(b.octave_[0].L_[0]);
503 image_t::PointType center;
504 center[0] = t_ab->GetUc();
505 center[1] = t_ab->GetVc();
508 std::vector<const match_t *> ab;
509 ab.assign(ab_sorted_filtered.begin(), ab_sorted_filtered.end());
511 std::cout <<
"estimating the affine transform" << std::endl;
512 typename transform_t::ParametersType params_01;
513 std::list<unsigned int> bestfit;
514 double bestquality = 0.0;
516 const unsigned int initial_order = std::min(2u, order);
517 const unsigned int initial_coeff =
518 transform_t::count_coefficients(0, initial_order);
520 if (RANSAC<transform_t>(k,
524 t_ab, 0, initial_order,
526 params_01, bestfit, bestquality))
528 t_ab->SetParameters(params_01);
531 bestfit_stats(ab, bestfit);
535 visualize_best_fit(fn_debug +
"d01a-",
545 #ifdef TRY_REMATCHING
547 std::cout <<
"re-matching the keys based on the affine transform estimate"
549 rematch_keys(fn_debug, a, b, t_ab,
551 ab_list, ab_sorted, 1.0);
554 ab_sorted_filtered.clear();
555 prefilter_matches_v2(fn_debug, 0.1, ab_sorted, ab_sorted_filtered);
558 if (fn_debug.size() != 0)
560 visualize_matches_v2(a, b, ab_sorted_filtered, fn_debug +
"rematched");
565 ab.assign(ab_sorted_filtered.begin(), ab_sorted_filtered.end());
568 std::cout <<
"re-estimating the affine transform" << std::endl;
571 if (RANSAC<transform_t>(k,
575 t_ab, 0, initial_order,
577 params_01, bestfit, bestquality))
579 t_ab->SetParameters(params_01);
582 bestfit_stats(ab, bestfit);
586 image_t::PointType shifted_center = t_ab->TransformPoint(center);
587 double shift_x = shifted_center[0] - center[0];
588 double shift_y = shifted_center[1] - center[1];
589 t_ab->setup_translation(shift_x, shift_y);
590 solve_for_parameters<transform_t>
591 (t_ab, 0, initial_order, ab, bestfit);
595 visualize_best_fit(fn_debug +
"d01b-",
607 unsigned int remaining_degrees = std::min(2u, order - 2);
608 unsigned int remaining_coeff =
609 transform_t::count_coefficients(2, remaining_degrees);
612 std::cout <<
"estimating the higher order transform "
613 <<
"(affine parameters remain fixed)" << std::endl;
614 typename transform_t::ParametersType params_0123;
620 if (RANSAC<transform_t>(k,
624 t_ab, 2, remaining_degrees,
626 params_0123, bestfit, bestquality))
628 t_ab->SetParameters(params_0123);
631 bestfit_stats(ab, bestfit);
637 solve_for_parameters<transform_t>
638 (t_ab, 0, 2, ab, bestfit);
640 solve_for_parameters<transform_t>
641 (t_ab, 2, remaining_degrees, ab, bestfit);
645 visualize_best_fit(fn_debug +
"d0123-",
657 #endif // TRY_REMATCHING
Definition: extrema.hxx:82
Definition: pyramid.hxx:173