35 #ifndef GRID_COMMON_HXX_
36 #define GRID_COMMON_HXX_
39 #include <Core/ITKCommon/common.hxx>
40 #include <Core/ITKCommon/FFT/fft_common.hxx>
41 #include <Core/ITKCommon/Transform/the_grid_transform.hxx>
42 #include <Core/ITKCommon/Transform/itkGridTransform.h>
43 #include <Core/ITKCommon/Optimizers/itkRegularStepGradientDescentOptimizer2.h>
44 #include <Core/ITKCommon/Optimizers/optimizer_observer.hxx>
46 #include <Core/Utils/Log.h>
48 #include <boost/filesystem.hpp>
59 #include <itkCommand.h>
60 #include <itkImageMaskSpatialObject.h>
61 #include <itkImageRegistrationMethod.h>
62 #include <itkMultiResolutionImageRegistrationMethod.h>
63 #include <itkNormalizedCorrelationImageToImageMetric.h>
65 namespace bfs=boost::filesystem;
78 #if defined(DEBUG_REFINE_ONE_POINT) || defined(DEBUG_ESTIMATE_DISPLACEMENT)
79 static int COUNTER = 0;
96 const pnt2d_t & tile_min,
97 const pnt2d_t & tile_max,
98 const mask_t * tile_mask,
99 base_transform_t::ConstPointer mosaic_to_tile,
100 unsigned int max_iterations = 100,
101 double min_step_scale = 1e-12,
102 double min_error_sqrd = 1e-16,
103 unsigned int pick_up_pace_steps = 5
113 const pnt2d_t & tile_min,
114 const pnt2d_t & tile_max,
115 const mask_t * tile_mask,
116 base_transform_t::ConstPointer mosaic_to_tile,
117 unsigned int max_iterations,
118 double min_step_scale,
119 double min_error_sqrd,
120 unsigned int pick_up_pace_steps);
125 template <
class TImage>
127 estimate_displacement(
double & best_metric,
128 translate_transform_t::Pointer & best_transform,
132 const vec2d_t & offset,
140 const typename TImage::SizeType & period_sz,
143 const double overlap_min = 0.05,
144 const double overlap_max = 1.0,
145 const mask_t * mask_a = NULL,
146 const mask_t * mask_b = NULL,
148 const unsigned int num_perms = 4)
150 vec2d_t best_offset = best_transform->GetOffset();
152 const unsigned int & w = period_sz[0];
153 const unsigned int & h = period_sz[1];
155 typedef typename TImage::SpacingType spacing_t;
156 spacing_t spacing = b->GetSpacing();
157 double sx = spacing[0];
158 double sy = spacing[1];
161 const double x = lm.x_;
162 const double y = lm.y_;
164 const vec2d_t t[] = {
165 vec2d(sx * x, sy * y),
166 vec2d(sx * (x - w), sy * y),
167 vec2d(sx * x, sy * (y - h)),
168 vec2d(sx * (x - w), sy * (y - h))
171 #ifdef DEBUG_ESTIMATE_DISPLACEMENT
172 static const bfs::path fn_save(
"/tmp/estimate_displacement-");
173 static int COUNTER2 = 0;
175 the_text_t::number(COUNTER, 3,
'0') +
"-" +
176 the_text_t::number(COUNTER2, 3,
'0') +
"-";
181 translate_transform_t::Pointer ti = translate_transform_t::New();
182 ti->SetOffset(-offset);
183 save_rgb<TImage>(fn_save + suffix +
"0-init.png",
192 std::ostringstream oss;
193 for (
unsigned int i = 0; i < num_perms; i++)
195 translate_transform_t::Pointer ti = translate_transform_t::New();
196 ti->SetOffset(t[i] - offset);
198 double area_ratio = overlap_ratio<TImage>(a, b, ti);
199 oss << i <<
": " << std::setw(3) <<
static_cast<int>(area_ratio * 100.0) <<
"% of overlap, ";
201 if (area_ratio < overlap_min || area_ratio > overlap_max)
203 oss <<
"skipping..." << std::endl;
218 double metric = my_metric<TImage>(area_ratio,
229 if (metric < best_metric)
232 best_metric = metric;
233 oss <<
" - better..." << std::endl;
235 #ifdef DEBUG_ESTIMATE_DISPLACEMENT
237 save_rgb<TImage>(fn_save + suffix +
238 the_text_t::number(i + 1) +
"-perm.png",
248 oss <<
" - worse..." << std::endl;
252 CORE_LOG_MESSAGE(oss.str());
253 best_transform->SetOffset(best_offset);
263 template <
class TImage>
265 match_one_pair(translate_transform_t::Pointer & best_transform,
267 const mask_t * fi_mask,
270 const mask_t * mi_mask,
275 const typename TImage::SizeType & period_sz,
277 const double & overlap_min,
278 const double & overlap_max,
280 image_t::PointType offset_min,
281 image_t::PointType offset_max,
283 const double & lp_filter_r,
284 const double & lp_filter_s,
286 const unsigned int max_peaks,
287 const bool & consider_zero_displacement)
289 static const vec2d_t offset = vec2d(0, 0);
290 best_transform = NULL;
292 std::list<local_max_t> max_list;
293 unsigned int total_peaks = find_correlation<TImage>(max_list,
299 unsigned int num_peaks = reject_negligible_maxima(max_list, 2.0);
300 std::ostringstream oss;
301 oss << num_peaks <<
'/' << total_peaks <<
" eligible peaks, ";
303 if (num_peaks > max_peaks)
305 oss <<
"skipping..." << std::endl;
306 CORE_LOG_MESSAGE(oss.str());
307 return std::numeric_limits<double>::max();
310 double best_metric = std::numeric_limits<double>::max();
311 best_transform = translate_transform_t::New();
312 best_transform->SetIdentity();
314 if (consider_zero_displacement)
317 estimate_displacement<TImage>(best_metric,
332 for (std::list<local_max_t>::iterator j = max_list.begin();
333 j != max_list.end(); ++j)
335 oss <<
"evaluating permutations..." << std::endl;
338 double prev_metric = best_metric;
339 vec2d_t prev_offset = best_transform->GetOffset();
341 estimate_displacement<TImage>(best_metric,
354 double overlap = overlap_ratio(fi, mi, best_transform);
355 if (overlap < overlap_min || overlap > overlap_max)
357 best_metric = prev_metric;
358 best_transform->SetOffset(prev_offset);
361 CORE_LOG_MESSAGE(oss.str());
373 template <
class TImage>
375 match_one_pair(translate_transform_t::Pointer & best_transform,
376 const TImage * fi_large,
377 const mask_t * fi_large_mask,
383 const mask_t * mi_mask,
387 const vec2d_t & offset,
389 const double & overlap_min,
390 const double & overlap_max,
395 const double & lp_filter_r,
396 const double & lp_filter_s,
398 const unsigned int max_peaks,
399 const bool & consider_zero_displacement)
401 best_transform = NULL;
403 std::list<local_max_t> max_list;
404 unsigned int total_peaks = find_correlation<TImage>(max_list,
410 unsigned int num_peaks = reject_negligible_maxima(max_list, 2.0);
411 std::ostringstream oss;
412 oss << num_peaks <<
'/' << total_peaks <<
" eligible peaks, ";
414 if (num_peaks > max_peaks)
416 oss <<
"skipping..." << std::endl;
417 CORE_LOG_MESSAGE(oss.str());
418 return std::numeric_limits<double>::max();
421 double best_metric = std::numeric_limits<double>::max();
422 best_transform = translate_transform_t::New();
423 best_transform->SetIdentity();
425 typename TImage::SizeType period_sz = mi->GetLargestPossibleRegion().GetSize();
427 if (consider_zero_displacement)
430 estimate_displacement<TImage>(best_metric,
445 for (std::list<local_max_t>::iterator j = max_list.begin();
446 j != max_list.end(); ++j)
448 oss <<
"evaluating permutations..." << std::endl;
451 double prev_metric = best_metric;
452 vec2d_t prev_offset = best_transform->GetOffset();
454 estimate_displacement<TImage>(best_metric,
467 double overlap = overlap_ratio(fi, mi, best_transform);
468 if (overlap < overlap_min || overlap > overlap_max)
470 best_metric = prev_metric;
471 best_transform->SetOffset(prev_offset);
474 CORE_LOG_MESSAGE(oss.str());
483 template <
typename TImage>
485 refine_one_point_fft(vec2d_t & shift,
486 const pnt2d_t & origin,
489 const TImage * tile_0,
490 const mask_t * mask_0,
493 const TImage * img_0,
494 const mask_t * msk_0,
495 const TImage * img_1,
496 const mask_t * msk_1)
499 translate_transform_t::Pointer translate;
501 match_one_pair<TImage>(translate,
517 vec2d(origin[0], origin[1]),
526 #ifdef DEBUG_REFINE_ONE_POINT
527 static const bfs::path fn_save(
"/tmp/refine_one_point_fft-");
528 bfs::path suffix = the_text_t::number(COUNTER, 3,
'0');
530 save_composite(fn_save + suffix +
"-a.png",
533 identity_transform_t::New(),
535 #endif // DEBUG_REFINE_ONE_POINT
537 #if defined(DEBUG_REFINE_ONE_POINT) || defined(DEBUG_ESTIMATE_DISPLACEMENT)
541 if (metric == std::numeric_limits<double>::max())
546 #ifdef DEBUG_REFINE_ONE_POINT
547 save_composite(fn_save + suffix +
"-b.png",
550 translate.GetPointer(),
552 #endif // DEBUG_REFINE_ONE_POINT
554 shift = -translate->GetOffset();
562 template <
typename TImage>
564 refine_one_point_helper(
const pnt2d_t & center,
565 const pnt2d_t & origin,
566 const double & min_overlap,
569 const TImage * tile_0,
570 const mask_t * mask_0,
571 const TImage * tile_1,
572 const mask_t * mask_1,
576 const base_transform_t * t_01,
585 const typename TImage::SizeType & sz,
586 const typename TImage::SpacingType & sp)
589 typedef itk::LinearInterpolateImageFunction<TImage, double> interpolator_t;
590 typename interpolator_t::Pointer interpolator[] = {
591 interpolator_t::New(),
592 interpolator_t::New()
595 interpolator[0]->SetInputImage(tile_0);
596 interpolator[1]->SetInputImage(tile_1);
598 if (!interpolator[0]->IsInsideBuffer(center))
608 typename TImage::IndexType index;
611 unsigned int area[] = { 0, 0 };
614 for (
unsigned int y = 0; y < sz[1]; y++)
616 mosaic_pt[1] = origin[1] + double(y) * sp[1];
618 for (
unsigned int x = 0; x < sz[0]; x++)
620 mosaic_pt[0] = origin[0] + double(x) * sp[0];
625 if (interpolator[0]->IsInsideBuffer(tile_pt) &&
626 pixel_in_mask<mask_t>(mask_0, tile_pt))
628 double p = interpolator[0]->Evaluate(tile_pt);
629 img_0->SetPixel(index, (
unsigned char)(std::min(255.0, p)));
630 msk_0->SetPixel(index, 1);
635 img_0->SetPixel(index, 0);
636 msk_0->SetPixel(index, 0);
640 tile_pt = t_01->TransformPoint(mosaic_pt);
641 if (interpolator[1]->IsInsideBuffer(tile_pt) &&
642 pixel_in_mask<mask_t>(mask_1, tile_pt))
644 double p = interpolator[1]->Evaluate(tile_pt);
645 img_1->SetPixel(index, (
unsigned char)(std::min(255.0, p)));
646 msk_1->SetPixel(index, 1);
651 img_1->SetPixel(index, 0);
652 msk_1->SetPixel(index, 0);
658 double max_area = double(sz[0] * sz[1]);
660 double(area[0]) / max_area,
661 double(area[1]) / max_area
664 if (a[0] < min_overlap || a[1] < min_overlap)
675 template <
typename TImage>
677 refine_one_point_fft(vec2d_t & shift,
678 const pnt2d_t & center,
679 const pnt2d_t & origin,
680 const double & min_overlap,
683 const TImage * tile_0,
684 const mask_t * mask_0,
685 const TImage * tile_1,
686 const mask_t * mask_1,
690 const base_transform_t * t_01,
699 const typename TImage::SizeType & sz,
700 const typename TImage::SpacingType & sp)
702 if (!refine_one_point_helper<TImage>(center,
720 return refine_one_point_fft<TImage>(shift,
733 template <
typename TImage>
735 refine_one_point_fft(vec2d_t & shift,
736 const pnt2d_t & center,
737 const double & min_overlap,
739 const TImage * tile_0,
740 const mask_t * mask_0,
741 const TImage * tile_1,
742 const mask_t * mask_1,
746 const base_transform_t * t_01,
749 const unsigned int & neighborhood)
751 typename TImage::SpacingType sp = tile_1->GetSpacing();
752 typename TImage::SizeType sz;
753 sz[0] = neighborhood;
754 sz[1] = neighborhood;
756 pnt2d_t origin(center);
757 origin[0] -= 0.5 * double(sz[0]) * sp[0];
758 origin[1] -= 0.5 * double(sz[1]) * sp[1];
760 typename TImage::Pointer img[] = {
761 make_image<TImage>(sz),
762 make_image<TImage>(sz)
765 mask_t::Pointer msk[] = {
766 make_image<mask_t>(sz),
767 make_image<mask_t>(sz)
770 img[0]->SetSpacing(sp);
771 img[1]->SetSpacing(sp);
772 msk[0]->SetSpacing(sp);
773 msk[1]->SetSpacing(sp);
775 return refine_one_point_fft<TImage>(shift,
795 template <
typename TImage>
797 refine_one_point_fft(vec2d_t & shift,
800 const TImage * img_0,
801 const mask_t * msk_0,
802 const TImage * img_1,
803 const mask_t * msk_1)
805 typename TImage::SizeType period_sz =
806 img_1->GetLargestPossibleRegion().GetSize();
809 translate_transform_t::Pointer translate;
811 match_one_pair<TImage>(translate,
830 #ifdef DEBUG_REFINE_ONE_POINT
831 static const bfs::path fn_save(
"/tmp/refine_one_point_fft-");
832 bfs::path suffix = the_text_t::number(COUNTER, 3,
'0');
834 save_composite(fn_save + suffix +
"-a.png",
837 identity_transform_t::New(),
839 #endif // DEBUG_REFINE_ONE_POINT
841 #if defined(DEBUG_REFINE_ONE_POINT) || defined(DEBUG_ESTIMATE_DISPLACEMENT)
845 if (metric == std::numeric_limits<double>::max())
850 #ifdef DEBUG_REFINE_ONE_POINT
851 save_composite(fn_save + suffix +
"-b.png",
854 translate.GetPointer(),
856 #endif // DEBUG_REFINE_ONE_POINT
858 shift = -translate->GetOffset();
868 template <
typename TImage,
typename TMask>
870 extract(
const typename TImage::PointType & origin,
875 TImage * tile_region,
878 const typename TImage::PixelType & bg =
879 itk::NumericTraits<typename TImage::PixelType>::Zero)
881 tile_region->SetOrigin(origin);
882 mask_region->SetOrigin(origin);
885 typedef itk::LinearInterpolateImageFunction<TImage, double> interpolator_t;
886 typename interpolator_t::Pointer interpolator = interpolator_t::New();
887 interpolator->SetInputImage(tile);
890 typename TImage::PointType tile_pt;
891 typename TImage::PixelType tile_val;
892 typename TMask::IndexType mask_ix;
893 typename TMask::PixelType mask_val;
895 static const typename TMask::PixelType mask_min =
896 itk::NumericTraits<typename TMask::PixelType>::Zero;
898 static const typename TMask::PixelType mask_max =
899 itk::NumericTraits<typename TMask::PixelType>::One;
901 unsigned int num_pixels = 0;
903 typedef itk::ImageRegionIteratorWithIndex<TImage> itex_t;
904 itex_t itex(tile_region, tile_region->GetLargestPossibleRegion());
905 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
910 tile_region->TransformIndexToPhysicalPoint(itex.GetIndex(), tile_pt);
911 if (interpolator->IsInsideBuffer(tile_pt))
916 mask->TransformPhysicalPointToIndex(tile_pt, mask_ix);
917 mask_val = mask->GetPixel(mask_ix);
920 if (mask_val != mask_min)
923 (
typename TImage::PixelType)(interpolator->Evaluate(tile_pt));
929 mask_region->SetPixel(itex.GetIndex(), mask_val);
939 template <
typename TImage>
941 refine_one_point_helper(
942 const TImage * tile_0,
943 const mask_t * mask_0,
944 const TImage * tile_1,
945 const mask_t * mask_1,
949 const pnt2d_t & center,
953 const double & min_overlap,
961 const typename TImage::SizeType & sz =
962 img_0->GetLargestPossibleRegion().GetSize();
963 const typename TImage::SpacingType & sp =
966 origin[0] = center[0] - (double(sz[0]) * sp[0]) / 2;
967 origin[1] = center[1] - (double(sz[1]) * sp[1]) / 2;
970 origin + vec2d(sz[0] * sp[0], 0),
971 origin + vec2d(sz[0] * sp[0], sz[1] * sp[1]),
972 origin + vec2d(0, sz[1] * sp[1])
976 typename TImage::IndexType tmp_ix;
977 if (!(tile_0->TransformPhysicalPointToIndex(origin, tmp_ix) ||
978 tile_0->TransformPhysicalPointToIndex(corner[0], tmp_ix) ||
979 tile_0->TransformPhysicalPointToIndex(corner[1], tmp_ix) ||
980 tile_0->TransformPhysicalPointToIndex(corner[2], tmp_ix)) ||
981 !(tile_1->TransformPhysicalPointToIndex(origin, tmp_ix) ||
982 tile_1->TransformPhysicalPointToIndex(corner[0], tmp_ix) ||
983 tile_1->TransformPhysicalPointToIndex(corner[1], tmp_ix) ||
984 tile_1->TransformPhysicalPointToIndex(corner[2], tmp_ix)))
990 unsigned int area[] = { 0, 0 };
992 area[0] = extract<TImage, mask_t>(origin,
998 area[1] = extract<TImage, mask_t>(origin,
1005 double max_area = double(sz[0] * sz[1]);
1007 double(area[0]) / max_area,
1008 double(area[1]) / max_area
1011 if (a[0] < min_overlap || a[1] < min_overlap)
1022 template <
typename TImage>
1025 const TImage * tile_0,
1026 const TImage * tile_1,
1029 const base_transform_t * forward_0,
1030 const base_transform_t * forward_1,
1033 const pnt2d_t & origin,
1036 const typename TImage::SizeType & sz,
1037 const typename TImage::SpacingType & sp)
1039 pnt2d_t corner[] = {
1041 origin + vec2d(sz[0] * sp[0], 0),
1042 origin + vec2d(sz[0] * sp[0], sz[1] * sp[1]),
1043 origin + vec2d(0, sz[1] * sp[1])
1047 typename TImage::IndexType tmp_ix;
1051 bool in[] = {
false,
false };
1053 for (
unsigned int i = 0; i < 4 && (!in[0] || !in[1]) ; i++)
1055 tmp_pt = forward_0->TransformPoint(corner[i]);
1056 in[0] = in[0] || tile_0->TransformPhysicalPointToIndex(tmp_pt, tmp_ix);
1058 tmp_pt = forward_1->TransformPoint(corner[i]);
1059 in[1] = in[1] || tile_1->TransformPhysicalPointToIndex(tmp_pt, tmp_ix);
1062 return in[0] && in[1];
1068 template <
typename TImage>
1070 refine_one_point_helper(
1071 const TImage * tile_0,
1072 const mask_t * mask_0,
1073 const TImage * tile_1,
1074 const mask_t * mask_1,
1077 const base_transform_t * forward_0,
1078 const base_transform_t * forward_1,
1081 const pnt2d_t & center,
1084 const double & min_overlap,
1087 const typename TImage::SizeType & sz,
1088 const typename TImage::SpacingType & sp,
1091 TImage * img_0_large,
1092 mask_t * msk_0_large,
1098 pnt2d_t origin = center;
1099 origin[0] -= (double(sz[0]) * sp[0]) / 2;
1100 origin[1] -= (double(sz[1]) * sp[1]) / 2;
1102 if (!tiles_intersect<TImage>(tile_0,
1114 typedef itk::LinearInterpolateImageFunction<TImage, double> interpolator_t;
1115 typename interpolator_t::Pointer interpolator[] = {
1116 interpolator_t::New(),
1117 interpolator_t::New()
1120 interpolator[0]->SetInputImage(tile_0);
1121 interpolator[1]->SetInputImage(tile_1);
1126 typename TImage::IndexType index;
1129 unsigned int area[] = { 0, 0 };
1132 for (
unsigned int y = 0; y < sz[1]; y++)
1134 mosaic_pt[1] = origin[1] + double(y) * sp[1];
1136 for (
unsigned int x = 0; x < sz[0]; x++)
1138 mosaic_pt[0] = origin[0] + double(x) * sp[0];
1142 tile_pt = forward_0->TransformPoint(mosaic_pt);
1143 if (interpolator[0]->IsInsideBuffer(tile_pt) &&
1144 pixel_in_mask<mask_t>(mask_0, tile_pt))
1146 double p = interpolator[0]->Evaluate(tile_pt);
1147 img_0->SetPixel(index, (
unsigned char)(std::min(255.0, p)));
1148 msk_0->SetPixel(index, 1);
1153 img_0->SetPixel(index, 0);
1154 msk_0->SetPixel(index, 0);
1158 tile_pt = forward_1->TransformPoint(mosaic_pt);
1159 if (interpolator[1]->IsInsideBuffer(tile_pt) &&
1160 pixel_in_mask<mask_t>(mask_1, tile_pt))
1162 double p = interpolator[1]->Evaluate(tile_pt);
1163 img_1->SetPixel(index, (
unsigned char)(std::min(255.0, p)));
1164 msk_1->SetPixel(index, 1);
1169 img_1->SetPixel(index, 0);
1170 msk_1->SetPixel(index, 0);
1176 double max_area = double(sz[0] * sz[1]);
1178 double(area[0]) / max_area,
1179 double(area[1]) / max_area
1182 if (a[0] < min_overlap || a[1] < min_overlap)
1187 if (img_0_large != NULL)
1190 pnt2d_t origin_large(center);
1191 origin_large[0] -= sz[0] * sp[0];
1192 origin_large[1] -= sz[1] * sp[1];
1194 for (
unsigned int y = 0; y < sz[1] * 2; y++)
1196 mosaic_pt[1] = origin_large[1] + double(y) * sp[1];
1198 for (
unsigned int x = 0; x < sz[0] * 2; x++)
1200 mosaic_pt[0] = origin_large[0] + double(x) * sp[0];
1204 tile_pt = forward_0->TransformPoint(mosaic_pt);
1205 if (interpolator[0]->IsInsideBuffer(tile_pt) &&
1206 pixel_in_mask<mask_t>(mask_0, tile_pt))
1208 double p = interpolator[0]->Evaluate(tile_pt);
1209 img_0_large->SetPixel(index, (
unsigned char)(std::min(255.0, p)));
1210 msk_0_large->SetPixel(index, 1);
1214 img_0_large->SetPixel(index, 0);
1215 msk_0_large->SetPixel(index, 0);
1228 template <
typename TImage>
1230 refine_one_point_fft(vec2d_t & shift,
1233 const TImage * tile_0,
1234 const mask_t * mask_0,
1237 const TImage * tile_1,
1238 const mask_t * mask_1,
1241 const pnt2d_t & center,
1244 const double & min_overlap,
1253 if (!refine_one_point_helper<TImage>(tile_0,
1268 return refine_one_point_fft<TImage>(shift,
1282 template <
typename TImage>
1284 refine_one_point_fft(vec2d_t & shift,
1287 const TImage * tile_0,
1288 const mask_t * mask_0,
1289 const TImage * tile_1,
1290 const mask_t * mask_1,
1293 const base_transform_t * forward_0,
1294 const base_transform_t * forward_1,
1297 const pnt2d_t & center,
1300 const double & min_overlap,
1303 const typename TImage::SizeType & sz,
1304 const typename TImage::SpacingType & sp,
1307 TImage * img_0_large,
1308 mask_t * msk_0_large,
1316 if (!refine_one_point_helper<TImage>(tile_0,
1337 origin[0] = sz[0] * sp[0] / 2;
1338 origin[1] = sz[1] * sp[1] / 2;
1339 return refine_one_point_fft<TImage>(shift,
1353 template <
typename TImage>
1355 refine_one_point_fft(vec2d_t & shift,
1358 const TImage * tile_0,
1359 const mask_t * mask_0,
1360 const TImage * tile_1,
1361 const mask_t * mask_1,
1364 const base_transform_t * forward_0,
1365 const base_transform_t * forward_1,
1368 const pnt2d_t & center,
1371 const double & min_overlap,
1374 const typename TImage::SizeType & sz,
1375 const typename TImage::SpacingType & sp,
1383 pnt2d_t origin(center);
1384 origin[0] -= sz[0] * sp[0] / 2;
1385 origin[1] -= sz[1] * sp[1] / 2;
1387 if (!refine_one_point_helper<TImage>(tile_0,
1407 return refine_one_point_fft<TImage>(shift,
1418 template <
class TTransform,
class TImage>
1420 refine_one_pair(
typename TTransform::Pointer & t01,
1428 const unsigned int levels,
1429 const unsigned int iterations,
1430 const double & min_step,
1431 const double & max_step)
1434 typedef itk::ImageRegistrationMethod<TImage, TImage>
1438 typename registration_t::Pointer registration = registration_t::New();
1441 typedef itk::LinearInterpolateImageFunction<TImage, double> interpolator_t;
1442 registration->SetInterpolator(interpolator_t::New());
1445 optimizer_t::Pointer optimizer = optimizer_t::New();
1446 registration->SetOptimizer(optimizer);
1447 optimizer_observer_t<optimizer_t>::Pointer observer =
1449 optimizer->AddObserver(itk::IterationEvent(), observer);
1450 optimizer->SetMinimize(
true);
1451 optimizer->SetNumberOfIterations(iterations);
1452 optimizer->SetMinimumStepLength(min_step);
1453 optimizer->SetMaximumStepLength(max_step);
1454 optimizer->SetGradientMagnitudeTolerance(1e-6);
1455 optimizer->SetRelaxationFactor(5e-1);
1456 optimizer->SetPickUpPaceSteps(5);
1457 optimizer->SetBackTracking(
true);
1460 typedef optimizer_t::ScalesType optimizer_scales_t;
1461 optimizer_scales_t parameter_scales(t01->GetNumberOfParameters());
1462 parameter_scales.Fill(1.0);
1464 try { optimizer->SetScales(parameter_scales); }
1465 catch (itk::ExceptionObject &) {}
1468 typedef itk::NormalizedCorrelationImageToImageMetric<TImage, TImage>
1471 typename metric_t::Pointer metric = metric_t::New();
1472 registration->SetMetric(metric);
1474 registration->SetTransform(t01);
1475 registration->SetInitialTransformParameters(t01->GetParameters());
1478 typedef itk::ImageMaskSpatialObject<2> mask_so_t;
1479 mask_t::ConstPointer fi_mask = m0;
1482 mask_so_t::Pointer fi_mask_so = mask_so_t::New();
1483 fi_mask_so->SetImage(fi_mask);
1484 metric->SetFixedImageMask(fi_mask_so);
1487 mask_t::ConstPointer mi_mask = m1;
1490 mask_so_t::Pointer mi_mask_so = mask_so_t::New();
1491 mi_mask_so->SetImage(mi_mask);
1492 metric->SetMovingImageMask(mi_mask_so);
1496 typename TImage::ConstPointer fi = i0;
1497 typename TImage::ConstPointer mi = i1;
1499 registration->SetFixedImageRegion(fi->GetLargestPossibleRegion());
1500 registration->SetFixedImage(fi);
1501 registration->SetMovingImage(mi);
1507 double metric_before =
1508 eval_metric<metric_t, interpolator_t>(t01, fi, mi, fi_mask, mi_mask);
1509 assert(metric_before != std::numeric_limits<double>::max());
1511 typename TTransform::ParametersType params_before = t01->GetParameters();
1512 std::ostringstream oss;
1518 registration->StartRegistration();
1520 catch (itk::ExceptionObject & exception)
1522 oss <<
"image registration threw an exception: "
1523 << std::endl << exception.what() << std::endl;
1525 t01->SetParameters(optimizer->GetBestParams());
1528 double metric_after =
1529 eval_metric<metric_t, interpolator_t>(t01, fi, mi, fi_mask, mi_mask);
1531 typename TTransform::ParametersType params_after = t01->GetParameters();
1533 oss <<
"BEFORE: " << metric_before << std::endl
1534 <<
"AFTER: " << metric_after << std::endl;
1536 if (metric_before <= metric_after || metric_after != metric_after)
1538 oss <<
"NOTE: minimization failed, ignoring registration results..." << std::endl;
1539 t01->SetParameters(params_before);
1540 CORE_LOG_MESSAGE(oss.str());
1541 return metric_before;
1544 CORE_LOG_MESSAGE(oss.str());
1545 return metric_after;
1552 template <
typename TImage>
1554 refine_one_point_nofft(vec2d_t & shift,
1555 const pnt2d_t & origin,
1558 const TImage * tile_0,
1559 const mask_t * mask_0,
1562 const TImage * img_1,
1563 const mask_t * msk_1)
1566 translate_transform_t::Pointer translate = translate_transform_t::New();
1567 vec2d_t offset = vec2d(origin[0], origin[1]);
1568 translate->SetOffset(-offset);
1571 refine_one_pair<translate_transform_t, TImage>
1582 std::ostringstream oss;
1584 shift = -(translate->GetOffset() + offset);
1585 oss <<
"shift: " << shift << std::endl;
1586 CORE_LOG_MESSAGE(oss.str());
1588 #ifdef DEBUG_REFINE_ONE_POINT
1589 static const bfs::path fn_save(
"/tmp/refine_one_point_nofft-");
1590 bfs::path suffix = the_text_t::number(COUNTER, 3,
'0');
1592 translate_transform_t::Pointer t = translate_transform_t::New();
1593 t->SetOffset(-offset);
1594 save_composite(fn_save + suffix +
"-a.png",
1600 #endif // DEBUG_REFINE_ONE_POINT
1602 #if defined(DEBUG_REFINE_ONE_POINT) || defined(DEBUG_ESTIMATE_DISPLACEMENT)
1606 if (metric == std::numeric_limits<double>::max())
1611 #ifdef DEBUG_REFINE_ONE_POINT
1612 save_composite(fn_save + suffix +
"-b.png",
1615 translate.GetPointer(),
1617 #endif // DEBUG_REFINE_ONE_POINT
1626 template <
typename TImage>
1628 refine_one_point_nofft(vec2d_t & shift,
1629 const pnt2d_t & center,
1630 const pnt2d_t & origin,
1631 const double & min_overlap,
1634 const TImage * tile_0,
1635 const mask_t * mask_0,
1636 const TImage * tile_1,
1637 const mask_t * mask_1,
1641 const base_transform_t * t_01,
1650 const typename TImage::SizeType & sz,
1651 const typename TImage::SpacingType & sp)
1653 if (!refine_one_point_helper<TImage>(center,
1672 translate_transform_t::Pointer translate = translate_transform_t::New();
1673 translate->SetIdentity();
1676 refine_one_pair<translate_transform_t, TImage>
1687 #ifdef DEBUG_REFINE_ONE_POINT
1688 static const bfs::path fn_save(
"/tmp/refine_one_point_nofft-");
1689 bfs::path suffix = the_text_t::number(COUNTER, 3,
'0');
1690 save_composite(fn_save + suffix +
"-a.png",
1693 identity_transform_t::New(),
1695 #endif // DEBUG_REFINE_ONE_POINT
1697 #if defined(DEBUG_REFINE_ONE_POINT) || defined(DEBUG_ESTIMATE_DISPLACEMENT)
1701 if (metric == std::numeric_limits<double>::max())
1706 #ifdef DEBUG_REFINE_ONE_POINT
1707 save_composite(fn_save + suffix +
"-b.png",
1710 translate.GetPointer(),
1712 #endif // DEBUG_REFINE_ONE_POINT
1714 shift = -translate->GetOffset();
1721 template <
typename TImage>
1723 refine_one_point_nofft(vec2d_t & shift,
1724 const pnt2d_t & center,
1725 const double & min_overlap,
1726 const TImage * tile_0,
1727 const mask_t * mask_0,
1728 const TImage * tile_1,
1729 const mask_t * mask_1,
1733 const base_transform_t * t_01,
1736 const unsigned int & neighborhood)
1738 typename TImage::SpacingType sp = tile_1->GetSpacing();
1739 typename TImage::SizeType sz;
1740 sz[0] = neighborhood;
1741 sz[1] = neighborhood;
1743 pnt2d_t origin(center);
1744 origin[0] -= 0.5 * double(sz[0]) * sp[0];
1745 origin[1] -= 0.5 * double(sz[1]) * sp[1];
1747 typename TImage::Pointer img[] = {
1748 make_image<TImage>(sz),
1749 make_image<TImage>(sz)
1752 mask_t::Pointer msk[] = {
1753 make_image<mask_t>(sz),
1754 make_image<mask_t>(sz)
1757 img[0]->SetSpacing(sp);
1758 img[1]->SetSpacing(sp);
1759 msk[0]->SetSpacing(sp);
1760 msk[1]->SetSpacing(sp);
1762 return refine_one_point_nofft<TImage>(shift,
1780 #endif // GRID_COMMON_HXX_
Definition: optimizer_observer.hxx:44
Definition: itkRegularStepGradientDescentOptimizer2.h:52
Definition: fft_common.hxx:77