41 #include <Core/ITKCommon/the_text.hxx>
42 #include <Core/ITKCommon/the_utils.hxx>
43 #include <Core/ITKCommon/ThreadUtils/itk_terminator.hxx>
44 #include <Core/ITKCommon/ThreadUtils/the_boost_thread.hxx>
45 #include <Core/ITKCommon/ThreadUtils/the_transaction.hxx>
46 #include <Core/ITKCommon/ThreadUtils/the_thread_pool.hxx>
47 #include <Core/ITKCommon/Filtering/itkNormalizeImageFilterWithMask.h>
48 #include <Core/ITKCommon/Transform/itkLegendrePolynomialTransform.h>
51 #include <boost/filesystem.hpp>
64 #include <itkSimpleFilterWatcher.h>
65 #include <itkImageFileReader.h>
66 #include <itkImageFileWriter.h>
67 #include <itkCastImageFilter.h>
68 #include <itkExtractImageFilter.h>
69 #include <itkResampleImageFilter.h>
70 #include <itkRescaleIntensityImageFilter.h>
71 #include <itkThresholdImageFilter.h>
72 #include <itkConstantPadImageFilter.h>
73 #include <itkDiscreteGaussianImageFilter.h>
74 #include <itkImageRegionConstIteratorWithIndex.h>
75 #include <itkShrinkImageFilter.h>
76 #include <itkMedianImageFilter.h>
77 #include <itkPasteImageFilter.h>
80 #include <itkNormalizedCorrelationImageToImageMetric.h>
81 #include <itkMeanSquaresImageToImageMetric.h>
84 #include <itkNearestNeighborInterpolateImageFunction.h>
85 #include <itkLinearInterpolateImageFunction.h>
86 #include <itkBSplineInterpolateImageFunction.h>
89 #include <itkCommand.h>
90 #include <itkImageMaskSpatialObject.h>
93 #include <itkTransformBase.h>
94 #include <itkTranslationTransform.h>
95 #include <itkScaleTransform.h>
98 #include <itkNumericTraits.h>
99 #include <itkAddImageFilter.h>
100 #include <itkSubtractImageFilter.h>
101 #include <itkDivideImageFilter.h>
102 #include <itkMultiplyImageFilter.h>
103 #include <itkRGBPixel.h>
104 #include <itkComposeRGBImageFilter.h>
106 #include <Core/Utils/Exception.h>
107 #include <Core/Utils/Log.h>
109 namespace bfs=boost::filesystem;
114 typedef itk::Size<2>::SizeValueType image_size_value_t;
119 #define array2d( T ) std::vector<std::vector<T> >
126 typedef itk::Image<unsigned char, 2> mask_t;
134 typedef itk::ImageMaskSpatialObject<2> mask_so_t;
142 inline mask_so_t::Pointer
143 mask_so(
const mask_t * mask)
145 mask_so_t::Pointer so = mask_so_t::New();
158 extern int BREAK(
unsigned int i);
167 typedef unsigned char native_pixel_t;
174 typedef itk::Image<native_pixel_t, 2> native_image_t;
182 typedef float pixel_t;
191 template <
typename T>
193 std_tile(
const bfs::path& fn_image,
194 const unsigned int & shrink_factor,
195 const double & pixel_spacing,
203 typedef itk::Image<pixel_t, 2> image_t;
210 typedef itk::Transform<double, 2, 2> base_transform_t;
217 typedef itk::IdentityTransform<double, 2> identity_transform_t;
224 typedef itk::TranslationTransform<double, 2> translate_transform_t;
231 typedef itk::Point<double, 2> pnt2d_t;
238 typedef itk::Vector<double, 2> vec2d_t;
246 typedef itk::Vector<double, 3> xyz_t;
254 xyz(
const double & r,
const double & g,
const double & b)
270 hsv_to_rgb(
const xyz_t & HSV)
294 double p = V * (1.0 - S);
295 double q = V * (1.0 - S * f);
296 double t = V * (1.0 - S * (1 - f));
346 rgb_to_hsv(
const xyz_t & RGB)
357 double min = std::min(R, std::min(G, B));
358 double max = std::max(R, std::max(G, B));
361 double delta = max - min;
384 H = (B - R) / delta + 2;
389 H = (R - G) / delta + 4;
408 inline static const pnt2d_t
409 pnt2d(
const double & x,
const double & y)
422 inline static const vec2d_t
423 vec2d(
const double & x,
const double & y)
436 inline static const pnt2d_t
437 add(
const pnt2d_t & pt,
const vec2d_t & vc)
440 out[0] = pt[0] + vc[0];
441 out[1] = pt[1] + vc[1];
450 inline static const vec2d_t
451 add(
const vec2d_t & a,
const vec2d_t & b)
454 out[0] = a[0] + b[0];
455 out[1] = a[1] + b[1];
464 inline static const vec2d_t
465 sub(
const pnt2d_t & a,
const pnt2d_t & b)
468 out[0] = a[0] - b[0];
469 out[1] = a[1] - b[1];
478 inline static const vec2d_t
479 mul(
const double & s,
const vec2d_t & vc)
492 inline static const vec2d_t
493 neg(
const vec2d_t & v)
495 return vec2d(-v[0], -v[1]);
504 is_empty_bbox(
const pnt2d_t & min,
505 const pnt2d_t & max);
513 is_singular_bbox(
const pnt2d_t & min,
514 const pnt2d_t & max);
523 calc_tile_mosaic_bbox(
const base_transform_t * mosaic_to_tile,
526 const pnt2d_t & tile_min,
527 const pnt2d_t & tile_max,
530 pnt2d_t & mosaic_min,
531 pnt2d_t & mosaic_max,
534 const unsigned int np = 15);
543 template <
typename T>
545 calc_tile_mosaic_bbox(
const base_transform_t * mosaic_to_tile,
549 pnt2d_t & mosaic_min,
550 pnt2d_t & mosaic_max,
553 const unsigned int np = 15)
555 typename T::SizeType sz = tile->GetLargestPossibleRegion().GetSize();
556 typename T::SpacingType sp = tile->GetSpacing();
558 pnt2d_t tile_min = tile->GetOrigin();
560 tile_max[0] = tile_min[0] + sp[0] *
static_cast<double>(sz[0]);
561 tile_max[1] = tile_min[1] + sp[1] *
static_cast<double>(sz[1]);
563 return calc_tile_mosaic_bbox(mosaic_to_tile,
578 template <
typename T>
580 calc_image_bbox(
const T * image, pnt2d_t & bbox_min, pnt2d_t & bbox_max)
582 typename T::SizeType sz = image->GetLargestPossibleRegion().GetSize();
583 typename T::SpacingType sp = image->GetSpacing();
584 bbox_min = image->GetOrigin();
585 bbox_max[0] = bbox_min[0] + sp[0] *
static_cast<double>(sz[0]);
586 bbox_max[1] = bbox_min[1] + sp[1] *
static_cast<double>(sz[1]);
596 clamp_bbox(
const pnt2d_t & confines_min,
597 const pnt2d_t & confines_max,
607 update_bbox(pnt2d_t & min, pnt2d_t & max,
const pnt2d_t & pt)
609 if (min[0] > pt[0]) min[0] = pt[0];
610 if (min[1] > pt[1]) min[1] = pt[1];
611 if (max[0] < pt[0]) max[0] = pt[0];
612 if (max[1] < pt[1]) max[1] = pt[1];
623 itk_threads_(itk::MultiThreader::GetGlobalDefaultNumberOfThreads()),
624 max_threads_(itk::MultiThreader::GetGlobalMaximumNumberOfThreads())
627 itk::MultiThreader::SetGlobalDefaultNumberOfThreads(1);
628 itk::MultiThreader::SetGlobalMaximumNumberOfThreads(1);
634 itk::MultiThreader::SetGlobalMaximumNumberOfThreads(max_threads_);
635 itk::MultiThreader::SetGlobalDefaultNumberOfThreads(itk_threads_);
649 template <
class T0,
class T1>
653 typedef typename itk::CastImageFilter<T0, T1> cast_t;
654 typename cast_t::Pointer filter = cast_t::New();
658 WRAP(terminator_t<cast_t> terminator(filter));
660 return filter->GetOutput();
669 template <
class image_t>
670 typename image_t::Pointer
671 make_image(
const typename image_t::RegionType::SizeType & sz,
672 const typename image_t::PixelType & fill_value =
673 itk::NumericTraits<typename image_t::PixelType>::Zero)
675 typename image_t::Pointer image = image_t::New();
676 image->SetRegions(sz);
678 image->FillBuffer(fill_value);
688 template <
class image_t>
689 typename image_t::Pointer
690 make_image(
const unsigned int width,
691 const unsigned int height,
692 const double spacing,
693 typename image_t::PixelType fill_value =
694 itk::NumericTraits<typename image_t::PixelType>::Zero)
696 typename image_t::SizeType sz;
700 typename image_t::Pointer image = make_image<image_t>(sz, fill_value);
701 typename image_t::SpacingType sp;
704 image->SetSpacing(sp);
715 template <
class image_t>
716 typename image_t::Pointer
717 make_image(
const unsigned int width,
718 const unsigned int height,
719 const double spacing,
720 typename image_t::PointType origin,
721 typename image_t::PixelType fill_value =
722 itk::NumericTraits<typename image_t::PixelType>::Zero)
724 typename image_t::Pointer image =
725 make_image<image_t>(width, height, spacing, fill_value);
726 image->SetOrigin(origin);
736 template <
class image_t>
737 typename image_t::Pointer
738 make_image(
const typename image_t::SpacingType & sp,
739 const typename image_t::RegionType::SizeType & sz,
740 const typename image_t::PixelType & fill_value =
741 itk::NumericTraits<typename image_t::PixelType>::Zero)
743 typename image_t::Pointer image = image_t::New();
744 image->SetRegions(sz);
745 image->SetSpacing(sp);
747 image->FillBuffer(fill_value);
757 template <
class image_t>
758 typename image_t::Pointer
759 make_image(
const typename image_t::PointType & origin,
760 const typename image_t::SpacingType & sp,
761 const typename image_t::RegionType::SizeType & sz,
762 const typename image_t::PixelType & fill_value =
763 itk::NumericTraits<typename image_t::PixelType>::Zero)
765 typename image_t::Pointer image = image_t::New();
766 image->SetOrigin(origin);
767 image->SetRegions(sz);
768 image->SetSpacing(sp);
770 image->FillBuffer(fill_value);
779 template <
class image_t>
780 typename image_t::Pointer
781 add(
const image_t * a,
const image_t * b)
783 typedef typename itk::AddImageFilter<image_t, image_t, image_t> sum_t;
785 typename sum_t::Pointer sum = sum_t::New();
789 WRAP(terminator_t<sum_t> terminator(sum));
791 return sum->GetOutput();
799 template <
class image_t>
800 typename image_t::Pointer
801 subtract(
const image_t * a,
const image_t * b)
803 typedef typename itk::SubtractImageFilter<image_t, image_t, image_t> dif_t;
805 typename dif_t::Pointer dif = dif_t::New();
809 WRAP(terminator_t<dif_t> terminator(dif));
811 return dif->GetOutput();
820 template <
class image_t>
821 typename image_t::Pointer
822 multiply(
const image_t * a,
const image_t * b)
824 typedef typename itk::MultiplyImageFilter<image_t, image_t, image_t> mul_t;
826 typename mul_t::Pointer mul = mul_t::New();
830 WRAP(terminator_t<mul_t> terminator(mul));
832 return mul->GetOutput();
841 template <
class image_t,
class mask_t>
842 typename image_t::Pointer
843 divide(
const image_t * a,
const mask_t * b)
845 typedef typename itk::DivideImageFilter<image_t, mask_t, image_t> div_t;
847 typename div_t::Pointer div = div_t::New();
851 WRAP(terminator_t<div_t> terminator(div));
853 return div->GetOutput();
864 template <
class image_t>
866 pixel_in_mask(
const mask_t * mask,
867 const mask_t::SizeType & mask_size,
868 const typename image_t::IndexType & index,
869 const unsigned int spacing_scale)
871 mask_t::IndexType mask_index(index);
872 mask_index[0] *= spacing_scale;
873 mask_index[1] *= spacing_scale;
875 if (mask_index[0] >= 0 &&
876 mask_index[1] >= 0 &&
877 image_size_value_t(mask_index[0]) < mask_size[0] &&
878 image_size_value_t(mask_index[1]) < mask_size[1])
881 return (mask == NULL) ?
true : (mask->GetPixel(mask_index) != 0);
893 template <
typename T>
895 pixel_in_mask(
const T * mask,
896 const typename T::PointType & physical_point)
898 if (mask == NULL)
return true;
900 typename T::IndexType mask_pixel_index;
901 if (mask->TransformPhysicalPointToIndex(physical_point, mask_pixel_index))
904 return mask->GetPixel(mask_pixel_index) != 0;
916 template <
typename T>
918 pixel_in_mask(
const T * image,
919 const itk::Image<unsigned char, T::ImageDimension> * mask,
920 const typename T::IndexType & image_pixel_index)
927 typename T::PointType physical_point;
928 image->TransformIndexToPhysicalPoint(image_pixel_index, physical_point);
930 typedef itk::Image<unsigned char, T::ImageDimension> mask_t;
931 return pixel_in_mask<mask_t>(mask, physical_point);
939 template <
typename T>
941 image_min_max(
const T * a,
942 typename T::PixelType & min,
943 typename T::PixelType & max,
944 const itk::Image<unsigned char, T::ImageDimension> * mask = NULL)
946 WRAP(itk_terminator_t terminator(
"image_min_max"));
948 typedef typename T::PixelType pixel_t;
949 typedef typename itk::ImageRegionConstIteratorWithIndex<T> iter_t;
951 min = std::numeric_limits<pixel_t>::max();
955 double counter = 0.0;
956 iter_t iter(a, a->GetLargestPossibleRegion());
957 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
960 WRAP(terminator.terminate_on_request());
962 if (!pixel_in_mask<T>(a, mask, iter.GetIndex()))
967 pixel_t v = iter.Get();
968 min = std::min(min, v);
969 max = std::max(max, v);
971 mean +=
static_cast<double>(v);
984 template <
class image_t>
986 remap_min_max_inplace(image_t * a,
992 WRAP(itk_terminator_t terminator(
"remap_min_max_inplace"));
994 typedef typename image_t::PixelType pixel_t;
995 typedef typename itk::ImageRegionIterator<image_t> iter_t;
998 double rng = max - min;
999 if (rng == 0.0)
return false;
1001 double new_rng = new_max - new_min;
1003 iter_t iter(a, a->GetLargestPossibleRegion());
1004 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
1007 WRAP(terminator.terminate_on_request());
1009 double t = (iter.Get() - min) / rng;
1010 iter.Set(pixel_t(new_min + t * new_rng));
1021 template <
class image_t>
1023 remap_min_max_inplace(image_t * a,
1024 typename image_t::PixelType new_min = 0,
1025 typename image_t::PixelType new_max = 255)
1027 WRAP(itk_terminator_t terminator(
"remap_min_max_inplace"));
1029 typedef typename image_t::PixelType pixel_t;
1030 typedef typename itk::ImageRegionIterator<image_t> iter_t;
1032 double min = std::numeric_limits<pixel_t>::max();
1035 iter_t iter(a, a->GetLargestPossibleRegion());
1036 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
1039 WRAP(terminator.terminate_on_request());
1041 double v = iter.Get();
1042 min = std::min(min, v);
1043 max = std::max(max, v);
1046 return remap_min_max_inplace<image_t>(a, min, max, new_min, new_max);
1054 template <
typename T>
1056 remap_min_max(
const T * a,
1057 typename T::PixelType new_min = 0,
1058 typename T::PixelType new_max = 255)
1060 WRAP(itk_terminator_t terminator(
"remap_min_max"));
1062 typedef typename T::RegionType rn_t;
1063 typedef typename T::SizeType sz_t;
1064 rn_t rn = a->GetLargestPossibleRegion();
1065 sz_t sz = rn.GetSize();
1067 typename T::Pointer b = T::New();
1069 b->SetSpacing(a->GetSpacing());
1072 double min = std::numeric_limits<pixel_t>::max();
1075 typename T::IndexType ix_end;
1079 typename T::IndexType ix;
1080 for (ix[1] = 0; ix[1] < ix_end[1]; ++ix[1])
1083 WRAP(terminator.terminate_on_request());
1085 for (ix[0] = 0; ix[0] < ix_end[0]; ++ix[0])
1087 double v = a->GetPixel(ix);
1088 min = std::min(min, v);
1089 max = std::max(max, v);
1094 double rng = max - min;
1097 b->FillBuffer(itk::NumericTraits<typename T::PixelType>::Zero);
1101 double new_rng = new_max - new_min;
1103 for (ix[1] = 0; ix[1] < ix_end[1]; ++ix[1])
1106 WRAP(terminator.terminate_on_request());
1108 for (ix[0] = 0; ix[0] < ix_end[0]; ++ix[0])
1110 double v = a->GetPixel(ix);
1111 double t = (v - min) / rng;
1112 b->SetPixel(ix,
typename T::PixelType(new_min + t * new_rng));
1126 invert(
typename T::Pointer & a)
1128 WRAP(itk_terminator_t terminator(
"invert"));
1130 typedef typename T::PixelType pixel_t;
1131 typedef typename itk::ImageRegionIterator<T> iter_t;
1133 pixel_t min = std::numeric_limits<pixel_t>::max();
1136 iter_t iter(a, a->GetLargestPossibleRegion());
1137 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
1140 WRAP(terminator.terminate_on_request());
1142 pixel_t v = iter.Get();
1143 min = std::min(min, v);
1144 max = std::max(max, v);
1147 pixel_t rng = max - min;
1148 if (rng == pixel_t(0))
return;
1151 pixel_t new_min = max;
1152 pixel_t new_max = min;
1153 pixel_t new_rng = new_max - new_min;
1155 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
1158 WRAP(terminator.terminate_on_request());
1160 pixel_t t = (iter.Get() - min) / rng;
1161 iter.Set(new_min + t * new_rng);
1171 template <
typename T>
1173 threshold(
const T * a,
1174 typename T::PixelType min,
1175 typename T::PixelType max,
1176 typename T::PixelType new_min,
1177 typename T::PixelType new_max)
1179 WRAP(itk_terminator_t terminator(
"threshold"));
1181 typename T::RegionType::SizeType sz = a->GetLargestPossibleRegion().GetSize();
1182 typename T::Pointer b = T::New();
1184 b->SetSpacing(a->GetSpacing());
1187 typedef typename itk::ImageRegionConstIteratorWithIndex<T> itex_t;
1189 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
1192 WRAP(terminator.terminate_on_request());
1194 typename T::PixelType v = itex.Get();
1195 if (v < min) v = new_min;
1196 else if (v > max) v = new_max;
1198 b->SetPixel(itex.GetIndex(), v);
1209 template <
typename T>
1211 clip_min_max(
const T * a,
1212 typename T::PixelType min = 0,
1213 typename T::PixelType max = 255)
1214 {
return threshold<T>(a, min, max, min, max); }
1221 template <
typename T>
1222 typename T::SizeType
1223 calc_padding(
const T * a,
const T * b)
1225 typedef typename T::SizeType sz_t;
1226 sz_t sa = a->GetLargestPossibleRegion().GetSize();
1227 const sz_t sb = b->GetLargestPossibleRegion().GetSize();
1229 const unsigned int d = T::GetImageDimension();
1230 for (
unsigned int i = 0; i < d; i++)
1232 sa[i] = std::max(sa[i], sb[i]);
1244 template <
typename T>
1247 const typename T::SizeType & size)
1249 typedef typename T::RegionType rn_t;
1250 typedef typename T::SizeType sz_t;
1251 rn_t r = a->GetLargestPossibleRegion();
1252 sz_t z = r.GetSize();
1254 WRAP(itk_terminator_t terminator(
"pad"));
1256 typename T::Pointer b = T::New();
1257 b->SetRegions(size);
1258 b->SetSpacing(a->GetSpacing());
1261 typename T::PixelType zero = itk::NumericTraits<typename T::PixelType>::Zero;
1262 typename T::IndexType ix;
1263 for (ix[1] = 0; (image_size_value_t)(ix[1]) < z[1]; ++ix[1])
1265 for (ix[0] = 0; (image_size_value_t)(ix[0]) < z[0]; ++ix[0])
1267 b->SetPixel(ix, a->GetPixel(ix));
1270 for (ix[0] = z[0]; (image_size_value_t)(ix[0]) < size[0]; ++ix[0])
1272 b->SetPixel(ix, zero);
1276 for (ix[1] = z[1]; (image_size_value_t)(ix[1]) < size[1]; ++ix[1])
1278 for (ix[0] = 0; (image_size_value_t)(ix[0]) < size[0]; ++ix[0])
1280 b->SetPixel(ix, zero);
1292 template <
typename T>
1294 crop(
const T * image,
1295 const typename T::IndexType & min,
1296 const typename T::IndexType & max)
1298 WRAP(itk_terminator_t terminator(
"crop"));
1299 typedef typename T::RegionType::SizeType sz_t;
1301 sz_t img_sz = image->GetLargestPossibleRegion().GetSize();
1303 const unsigned int d = T::GetImageDimension();
1304 for (
unsigned int i = 0; i < d; i++)
1306 reg_sz[i] = std::min(static_cast<unsigned int>(max[i] - min[i] + 1),
1307 static_cast<unsigned int>(img_sz[i] - min[i]));
1310 typename T::RegionType region;
1311 region.SetIndex(min);
1312 region.SetSize(reg_sz);
1314 typename T::Pointer out = make_image<T>(reg_sz);
1316 typedef itk::ImageRegionIteratorWithIndex<T> itex_t;
1317 itex_t itex(out, out->GetLargestPossibleRegion());
1318 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
1321 WRAP(terminator.terminate_on_request());
1323 typename T::IndexType ix1 = itex.GetIndex();
1324 typename T::IndexType ix0;
1325 for (
unsigned int i = 0; i < d; i++)
1327 ix0[i] = ix1[i] + min[i];
1330 out->SetPixel(ix1, image->GetPixel(ix0));
1335 typename T::PointType origin;
1336 image->TransformIndexToPhysicalPoint(region.GetIndex(), origin);
1337 out->SetOrigin(origin);
1339 out->SetSpacing(image->GetSpacing());
1349 template <
typename T>
1351 smooth(
const T * in,
1353 const double maximum_error = 0.1)
1355 typedef typename itk::DiscreteGaussianImageFilter<T, T> smoother_t;
1356 typename smoother_t::Pointer smoother = smoother_t::New();
1360 smoother->SetInput(in);
1361 smoother->SetUseImageSpacing(
false);
1362 smoother->SetVariance(sigma * sigma);
1363 smoother->SetMaximumError(maximum_error);
1365 WRAP(terminator_t<smoother_t> terminator(smoother));
1367 return smoother->GetOutput();
1375 template <
typename T>
1377 shrink(
const T * in,
1378 const unsigned int & shrink_factor,
1379 const double maximum_error = 0.1,
1380 const bool & antialias =
true)
1383 typedef itk::Image<float, T::ImageDimension> flt_img_t;
1384 typename flt_img_t::Pointer image = cast<T, flt_img_t>(in);
1388 double variance =
static_cast<double>(shrink_factor) / 2.0;
1389 double sigma = sqrt(variance);
1390 image = ::smooth<flt_img_t>(image, sigma, maximum_error);
1393 typedef itk::ShrinkImageFilter<flt_img_t, flt_img_t> shrinker_t;
1394 typename shrinker_t::Pointer shrinker = shrinker_t::New();
1398 shrinker->SetInput(image);
1399 shrinker->SetShrinkFactors(shrink_factor);
1401 WRAP(terminator_t<shrinker_t> terminator(shrinker));
1403 image = shrinker->GetOutput();
1404 return cast<flt_img_t, T>(image);
1412 template <
typename T>
1414 load(
const bfs::path& filename,
bool blab =
false)
1416 typedef typename itk::ImageFileReader<T> reader_t;
1417 typename reader_t::Pointer reader = reader_t::New();
1421 reader->SetFileName(filename.string().c_str());
1427 return reader->GetOutput();
1435 template <
typename T>
1437 save(
const T * image,
const bfs::path & filename,
bool blab =
false)
1439 typedef typename itk::ImageFileWriter<T> writer_t;
1440 typename writer_t::Pointer writer = writer_t::New();
1441 writer->SetInput(image);
1444 writer->SetFileName(filename.string().c_str());
1453 template <
typename T>
1455 save_image_tile(T * image,
1456 const bfs::path & filename,
1457 const unsigned int x,
1458 const unsigned int y,
1459 const unsigned int source_width,
1460 const unsigned int source_height,
1461 const unsigned int tile_width,
1462 const unsigned int tile_height,
1465 typename itk::PasteImageFilter<T>::Pointer pasteImageFilter =
1466 itk::PasteImageFilter<T>::New();
1468 pasteImageFilter->SetSourceImage( image );
1470 typename T::RegionType mosaicRegion = image->GetBufferedRegion();
1471 typename T::SizeType mosaicSize = mosaicRegion.GetSize();
1474 typename T::IndexType sourceIndex;
1478 typename T::SizeType sourceSize;
1479 sourceSize[0] = source_width;
1480 sourceSize[1] = source_height;
1482 typename T::RegionType sourceRegion;
1483 sourceRegion.SetIndex( sourceIndex );
1484 sourceRegion.SetSize( sourceSize );
1485 pasteImageFilter->SetSourceRegion( sourceRegion );
1488 typename T::Pointer destImage = T::New();
1489 pasteImageFilter->SetDestinationImage( destImage );
1491 typename T::IndexType destIndex;
1495 typename T::SizeType destSize;
1496 destSize[0] = tile_width;
1497 destSize[1] = tile_height;
1499 typename T::RegionType sectionRegion;
1500 sectionRegion.SetIndex( destIndex );
1501 sectionRegion.SetSize( destSize );
1502 destImage->SetRegions( sectionRegion );
1503 destImage->Allocate();
1504 destImage->FillBuffer(0);
1506 pasteImageFilter->SetDestinationIndex( destIndex );
1508 typename T::Pointer partialImage = pasteImageFilter->GetOutput();
1510 typedef typename itk::ImageFileWriter<T> writer_t;
1511 typename writer_t::Pointer writer = writer_t::New();
1512 writer->SetInput(partialImage);
1519 writer->SetFileName(filename.string().c_str());
1529 template <
typename T>
1531 save_as_tiles(T * image,
1532 const bfs::path & prefix,
1533 const bfs::path & extension,
1536 const double downsample,
1537 bool save_image =
true,
1544 bfs::path xmlFileName(prefix);
1545 xmlFileName.replace_extension(
"xml");
1546 std::ofstream xmlOut(xmlFileName.string().c_str());
1548 if (! xmlOut.is_open())
1550 std::cout <<
"Error opening xml file for writing: " << xmlFileName << std::endl;
1554 typename T::RegionType mosaicRegion = image->GetBufferedRegion();
1555 typename T::SizeType mosaicSize = mosaicRegion.GetSize();
1556 if (w == std::numeric_limits<unsigned int>::max())
1561 if (h == std::numeric_limits<unsigned int>::max())
1566 unsigned int numTilesWide = (mosaicSize[0] + (w - 1)) / w;
1567 unsigned int numTilesTall = (mosaicSize[1] + (h - 1)) / h;
1575 std::string name_part(prefix.stem().string() +
"_");
1577 xmlOut <<
"<?xml version=\"1.0\"?>" << std::endl;
1578 xmlOut <<
"<Level GridDimX=\"" << numTilesWide
1579 <<
"\" GridDimY=\"" << numTilesTall
1580 <<
"\" " <<
"TileXDim=\"" << w
1581 <<
"\" " <<
"TileYDim=\"" << h
1582 <<
"\" " <<
"Downsample=\"" << downsample
1583 <<
"\" " <<
"FilePrefix=\"" << name_part
1584 <<
"\" " <<
"FilePostfix=\"" << extension
1585 <<
"\"/>" << std::endl;
1587 for (
unsigned int x = 0, xid = 0; x < mosaicSize[0]; x += w, xid++)
1589 for (
unsigned int y = 0, yid = 0; y < mosaicSize[1]; y += h, yid++)
1592 bfs::path fn_partialSave(prefix);
1593 fn_partialSave +=
"_X";
1594 fn_partialSave += the_text_t::number(xid, 3,
'0');
1595 fn_partialSave +=
"_Y";
1596 fn_partialSave += the_text_t::number(yid, 3,
'0');
1597 fn_partialSave += extension;
1599 unsigned int sectionWidth = std::min<unsigned int>(w, mosaicSize[0] - x);
1600 unsigned int sectionHeight = std::min<unsigned int>(h, mosaicSize[1] - y);
1603 save_image_tile<T>(image,
1625 template <
typename T>
1627 save_tile_xml(
const bfs::path & prefix,
1628 const bfs::path & extension,
1631 unsigned int full_width,
1632 unsigned int full_height,
1633 const double downsample,
1634 bool save_image =
true,
1641 bfs::path xmlFileName(prefix);
1642 xmlFileName.replace_extension(
"xml");
1643 std::ofstream xmlOut(xmlFileName.c_str());
1645 if (!xmlOut.is_open())
1647 std::cout <<
"Error opening xml file for writing: " << xmlFileName << std::endl;
1651 if (w == std::numeric_limits<unsigned int>::max())
1656 if (h == std::numeric_limits<unsigned int>::max())
1661 unsigned int numTilesWide = (full_width + (w - 1)) / w;
1662 unsigned int numTilesTall = (full_height + (h - 1)) / h;
1669 std::string name_part(prefix.stem().string() +
"_");
1671 xmlOut <<
"<?xml version=\"1.0\"?>" << std::endl;
1672 xmlOut <<
"<Level GridDimX=\"" << numTilesWide
1673 <<
"\" GridDimY=\"" << numTilesTall
1674 <<
"\" " <<
"TileXDim=\"" << w
1675 <<
"\" " <<
"TileYDim=\"" << h
1676 <<
"\" " <<
"Downsample=\"" << downsample
1677 <<
"\" " <<
"FilePrefix=\"" << name_part
1678 <<
"\" " <<
"FilePostfix=\"" << extension
1679 <<
"\"/>" << std::endl;
1681 for (
unsigned int x = 0, xid = 0; x < full_width; x += w, xid++)
1683 for (
unsigned int y = 0, yid = 0; y < full_height; y += h, yid++)
1686 bfs::path fn_partialSave = prefix;
1687 fn_partialSave +=
"_X";
1688 fn_partialSave += the_text_t::number(xid, 3,
'0');
1689 fn_partialSave +=
"_Y";
1690 fn_partialSave += the_text_t::number(yid, 3,
'0');
1691 fn_partialSave += extension;
1706 calc_area(
const itk::Vector<double, 2> & spacing,
1707 const unsigned long int pixels)
1709 double pixel_area = spacing[0] * spacing[1];
1710 double area = pixel_area *
static_cast<double>(pixels);
1719 template <
typename T>
1721 calc_area(
const T * image,
const mask_t * mask)
1723 WRAP(itk_terminator_t terminator(
"calc_area"));
1724 unsigned long int pixels = 0;
1726 typedef itk::ImageRegionConstIteratorWithIndex<T> itex_t;
1727 itex_t itex(image, image->GetLargestPossibleRegion());
1729 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
1732 WRAP(terminator.terminate_on_request());
1734 if (pixel_in_mask<T>(image, mask, itex.GetIndex()))
1740 return calc_area(image->GetSpacing(), pixels);
1746 template <
typename T>
1748 get_area(
const T * image)
1750 const typename T::RegionType::SizeType & sz =
1751 image->GetLargestPossibleRegion().GetSize();
1752 const unsigned int num_pixels = sz[0] * sz[1];
1753 return calc_area(image->GetSpacing(), num_pixels);
1763 template <
class metric_t,
class interpolator_t>
1765 eval_metric(
const base_transform_t * fi_to_mi,
1766 const typename metric_t::FixedImageType * fi,
1767 const typename metric_t::MovingImageType * mi,
1768 const mask_t * fi_mask = NULL,
1769 const mask_t * mi_mask = NULL)
1771 typename metric_t::Pointer metric = metric_t::New();
1772 metric->SetFixedImage(fi);
1773 metric->SetMovingImage(mi);
1774 metric->SetTransform(const_cast<base_transform_t *>(fi_to_mi));
1775 metric->SetInterpolator(interpolator_t::New());
1782 typedef typename metric_t::FixedImageType fi_image_t;
1783 typename fi_image_t::RegionType fi_roi = fi->GetLargestPossibleRegion();
1788 if (calc_tile_mosaic_bbox(fi_to_mi,
1797 calc_image_bbox(fi, fi_min, fi_max);
1800 clamp_bbox(fi_min, fi_max, mi_min, mi_max);
1803 typename fi_image_t::IndexType roi_index[2];
1804 if (fi->TransformPhysicalPointToIndex(mi_min, roi_index[0]) &&
1805 fi->TransformPhysicalPointToIndex(mi_max, roi_index[1]))
1807 typename fi_image_t::SizeType roi_size;
1808 roi_size[0] = roi_index[1][0] - roi_index[0][0] + 1;
1809 roi_size[1] = roi_index[1][1] - roi_index[0][1] + 1;
1810 fi_roi.SetIndex(roi_index[0]);
1811 fi_roi.SetSize(roi_size);
1815 metric->SetFixedImageRegion(fi_roi);
1817 if (fi_mask != NULL)
1819 metric->SetFixedImageMask(mask_so(fi_mask));
1822 if (mi_mask != NULL)
1824 metric->SetMovingImageMask(mask_so(mi_mask));
1827 metric->Initialize();
1832 measure = metric->GetValue(fi_to_mi->GetParameters());
1834 catch (itk::ExceptionObject & exception)
1836 std::ostringstream oss;
1837 oss <<
"image metric threw an exception:" << exception;
1838 CORE_LOG_WARNING(oss.str());
1839 measure = std::numeric_limits<double>::max();
1851 template <
typename TImage,
typename TInterpolator>
1853 my_metric(
double & area,
1858 const base_transform_t * fi_to_mi,
1859 const mask_t * fi_mask,
1860 const mask_t * mi_mask,
1862 const TInterpolator * mi_interpolator)
1864 WRAP(itk_terminator_t terminator(
"my_metric"));
1865 typedef typename itk::ImageRegionConstIteratorWithIndex<TImage> itex_t;
1866 typedef typename TImage::IndexType index_t;
1867 typedef typename TImage::PointType point_t;
1868 typedef typename TImage::PixelType pixel_t;
1875 typename TImage::RegionType fi_roi = fi->GetLargestPossibleRegion();
1880 if (calc_tile_mosaic_bbox(fi_to_mi,
1889 calc_image_bbox(fi, fi_min, fi_max);
1892 clamp_bbox(fi_min, fi_max, mi_min, mi_max);
1893 if (is_singular_bbox(mi_min, mi_max))
1895 return std::numeric_limits<double>::max();
1899 index_t roi_index[2];
1900 if (fi->TransformPhysicalPointToIndex(mi_min, roi_index[0]) &&
1901 fi->TransformPhysicalPointToIndex(mi_max, roi_index[1]))
1903 typename TImage::SizeType roi_size;
1904 roi_size[0] = roi_index[1][0] - roi_index[0][0] + 1;
1905 roi_size[1] = roi_index[1][1] - roi_index[0][1] + 1;
1906 fi_roi.SetIndex(roi_index[0]);
1907 fi_roi.SetSize(roi_size);
1912 mask_t::SizeType fi_mask_size = fi->GetLargestPossibleRegion().GetSize();
1913 unsigned int fi_spacing_scale = 1;
1916 mask_t::SizeType sz = fi_mask->GetLargestPossibleRegion().GetSize();
1917 fi_spacing_scale = sz[0] / fi_mask_size[0];
1927 unsigned long int pixels = 0;
1930 itex_t itex(fi, fi_roi);
1932 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
1935 WRAP(terminator.terminate_on_request());
1937 fi_ix = itex.GetIndex();
1938 if (fi_mask && !pixel_in_mask<TImage>(fi_mask,
1948 fi->TransformIndexToPhysicalPoint(fi_ix, xy);
1951 const point_t uv = fi_to_mi->TransformPoint(xy);
1954 if (!pixel_in_mask<mask_t>(mi_mask, uv) ||
1955 !mi_interpolator->IsInsideBuffer(uv))
1960 pixel_t m = pixel_t(mi_interpolator->Evaluate(uv));
1961 pixel_t f = itex.Get();
1975 area = calc_area(fi->GetSpacing(), pixels);
1978 return std::numeric_limits<double>::max();
1981 aa = aa - ((sa * sa) / static_cast<double>(pixels));
1982 bb = bb - ((sb * sb) / static_cast<double>(pixels));
1983 ab = ab - ((sa * sb) / static_cast<double>(pixels));
1985 double result = -ab / sqrt(aa * bb);
1997 template <
typename TImage>
1999 my_metric(
double & overlap,
2002 const base_transform_t * fi_to_mi,
2003 const mask_t * fi_mask = NULL,
2004 const mask_t * mi_mask = NULL,
2005 const double min_overlap = 0.05,
2006 const double max_overlap = 1.0)
2010 typedef itk::NearestNeighborInterpolateImageFunction
2011 <TImage,
double> interpolator_t;
2012 typename interpolator_t::Pointer mi_interpolator = interpolator_t::New();
2013 mi_interpolator->SetInputImage(mi);
2015 double overlap_area = 0;
2016 double m = my_metric<TImage, interpolator_t>(overlap_area,
2023 if (overlap_area != 0)
2032 double area_a = get_area<TImage>(fi);
2033 double area_b = get_area<TImage>(mi);
2036 double smaller_area = std::min(area_a, area_b);
2037 overlap = overlap_area / smaller_area;
2039 if (overlap < min_overlap || overlap > max_overlap)
2041 return std::numeric_limits<double>::max();
2056 template <
typename TImage>
2058 my_metric(
const TImage * fi,
2060 const base_transform_t * fi_to_mi,
2061 const mask_t * fi_mask = NULL,
2062 const mask_t * mi_mask = NULL,
2063 const double min_overlap = 0.0,
2064 const double max_overlap = 1.0)
2066 double overlap = 0.0;
2067 return my_metric<TImage>(overlap,
2100 template <
class image_po
inter_t>
2102 calc_image_bboxes(
const std::vector<image_pointer_t> & image,
2105 std::vector<pnt2d_t> & image_min,
2106 std::vector<pnt2d_t> & image_max)
2108 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType T;
2109 typedef typename T::RegionType::SizeType imagesz_t;
2110 typedef typename T::SpacingType spacing_t;
2112 const unsigned int num_images = image.size();
2113 image_min.resize(num_images);
2114 image_max.resize(num_images);
2117 for (
unsigned int i = 0; i < num_images; i++)
2120 image_min[i][0] = std::numeric_limits<double>::max();
2121 image_min[i][1] = image_min[i][0];
2122 image_max[i][0] = -image_min[i][0];
2123 image_max[i][1] = -image_min[i][0];
2126 if (image[i].GetPointer() == NULL)
continue;
2129 calc_image_bbox<T>(image[i], image_min[i], image_max[i]);
2140 template <
class image_po
inter_t>
2142 calc_image_bboxes_load_images(
const std::list<bfs::path> & in,
2145 std::vector<pnt2d_t> & image_min,
2146 std::vector<pnt2d_t> & image_max,
2148 const unsigned int shrink_factor,
2149 const double pixel_spacing)
2151 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType T;
2152 typedef typename T::RegionType::SizeType imagesz_t;
2153 typedef typename T::SpacingType spacing_t;
2155 const unsigned int num_images = in.size();
2156 image_min.resize(num_images);
2157 image_max.resize(num_images);
2161 for (std::list<bfs::path>::const_iterator iter = in.begin();
2162 iter != in.end(); ++iter, i++)
2165 image_min[i][0] = std::numeric_limits<double>::max();
2166 image_min[i][1] = image_min[i][0];
2167 image_max[i][0] = -image_min[i][0];
2168 image_max[i][1] = -image_min[i][0];
2171 typedef typename itk::ImageFileReader<T> reader_t;
2172 typename reader_t::Pointer reader = reader_t::New();
2174 reader->SetFileName((*iter).string().c_str());
2177 WRAP(terminator_t<reader_t> terminator(reader));
2180 reader->UpdateOutputInformation();
2181 typename T::Pointer image = reader->GetOutput();
2184 calc_image_bbox<T>(image, image_min[i], image_max[i]);
2187 image = image_t::Pointer(NULL);
2248 template <
class po
int_t,
class transform_po
inter_t>
2250 calc_mosaic_bboxes(
const std::vector<transform_pointer_t> & xform,
2253 const std::vector<point_t> & image_min,
2254 const std::vector<point_t> & image_max,
2257 std::vector<point_t> & mosaic_min,
2258 std::vector<point_t> & mosaic_max,
2261 const unsigned int np = 15)
2263 const unsigned int num_images = xform.size();
2264 mosaic_min.resize(num_images);
2265 mosaic_max.resize(num_images);
2267 point_t image_point;
2268 point_t mosaic_point;
2272 for (
unsigned int i = 0; i < num_images; i++)
2274 ok = ok & calc_tile_mosaic_bbox(xform[i],
2292 template <
class po
int_t>
2295 const std::vector<point_t> & mosaic_min,
2296 const std::vector<point_t> & mosaic_max,
2303 min[0] = std::numeric_limits<double>::max();
2309 const unsigned int num_images = mosaic_min.size();
2310 for (
unsigned int i = 0; i < num_images; i++)
2313 if (mosaic_min[i][0] == std::numeric_limits<double>::max())
continue;
2316 update_bbox(min, max, mosaic_min[i]);
2317 update_bbox(min, max, mosaic_max[i]);
2327 template <
class image_po
inter_t,
class transform_po
inter_t>
2329 calc_mosaic_bbox(
const std::vector<transform_pointer_t> & transform,
2330 const std::vector<image_pointer_t> & image,
2333 typename image_pointer_t::ObjectType::PointType & min,
2334 typename image_pointer_t::ObjectType::PointType & max,
2337 const unsigned int np = 15)
2339 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType image_t;
2340 typedef typename image_t::PointType point_t;
2343 std::vector<point_t> image_min;
2344 std::vector<point_t> image_max;
2345 calc_image_bboxes<image_pointer_t>(image, image_min, image_max);
2348 std::vector<point_t> mosaic_min;
2349 std::vector<point_t> mosaic_max;
2352 calc_mosaic_bboxes<point_t, transform_pointer_t>(transform,
2360 calc_mosaic_bbox<point_t>(mosaic_min, mosaic_max, min, max);
2369 template <
class image_po
inter_t,
class transform_po
inter_t>
2371 calc_mosaic_bbox_load_images(
const std::vector<transform_pointer_t> & transform,
2372 const std::list<bfs::path> & fn_image,
2375 typename image_pointer_t::ObjectType::PointType & min,
2376 typename image_pointer_t::ObjectType::PointType & max,
2377 std::vector<typename image_pointer_t::ObjectType::PointType> & mosaic_min,
2378 std::vector<typename image_pointer_t::ObjectType::PointType> & mosaic_max,
2379 const unsigned int shrink_factor,
2380 const double pixel_spacing,
2383 const unsigned int np = 15)
2385 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType image_t;
2386 typedef typename image_t::PointType point_t;
2389 std::vector<point_t> image_min;
2390 std::vector<point_t> image_max;
2392 calc_image_bboxes_load_images<image_pointer_t>(fn_image,
2400 calc_mosaic_bboxes<point_t, transform_pointer_t>(transform,
2408 calc_mosaic_bbox<point_t>(mosaic_min, mosaic_max, min, max);
2418 bbox_overlap(
const pnt2d_t & min_box1,
2419 const pnt2d_t & max_box1,
2420 const pnt2d_t & min_box2,
2421 const pnt2d_t & max_box2)
2424 max_box1[0] > min_box2[0] &&
2425 min_box1[0] < max_box2[0] &&
2426 max_box1[1] > min_box2[1] &&
2427 min_box1[1] < max_box2[1];
2436 inside_bbox(
const pnt2d_t & min,
const pnt2d_t & max,
const pnt2d_t & pt)
2450 inline static double
2451 calc_pixel_weight(
const pnt2d_t & bbox_min,
2452 const pnt2d_t & bbox_max,
2455 double w = bbox_max[0] - bbox_min[0];
2456 double h = bbox_max[1] - bbox_min[1];
2457 double r = 0.5 * ((w > h) ? h : w);
2458 double sx = std::min(pt[0] - bbox_min[0], bbox_max[0] - pt[0]);
2459 double sy = std::min(pt[1] - bbox_min[1], bbox_max[1] - pt[1]);
2460 double s = (1.0 + std::min(sx, sy)) / (r + 1.0);
2461 return s * s * s * s;
2485 template <
class image_po
inter_t,
class transform_po
inter_t>
2486 typename image_pointer_t::ObjectType::Pointer
2488 (
bool assemble_mosaic_mask,
2489 mask_t::Pointer & mosaic_mask,
2490 const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
2491 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
2492 const typename image_pointer_t::ObjectType::SizeType & mosaic_sz,
2493 const unsigned int num_images,
2494 const std::vector<bool> & omit,
2495 const std::vector<double> & tint,
2496 const std::vector<transform_pointer_t> & transform,
2497 const std::vector<image_pointer_t> & image,
2500 const std::vector<mask_t::ConstPointer> & image_mask =
2501 std::vector<mask_t::ConstPointer>(0),
2504 const feathering_t feathering = FEATHER_NONE_E,
2505 double background = 255.0,
2507 bool dont_allocate =
false)
2509 WRAP(itk_terminator_t terminator(
"make_mosaic_st"));
2511 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType image_t;
2512 typedef typename image_t::IndexType index_t;
2513 typedef typename image_t::PointType point_t;
2514 typedef typename image_t::PixelType pixel_t;
2515 typedef typename image_t::SpacingType spacing_t;
2516 typedef typename image_t::RegionType::SizeType imagesz_t;
2517 typedef typename itk::ImageRegionIteratorWithIndex<image_t> itex_t;
2520 typedef typename itk::LinearInterpolateImageFunction
2521 <image_t,
double> img_interpolator_t;
2522 std::vector<typename img_interpolator_t::Pointer> img(num_images);
2524 for (
unsigned int i = 0; i < num_images; i++)
2526 img[i] = img_interpolator_t::New();
2527 img[i]->SetInputImage(image[i]);
2531 typedef itk::NearestNeighborInterpolateImageFunction
2532 <mask_t,
double> msk_interpolator_t;
2533 std::vector<msk_interpolator_t::Pointer> msk(num_images);
2534 msk.assign(num_images, msk_interpolator_t::Pointer(NULL));
2536 for (
unsigned int i = 0; i < image_mask.size() && i < num_images; i++)
2538 if (image_mask[i].GetPointer() == NULL)
continue;
2540 msk[i] = msk_interpolator_t::New();
2541 msk[i]->SetInputImage(image_mask[i]);
2545 std::vector<point_t> bbox_min(num_images);
2546 std::vector<point_t> bbox_max(num_images);
2547 calc_image_bboxes<image_pointer_t>(image, bbox_min, bbox_max);
2550 std::vector<point_t> min(num_images);
2551 std::vector<point_t> max(num_images);
2553 calc_mosaic_bboxes<point_t, transform_pointer_t>(transform,
2560 typename image_t::Pointer mosaic = image_t::New();
2561 mosaic->SetOrigin(mosaic_min);
2562 mosaic->SetRegions(mosaic_sz);
2563 mosaic->SetSpacing(mosaic_sp);
2566 if (assemble_mosaic_mask)
2568 mosaic_mask = mask_t::New();
2569 mosaic_mask->SetOrigin(mosaic_min);
2570 mosaic_mask->SetRegions(mosaic_sz);
2571 mosaic_mask->SetSpacing(mosaic_sp);
2581 WRAP(terminator.terminate_on_request());
2585 if (assemble_mosaic_mask)
2587 mosaic_mask->Allocate();
2591 bool integer_pixel = std::numeric_limits<pixel_t>::is_integer;
2592 double pixel_max =
static_cast<double>(std::numeric_limits<pixel_t>::max());
2593 double pixel_min = integer_pixel ?
2594 static_cast<double>(std::numeric_limits<pixel_t>::min()) : -pixel_max;
2596 itex_t itex(mosaic, mosaic->GetLargestPossibleRegion());
2597 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
2600 WRAP(terminator.terminate_on_request());
2603 mosaic->TransformIndexToPhysicalPoint(itex.GetIndex(), point);
2606 double weight = 0.0;
2607 unsigned int num_pixels = 0;
2608 for (
unsigned int k = 0; k < num_images; k++)
2611 if (omit[k] || (image[k].GetPointer() == NULL))
continue;
2614 if (!inside_bbox(min[k], max[k], point))
continue;
2616 const transform_pointer_t & t = transform[k];
2617 point_t pt_k = t->TransformPoint(point);
2620 if (!img[k]->IsInsideBuffer(pt_k))
continue;
2624 if ((msk[k].GetPointer() != NULL) &&
2625 (alpha = msk[k]->Evaluate(pt_k)) < 1.0)
continue;
2629 double wp = tint[k];
2630 double p = img[k]->Evaluate(pt_k) * wp;
2631 double wa = ((alpha == 1.0) ? 1e-0 : 1e-6) * wp;
2633 if (feathering == FEATHER_NONE_E)
2640 double pixel_weight =
2641 calc_pixel_weight(bbox_min[k], bbox_max[k], pt_k);
2643 if (feathering == FEATHER_BLEND_E)
2645 pixel += pixel_weight * p * wa;
2646 weight += pixel_weight * wa;
2650 if (pixel_weight > weight)
2652 pixel = pixel_weight * p * wa;
2653 weight = pixel_weight * wa;
2665 pixel = floor(pixel + 0.5);
2668 pixel = std::max(pixel_min, std::min(pixel_max, pixel));
2671 pixel_t tmp = pixel_t(pixel);
2676 itex.Set(num_pixels > 0 ? 0 : pixel_t(background));
2679 if (mosaic_mask.GetPointer())
2681 mask_t::PixelType mask_pixel = (weight > 0.0) ? 1 : 0;
2682 mosaic_mask->SetPixel(itex.GetIndex(), mask_pixel);
2695 template <
typename image_po
inter_t,
typename transform_po
inter_t>
2699 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType tile_t;
2700 typedef typename image_t::PointType pnt_t;
2701 typedef typename image_t::PixelType pxl_t;
2702 typedef typename image_t::RegionType rn_t;
2703 typedef typename image_t::RegionType::SizeType sz_t;
2704 typedef typename image_t::RegionType::IndexType ix_t;
2705 typedef typename itk::LinearInterpolateImageFunction<tile_t, double> itile_t;
2706 typedef itk::NearestNeighborInterpolateImageFunction<mask_t, double> imask_t;
2710 unsigned int thread_offset,
2711 unsigned int thread_stride,
2714 typename tile_t::Pointer & mosaic,
2715 mask_t * mosaic_mask,
2719 unsigned int num_tiles,
2722 const std::vector<bool> & omit,
2725 const std::vector<double> & tint,
2728 const std::vector<transform_pointer_t> & transform,
2731 const std::vector<image_pointer_t> & tile,
2732 const std::vector<mask_t::ConstPointer> & mask,
2735 const std::vector<typename itile_t::Pointer> & itile,
2736 const std::vector<typename imask_t::Pointer> & imask,
2739 const std::vector<pnt_t> & bbox_min,
2740 const std::vector<pnt_t> & bbox_max,
2743 const std::vector<pnt_t> & min,
2744 const std::vector<pnt_t> & max,
2747 feathering_t feathering,
2752 thread_offset_(thread_offset),
2753 thread_stride_(thread_stride),
2755 mosaic_mask_(mosaic_mask),
2756 num_tiles_(num_tiles),
2759 transform_(transform),
2764 bbox_min_(bbox_min),
2765 bbox_max_(bbox_max),
2768 feathering_(feathering),
2769 background_(background)
2774 WRAP(itk_terminator_t terminator(
"assemble_mosaic_t::execute"));
2777 const bool integer_pixel = std::numeric_limits<pxl_t>::is_integer;
2778 const double pixel_max =
static_cast<double>(std::numeric_limits<pxl_t>::max());
2779 const double pixel_min = integer_pixel ?
2780 static_cast<double>(std::numeric_limits<pxl_t>::min()) : -pixel_max;
2782 rn_t region = mosaic_->GetLargestPossibleRegion();
2783 ix_t origin = region.GetIndex();
2784 sz_t extent = region.GetSize();
2785 ix_t::IndexValueType x_end = origin[0] + extent[0];
2786 ix_t::IndexValueType y_end = origin[1] + extent[1];
2789 for (ix[1] = origin[1]; ix[1] < y_end; ++ix[1])
2791 for (ix[0] = origin[0] + thread_offset_;
2793 ix[0] += thread_stride_)
2796 WRAP(terminator.terminate_on_request());
2799 mosaic_->TransformIndexToPhysicalPoint(ix, point);
2802 double weight = 0.0;
2803 unsigned int num_pixels = 0;
2805 for (
unsigned int k = 0; k < num_tiles_; k++)
2808 if (omit_[k] || (tile_[k].GetPointer() == NULL))
2814 if (!inside_bbox(min_[k], max_[k], point))
2819 const transform_pointer_t & t = transform_[k];
2820 pnt_t pt_k = t->TransformPoint(point);
2823 if (!itile_[k]->IsInsideBuffer(pt_k))
2830 if ((imask_[k].GetPointer() != NULL) &&
2831 (alpha = imask_[k]->Evaluate(pt_k)) < 1.0)
2838 double wp = tint_[k];
2839 double p = itile_[k]->Evaluate(pt_k) * wp;
2840 double wa = ((alpha == 1.0) ? 1e-0 : 1e-6) * wp;
2842 if (feathering_ == FEATHER_NONE_E)
2849 double pixel_weight = calc_pixel_weight(bbox_min_[k],
2853 if (feathering_ == FEATHER_BLEND_E)
2855 pixel += pixel_weight * p * wa;
2856 weight += pixel_weight * wa;
2860 if (pixel_weight > weight)
2862 pixel = pixel_weight * p * wa;
2863 weight = pixel_weight * wa;
2875 pixel = floor(pixel + 0.5);
2878 pixel = std::max(pixel_min, std::min(pixel_max, pixel));
2881 pxl_t output = pxl_t(pixel);
2882 mosaic_->SetPixel(ix, output);
2886 pxl_t output = num_pixels > 0 ? 0 : pxl_t(background_);
2887 mosaic_->SetPixel(ix, output);
2892 mask_t::PixelType mask_pixel = (weight > 0.0) ? 1 : 0;
2893 mosaic_mask_->SetPixel(ix, mask_pixel);
2900 unsigned int thread_offset_;
2901 unsigned int thread_stride_;
2904 typename tile_t::Pointer & mosaic_;
2905 mask_t * mosaic_mask_;
2909 unsigned int num_tiles_;
2912 const std::vector<bool> & omit_;
2915 const std::vector<double> & tint_;
2918 const std::vector<transform_pointer_t> & transform_;
2921 const std::vector<image_pointer_t> & tile_;
2922 const std::vector<mask_t::ConstPointer> & mask_;
2926 const std::vector<typename itile_t::Pointer> & itile_;
2927 const std::vector<typename imask_t::Pointer> & imask_;
2930 const std::vector<pnt_t> & bbox_min_;
2931 const std::vector<pnt_t> & bbox_max_;
2934 const std::vector<pnt_t> & min_;
2935 const std::vector<pnt_t> & max_;
2938 feathering_t feathering_;
2953 template <
class image_po
inter_t,
class transform_po
inter_t>
2954 typename image_pointer_t::ObjectType::Pointer
2956 (
unsigned int num_threads,
2957 bool assemble_mosaic_mask,
2958 mask_t::Pointer & mosaic_mask,
2959 const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
2960 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
2961 const typename image_pointer_t::ObjectType::SizeType & mosaic_sz,
2962 const unsigned int num_images,
2963 const std::vector<bool> & omit,
2964 const std::vector<double> & tint,
2965 const std::vector<transform_pointer_t> & transform,
2966 const std::vector<image_pointer_t> & image,
2969 const std::vector<mask_t::ConstPointer> & image_mask =
2970 std::vector<mask_t::ConstPointer>(0),
2973 const feathering_t feathering = FEATHER_NONE_E,
2974 double background = 255.0,
2976 bool dont_allocate =
false)
2978 if (num_threads == 1)
2982 make_mosaic_st<image_pointer_t, transform_pointer_t>
2983 (assemble_mosaic_mask,
2999 WRAP(itk_terminator_t terminator(
"make_mosaic_mt"));
3001 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType img_t;
3002 typedef typename img_t::PointType pnt_t;
3005 typedef typename itk::LinearInterpolateImageFunction
3006 <img_t,
double> img_interpolator_t;
3007 std::vector<typename img_interpolator_t::Pointer> img(num_images);
3009 for (
unsigned int i = 0; i < num_images; i++)
3011 img[i] = img_interpolator_t::New();
3012 img[i]->SetInputImage(image[i]);
3016 typedef itk::NearestNeighborInterpolateImageFunction
3017 <mask_t,
double> msk_interpolator_t;
3018 std::vector<msk_interpolator_t::Pointer> msk(num_images);
3019 msk.assign(num_images, msk_interpolator_t::Pointer(NULL));
3021 for (
unsigned int i = 0; i < image_mask.size() && i < num_images; i++)
3023 if (image_mask[i].GetPointer() == NULL)
continue;
3025 msk[i] = msk_interpolator_t::New();
3026 msk[i]->SetInputImage(image_mask[i]);
3030 std::vector<pnt_t> bbox_min(num_images);
3031 std::vector<pnt_t> bbox_max(num_images);
3032 calc_image_bboxes<image_pointer_t>(image, bbox_min, bbox_max);
3035 std::vector<pnt_t> min(num_images);
3036 std::vector<pnt_t> max(num_images);
3037 calc_mosaic_bboxes<pnt_t, transform_pointer_t>(transform,
3044 typename img_t::Pointer mosaic = img_t::New();
3045 mosaic->SetOrigin(mosaic_min);
3046 mosaic->SetRegions(mosaic_sz);
3047 mosaic->SetSpacing(mosaic_sp);
3050 if (assemble_mosaic_mask)
3052 mosaic_mask = mask_t::New();
3053 mosaic_mask->SetOrigin(mosaic_min);
3054 mosaic_mask->SetRegions(mosaic_sz);
3055 mosaic_mask->SetSpacing(mosaic_sp);
3067 if (assemble_mosaic_mask)
3069 mosaic_mask->Allocate();
3073 std::list<the_transaction_t *> schedule;
3074 for (
unsigned int i = 0; i < num_threads; i++)
3081 mosaic_mask.GetPointer(),
3097 schedule.push_back(t);
3102 thread_pool.set_idle_sleep_duration(50);
3103 thread_pool.push_back(schedule);
3104 thread_pool.pre_distribute_work();
3108 thread_pool.start();
3126 template <
class image_po
inter_t,
class transform_po
inter_t>
3127 typename image_pointer_t::ObjectType::Pointer
3129 (
const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
3130 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
3131 const typename image_pointer_t::ObjectType::SizeType & mosaic_sz,
3132 const unsigned int num_images,
3133 const std::vector<bool> & omit,
3134 const std::vector<double> & tint,
3135 const std::vector<transform_pointer_t> & transform,
3136 const std::vector<image_pointer_t> & image,
3139 const std::vector<mask_t::ConstPointer> & image_mask =
3140 std::vector<mask_t::ConstPointer>(0),
3143 const feathering_t feathering = FEATHER_NONE_E,
3144 double background = 255.0,
3146 bool dont_allocate =
false)
3149 unsigned int num_threads = boost::thread::hardware_concurrency();
3152 const bool assemble_mosaic_mask =
false;
3153 mask_t::Pointer mosaic_mask;
3156 make_mosaic_mt<image_pointer_t, transform_pointer_t>
3158 assemble_mosaic_mask,
3181 template <
class image_po
inter_t,
class transform_po
inter_t>
3182 typename image_pointer_t::ObjectType::Pointer
3184 (
const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
3185 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
3186 const typename image_pointer_t::ObjectType::SizeType & mosaic_sz,
3187 const unsigned int num_images,
3188 const std::vector<bool> & omit,
3189 const std::vector<transform_pointer_t> & transform,
3190 const std::vector<image_pointer_t> & image,
3193 const std::vector<mask_t::ConstPointer> & image_mask =
3194 std::vector<mask_t::ConstPointer>(0),
3197 const feathering_t feathering = FEATHER_NONE_E,
3198 double background = 255.0,
3200 bool dont_allocate =
false)
3202 const std::vector<double> tint(num_images, 1.0);
3203 return make_mosaic<image_pointer_t, transform_pointer_t>
3224 template <
class image_po
inter_t,
class transform_po
inter_t>
3225 typename image_pointer_t::ObjectType::Pointer
3227 (
const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
3228 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
3229 const typename image_pointer_t::ObjectType::PointType & mosaic_max,
3230 const unsigned int num_images,
3231 const std::vector<bool> & omit,
3232 const std::vector<transform_pointer_t> & transform,
3233 const std::vector<image_pointer_t> & image,
3236 const std::vector<mask_t::ConstPointer> & image_mask =
3237 std::vector<mask_t::ConstPointer>(0),
3240 const feathering_t feathering = FEATHER_NONE_E,
3242 double background = 255.0,
3244 bool dont_allocate =
false)
3246 typename image_pointer_t::ObjectType::SizeType mosaic_sz;
3247 mosaic_sz[0] =
static_cast<unsigned int>((mosaic_max[0] - mosaic_min[0]) /
3249 mosaic_sz[1] =
static_cast<unsigned int>((mosaic_max[1] - mosaic_min[1]) /
3252 return make_mosaic<image_pointer_t, transform_pointer_t>
3272 template <
class image_po
inter_t,
class transform_po
inter_t>
3273 typename image_pointer_t::ObjectType::Pointer
3275 (
const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
3276 const unsigned int num_images,
3277 const std::vector<bool> & omit,
3278 const std::vector<transform_pointer_t> & transform,
3279 const std::vector<image_pointer_t> & image,
3282 const std::vector<mask_t::ConstPointer> & image_mask =
3283 std::vector<mask_t::ConstPointer>(0),
3286 const feathering_t feathering = FEATHER_NONE_E,
3288 double background = 255.0,
3290 bool dont_allocate =
false)
3293 typename image_pointer_t::ObjectType::PointType mosaic_min;
3294 typename image_pointer_t::ObjectType::PointType mosaic_max;
3295 calc_mosaic_bbox<image_pointer_t, transform_pointer_t>
3301 return make_mosaic<image_pointer_t, transform_pointer_t>
3321 template <
class image_po
inter_t,
class transform_po
inter_t>
3322 typename image_pointer_t::ObjectType::Pointer
3323 make_mosaic(
const std::vector<image_pointer_t> & image,
3324 const std::vector<transform_pointer_t> & transform,
3325 const feathering_t feathering = FEATHER_NONE_E,
3326 const unsigned int omit = std::numeric_limits<unsigned int>::max(),
3327 unsigned int num_images = std::numeric_limits<unsigned int>::max(),
3329 const std::vector<mask_t::ConstPointer> & image_mask =
3330 std::vector<mask_t::ConstPointer>(0))
3332 if (num_images == std::numeric_limits<unsigned int>::max())
3334 num_images = image.size();
3337 std::vector<bool> omit_vec(num_images);
3338 omit_vec.assign(num_images,
false);
3339 if (omit != std::numeric_limits<unsigned int>::max())
3341 omit_vec[omit] =
true;
3345 make_mosaic<image_pointer_t, transform_pointer_t>
3346 (image[0]->GetSpacing(),
3362 template <
typename T>
3364 update_mosaic(
const T * mosaic,
3366 const base_transform_t * tile_transform,
3367 const mask_t * mask_mosaic = NULL,
3368 const mask_t * mask_tile = NULL)
3370 std::vector<typename T::ConstPointer> image(2);
3374 std::vector<base_transform_t::ConstPointer> transform(2);
3375 transform[0] = identity_transform_t::New();
3376 transform[1] = tile_transform;
3378 std::vector<mask_t::ConstPointer> image_mask(2);
3379 image_mask[0] = mask_mosaic;
3380 image_mask[1] = mask_tile;
3382 std::vector<bool> omit(2);
3383 omit.assign(2,
false);
3386 make_mosaic<typename T::ConstPointer, base_transform_t::ConstPointer>
3387 (mosaic->GetSpacing(),
3402 template <
class transform_po
inter_t>
3404 make_mask_st(
const mask_t::SpacingType & mosaic_sp,
3405 const unsigned int num_images,
3406 const std::vector<bool> & omit,
3407 const std::vector<transform_pointer_t> & transform,
3408 const std::vector<mask_t::ConstPointer> & image_mask)
3410 WRAP(itk_terminator_t terminator(
"make_mask_st"));
3412 typedef mask_t::IndexType index_t;
3413 typedef mask_t::PointType point_t;
3414 typedef mask_t::PixelType pixel_t;
3415 typedef mask_t::SpacingType spacing_t;
3416 typedef mask_t::RegionType::SizeType imagesz_t;
3417 typedef itk::ImageRegionIteratorWithIndex<mask_t> itex_t;
3420 typedef itk::NearestNeighborInterpolateImageFunction
3421 <mask_t,
double> msk_interpolator_t;
3422 std::vector<msk_interpolator_t::Pointer> msk(num_images);
3423 msk.assign(num_images, msk_interpolator_t::Pointer(NULL));
3425 for (
unsigned int i = 0; i < image_mask.size() && i < num_images; i++)
3427 if (image_mask[i].GetPointer() == NULL)
continue;
3429 msk[i] = msk_interpolator_t::New();
3430 msk[i]->SetInputImage(image_mask[i]);
3434 std::vector<point_t> bbox_min(num_images);
3435 std::vector<point_t> bbox_max(num_images);
3436 calc_image_bboxes<mask_t::ConstPointer>(image_mask, bbox_min, bbox_max);
3439 std::vector<point_t> min(num_images);
3440 std::vector<point_t> max(num_images);
3441 calc_mosaic_bboxes<point_t, transform_pointer_t>(transform,
3450 calc_mosaic_bbox<point_t>(min, max, mosaic_min, mosaic_max);
3453 mask_t::Pointer mosaic = mask_t::New();
3454 imagesz_t mosaic_sz;
3456 mosaic_sz[0] =
static_cast<unsigned int>((mosaic_max[0] - mosaic_min[0]) /
3458 mosaic_sz[1] =
static_cast<unsigned int>((mosaic_max[1] - mosaic_min[1]) /
3460 mosaic->SetOrigin(pnt2d(mosaic_min[0], mosaic_min[1]));
3461 mosaic->SetRegions(mosaic_sz);
3462 mosaic->SetSpacing(mosaic_sp);
3465 WRAP(terminator.terminate_on_request());
3468 mosaic->FillBuffer(itk::NumericTraits<pixel_t>::Zero);
3470 itex_t itex(mosaic, mosaic->GetLargestPossibleRegion());
3471 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
3474 WRAP(terminator.terminate_on_request());
3477 mosaic->TransformIndexToPhysicalPoint(itex.GetIndex(), point);
3479 for (
unsigned int k = 0; k < num_images; k++)
3482 if (omit[k] || (image_mask[k].GetPointer() == NULL))
continue;
3485 if (!inside_bbox(min[k], max[k], point))
continue;
3487 const transform_pointer_t & t = transform[k];
3488 point_t pt_k = t->TransformPoint(point);
3491 if (!msk[k]->IsInsideBuffer(pt_k))
continue;
3494 if (msk[k]->Evaluate(pt_k) == 0)
continue;
3511 template <
typename transform_po
inter_t>
3515 typedef mask_t::PointType pnt_t;
3516 typedef mask_t::PixelType pxl_t;
3517 typedef mask_t::RegionType rn_t;
3518 typedef mask_t::RegionType::SizeType sz_t;
3519 typedef mask_t::RegionType::IndexType ix_t;
3520 typedef itk::NearestNeighborInterpolateImageFunction<mask_t, double> imask_t;
3524 unsigned int thread_offset,
3525 unsigned int thread_stride,
3528 mask_t::Pointer & mosaic,
3532 unsigned int num_tiles,
3535 const std::vector<bool> & omit,
3538 const std::vector<transform_pointer_t> & transform,
3541 const std::vector<mask_t::ConstPointer> & mask,
3544 const std::vector<typename imask_t::Pointer> & imask,
3547 const std::vector<pnt_t> & min,
3548 const std::vector<pnt_t> & max):
3550 thread_offset_(thread_offset),
3551 thread_stride_(thread_stride),
3553 num_tiles_(num_tiles),
3555 transform_(transform),
3564 WRAP(itk_terminator_t terminator(
"assemble_mask_t::execute"));
3566 rn_t region = mosaic_->GetLargestPossibleRegion();
3567 ix_t origin = region.GetIndex();
3568 sz_t extent = region.GetSize();
3569 ix_t::IndexValueType x_end = origin[0] + extent[0];
3570 ix_t::IndexValueType y_end = origin[1] + extent[1];
3573 for (ix[1] = origin[1]; ix[1] < y_end; ++ix[1])
3575 for (ix[0] = origin[0] + thread_offset_;
3577 ix[0] += thread_stride_)
3580 WRAP(terminator.terminate_on_request());
3583 mosaic_->TransformIndexToPhysicalPoint(ix, point);
3585 mask_t::PixelType mask_pixel = 0;
3586 for (
unsigned int k = 0; k < num_tiles_; k++)
3589 if (omit_[k] || (mask_[k].GetPointer() == NULL))
3595 if (!inside_bbox(min_[k], max_[k], point))
3600 const transform_pointer_t & t = transform_[k];
3601 pnt_t pt_k = t->TransformPoint(point);
3604 if (!imask_[k]->IsInsideBuffer(pt_k))
3610 if (imask_[k]->Evaluate(pt_k) == 0)
3619 mosaic_->SetPixel(ix, mask_pixel);
3625 unsigned int thread_offset_;
3626 unsigned int thread_stride_;
3629 mask_t::Pointer & mosaic_;
3633 unsigned int num_tiles_;
3636 const std::vector<bool> & omit_;
3639 const std::vector<transform_pointer_t> & transform_;
3642 const std::vector<mask_t::ConstPointer> & mask_;
3645 const std::vector<typename imask_t::Pointer> & imask_;
3648 const std::vector<pnt_t> & min_;
3649 const std::vector<pnt_t> & max_;
3659 template <
class transform_po
inter_t>
3661 make_mask_mt(
unsigned int num_threads,
3662 const mask_t::SpacingType & mosaic_sp,
3663 const unsigned int num_images,
3664 const std::vector<bool> & omit,
3665 const std::vector<transform_pointer_t> & transform,
3666 const std::vector<mask_t::ConstPointer> & image_mask)
3668 if (num_threads == 1)
3671 return make_mask_st<transform_pointer_t>(mosaic_sp,
3679 WRAP(itk_terminator_t terminator(
"make_mask_mt"));
3682 typedef itk::NearestNeighborInterpolateImageFunction<mask_t, double> imask_t;
3683 std::vector<imask_t::Pointer> imask(num_images);
3684 imask.assign(num_images, imask_t::Pointer(NULL));
3686 for (
unsigned int i = 0; i < image_mask.size() && i < num_images; i++)
3688 if (image_mask[i].GetPointer() == NULL)
continue;
3690 imask[i] = imask_t::New();
3691 imask[i]->SetInputImage(image_mask[i]);
3695 typedef mask_t::PointType pnt_t;
3696 std::vector<pnt_t> bbox_min(num_images);
3697 std::vector<pnt_t> bbox_max(num_images);
3698 calc_image_bboxes<mask_t::ConstPointer>(image_mask, bbox_min, bbox_max);
3701 std::vector<pnt_t> min(num_images);
3702 std::vector<pnt_t> max(num_images);
3703 calc_mosaic_bboxes<pnt_t, transform_pointer_t>(transform,
3712 calc_mosaic_bbox<pnt_t>(min, max, mosaic_min, mosaic_max);
3715 mask_t::Pointer mosaic = mask_t::New();
3716 mask_t::RegionType::SizeType mosaic_sz;
3717 mosaic_sz[0] =
static_cast<unsigned int>((mosaic_max[0] - mosaic_min[0]) /
3719 mosaic_sz[1] =
static_cast<unsigned int>((mosaic_max[1] - mosaic_min[1]) /
3721 mosaic->SetOrigin(pnt2d(mosaic_min[0], mosaic_min[1]));
3722 mosaic->SetRegions(mosaic_sz);
3723 mosaic->SetSpacing(mosaic_sp);
3727 std::list<the_transaction_t *> schedule;
3728 for (
unsigned int i = 0; i < num_threads; i++)
3742 schedule.push_back(t);
3747 thread_pool.set_idle_sleep_duration(50);
3748 thread_pool.push_back(schedule);
3749 thread_pool.pre_distribute_work();
3753 thread_pool.start();
3763 template <
class transform_po
inter_t>
3765 make_mask(
const mask_t::SpacingType & mosaic_sp,
3766 const unsigned int num_images,
3767 const std::vector<bool> & omit,
3768 const std::vector<transform_pointer_t> & transform,
3769 const std::vector<mask_t::ConstPointer> & image_mask)
3772 unsigned int num_threads = boost::thread::hardware_concurrency();
3774 return make_mask_mt<transform_pointer_t>(num_threads,
3787 template <
class transform_po
inter_t>
3789 make_mask(
const std::vector<transform_pointer_t> & transform,
3790 const std::vector<mask_t::ConstPointer> & image_mask)
3792 const unsigned int num_images = transform.size();
3793 return make_mask<transform_pointer_t>(image_mask[0]->GetSpacing(),
3795 std::vector<bool>(num_images,
false),
3805 template <
class image_po
inter_t,
class transform_po
inter_t>
3806 typename image_pointer_t::ObjectType::Pointer
3807 make_mosaic(
const feathering_t feathering,
3808 const std::vector<transform_pointer_t> & transform,
3809 const std::vector<image_pointer_t> & image,
3810 const std::vector<mask_t::ConstPointer> & image_mask =
3811 std::vector<mask_t::ConstPointer>(0),
3812 bool dont_allocate =
false)
3814 const unsigned int num_images = transform.size();
3815 return make_mosaic<image_pointer_t, transform_pointer_t>
3816 (image[0]->GetSpacing(),
3818 std::vector<bool>(num_images,
false),
3837 template <
typename T>
3840 const base_transform_t * t)
3842 std::vector<typename T::ConstPointer> image(1);
3845 std::vector<base_transform_t::ConstPointer> transform(1);
3849 make_mosaic<typename T::ConstPointer, base_transform_t::ConstPointer>
3861 template <
typename T>
3863 resize(
const T * in,
double scale)
3865 typedef itk::ScaleTransform<double, 2> scale_t;
3866 scale_t::Pointer transform = scale_t::New();
3867 scale_t::ScaleType s = transform->GetScale();
3870 transform->SetScale(s);
3871 return warp<T>(in, transform);
3881 template <
typename T>
3883 resize(
const T * in,
unsigned int max_edge_size,
double & scale)
3885 typename T::RegionType::SizeType sz =
3886 in->GetLargestPossibleRegion().GetSize();
3888 double xScale =
static_cast<double>(max_edge_size) / static_cast<double>(sz[0]);
3889 double yScale =
static_cast<double>(max_edge_size) / static_cast<double>(sz[1]);
3890 scale = xScale < yScale ? xScale : yScale;
3891 return resize<T>(in, scale);
3901 template <
typename T>
3903 resize(
const T * in,
unsigned int max_edge_size)
3906 return resize<T>(in, max_edge_size, scale);
3916 template <
class image_po
inter_t,
class transform_po
inter_t>
3918 save_mosaic(
const std::vector<image_pointer_t> & image,
3919 const std::vector<transform_pointer_t> & transform,
3920 const bfs::path & filename,
3921 const unsigned int omit = std::numeric_limits<unsigned int>::max(),
3922 unsigned int num_images = std::numeric_limits<unsigned int>::max())
3924 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType image_t;
3926 typename image_t::Pointer mosaic =
3927 make_mosaic<image_pointer_t, transform_pointer_t>(image,
3932 save<image_t>(mosaic, filename,
false);
3941 template <
typename T>
3943 align_fi_mi(
const T * fi,
3945 const base_transform_t * mi_transform,
3946 typename T::Pointer & fi_aligned,
3947 typename T::Pointer & mi_aligned)
3949 std::vector<typename T::ConstPointer> image(2);
3953 std::vector<base_transform_t::ConstPointer> transform(2);
3954 transform[0] = identity_transform_t::New();
3955 transform[1] = mi_transform;
3958 make_mosaic<typename T::ConstPointer, base_transform_t::ConstPointer>
3965 make_mosaic<typename T::ConstPointer, base_transform_t::ConstPointer>
3979 template <
typename T>
3981 save_composite(
const bfs::path & filename,
3984 const base_transform_t * xform,
3987 typename T::Pointer fi_aligned;
3988 typename T::Pointer mi_aligned;
3989 align_fi_mi(fi, mi, xform, fi_aligned, mi_aligned);
3991 typedef itk::CastImageFilter<T, native_image_t> cast_to_native_t;
3992 typename cast_to_native_t::Pointer fi_native = cast_to_native_t::New();
3993 typename cast_to_native_t::Pointer mi_native = cast_to_native_t::New();
3994 fi_native->SetInput(fi_aligned);
3995 mi_native->SetInput(mi_aligned);
3997 typedef itk::RGBPixel<native_pixel_t> composite_pixel_t;
3998 typedef itk::Image<composite_pixel_t, 2> composite_image_t;
3999 typedef itk::ComposeRGBImageFilter<native_image_t, composite_image_t>
4002 compose_filter_t::Pointer composer = compose_filter_t::New();
4003 composer->SetInput1(mi_native->GetOutput());
4004 composer->SetInput2(fi_native->GetOutput());
4005 composer->SetInput3(fi_native->GetOutput());
4007 typedef itk::ImageFileWriter<composite_image_t> composite_writer_t;
4008 composite_writer_t::Pointer writer = composite_writer_t::New();
4009 writer->SetFileName(filename.string().c_str());
4010 writer->SetInput(composer->GetOutput());
4025 template <
class image_po
inter_t,
class transform_po
inter_t>
4028 (
typename image_pointer_t::ObjectType::Pointer * mosaic,
4029 const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
4030 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
4031 const typename image_pointer_t::ObjectType::SizeType & mosaic_sz,
4032 const xyz_t & background_color,
4033 const std::vector<xyz_t> & color,
4034 const std::vector<bool> & omit,
4035 const std::vector<transform_pointer_t> & transform,
4036 const std::vector<image_pointer_t> & image,
4039 const std::vector<mask_t::ConstPointer> & image_mask =
4040 std::vector<mask_t::ConstPointer>(0),
4043 const feathering_t feathering = FEATHER_NONE_E)
4045 WRAP(itk_terminator_t terminator(
"make_mosaic_rgb"));
4046 unsigned int num_images = image.size();
4048 for (
unsigned int i = 0; i < 3; i++)
4050 std::vector<double> tint(num_images);
4051 for (
unsigned int j = 0; j < num_images; j++)
4053 tint[j] = color[j][i] / 255.0;
4057 make_mosaic<image_pointer_t, transform_pointer_t>
4068 background_color[i]);
4083 template <
class image_po
inter_t,
class transform_po
inter_t>
4086 (
typename image_pointer_t::ObjectType::Pointer * mosaic,
4087 const typename image_pointer_t::ObjectType::SpacingType & mosaic_sp,
4088 const typename image_pointer_t::ObjectType::PointType & mosaic_min,
4089 const typename image_pointer_t::ObjectType::PointType & mosaic_max,
4090 const xyz_t & background_color,
4091 const std::vector<xyz_t> & color,
4092 const std::vector<bool> & omit,
4093 const std::vector<transform_pointer_t> & transform,
4094 const std::vector<image_pointer_t> & image,
4097 const std::vector<mask_t::ConstPointer> & image_mask =
4098 std::vector<mask_t::ConstPointer>(0),
4101 const feathering_t feathering = FEATHER_NONE_E)
4103 typename image_pointer_t::ObjectType::SizeType mosaic_sz;
4104 mosaic_sz[0] =
static_cast<unsigned int>((mosaic_max[0] - mosaic_min[0]) /
4106 mosaic_sz[1] =
static_cast<unsigned int>((mosaic_max[1] - mosaic_min[1]) /
4109 make_mosaic_rgb<image_pointer_t, transform_pointer_t>
4132 template <
class image_po
inter_t,
class transform_po
inter_t>
4134 make_mosaic_rgb(
typename image_pointer_t::ObjectType::Pointer * mosaic,
4135 const xyz_t & background_color,
4136 const std::vector<xyz_t> & color,
4137 const std::vector<bool> & omit,
4138 const std::vector<transform_pointer_t> & transform,
4139 const std::vector<image_pointer_t> & image,
4142 const std::vector<mask_t::ConstPointer> & image_mask =
4143 std::vector<mask_t::ConstPointer>(0),
4146 const feathering_t feathering = FEATHER_NONE_E)
4149 typename image_pointer_t::ObjectType::SpacingType mosaic_sp =
4150 image[0]->GetSpacing();
4153 typename image_pointer_t::ObjectType::PointType mosaic_min;
4154 typename image_pointer_t::ObjectType::PointType mosaic_max;
4155 calc_mosaic_bbox<image_pointer_t, transform_pointer_t>
4161 make_mosaic_rgb<image_pointer_t, transform_pointer_t>
4181 make_colors(
const unsigned int & num_color, std::vector<xyz_t> & color);
4193 template <
class image_po
inter_t,
class transform_po
inter_t>
4195 make_mosaic_rgb(
typename image_pointer_t::ObjectType::Pointer * mosaic,
4196 const std::vector<bool> & omit,
4197 const std::vector<transform_pointer_t> & transform,
4198 const std::vector<image_pointer_t> & image,
4201 const std::vector<mask_t::ConstPointer> & image_mask =
4202 std::vector<mask_t::ConstPointer>(0),
4205 const feathering_t feathering = FEATHER_NONE_E,
4208 double background = 255.0,
4211 bool first_tile_white =
false)
4213 static const xyz_t EAST = xyz(1, 0, 0);
4214 static const xyz_t NORTH = xyz(0, 1, 0);
4215 static const xyz_t WEST = xyz(0, 0, 1);
4216 static const xyz_t SOUTH = xyz(0, 0, 0);
4218 unsigned int num_images = image.size();
4219 xyz_t background_color = xyz(background, background, background);
4220 std::vector<xyz_t> color;
4222 if (first_tile_white)
4224 std::vector<xyz_t> tmp;
4225 make_colors(num_images - 1, tmp);
4226 color.resize(num_images);
4227 color[0] = xyz(255, 255, 255);
4228 for (
unsigned int i = 1; i < num_images; i++)
4230 color[i] = tmp[i - 1];
4235 make_colors(num_images, color);
4238 make_mosaic_rgb<image_pointer_t, transform_pointer_t>
4258 template <
class image_po
inter_t,
class transform_po
inter_t>
4260 make_mosaic_rgb(
typename image_pointer_t::ObjectType::Pointer * mosaic,
4261 const feathering_t feathering,
4262 const std::vector<transform_pointer_t> & transform,
4263 const std::vector<image_pointer_t> & image,
4264 const std::vector<mask_t::ConstPointer> & image_mask =
4265 std::vector<mask_t::ConstPointer>(0),
4266 const double background = 255.0,
4267 bool first_tile_white =
false)
4269 make_mosaic_rgb<image_pointer_t, transform_pointer_t>
4271 std::vector<bool>(transform.size(),
false),
4285 template <
typename T>
4287 to_rgb(
const T * image, native_image_t::Pointer * rgb)
4290 cast<T, native_image_t>(remap_min_max<T>(image, 0.0, 255.0));
4291 rgb[1] = cast<native_image_t, native_image_t>(rgb[0]);
4292 rgb[2] = cast<native_image_t, native_image_t>(rgb[0]);
4300 template <
class image_ptr_t>
4302 save_rgb(
const image_ptr_t * image,
const bfs::path & filename,
bool blab =
false)
4304 typedef typename image_ptr_t::ObjectType::Pointer::ObjectType image_t;
4306 typedef itk::RGBPixel<native_pixel_t> composite_pixel_t;
4307 typedef itk::Image<composite_pixel_t, 2> composite_image_t;
4308 typedef itk::ComposeRGBImageFilter<image_t, composite_image_t>
4311 typename compose_filter_t::Pointer composer = compose_filter_t::New();
4312 composer->SetInput1(image[0]);
4313 composer->SetInput2(image[1]);
4314 composer->SetInput3(image[2]);
4316 typedef itk::ImageFileWriter<composite_image_t> composite_writer_t;
4317 typename composite_writer_t::Pointer writer = composite_writer_t::New();
4318 writer->SetFileName(filename.string().c_str());
4319 writer->SetInput(composer->GetOutput());
4336 template <
class image_po
inter_t,
class transform_po
inter_t>
4338 save_mosaic_rgb(
const bfs::path & filename,
4339 const feathering_t feathering,
4340 const std::vector<transform_pointer_t> & transform,
4341 const std::vector<image_pointer_t> & image,
4342 const std::vector<mask_t::ConstPointer> & image_mask =
4343 std::vector<mask_t::ConstPointer>(0),
4344 const double background = 255.0,
4345 bool first_tile_white =
false,
4348 typedef typename image_pointer_t::ObjectType::Pointer::ObjectType image_t;
4349 typename image_t::Pointer mosaic[3];
4350 make_mosaic_rgb<image_pointer_t, transform_pointer_t>
4358 save_rgb<typename image_t::Pointer>(mosaic, filename, blab);
4367 template <
typename T>
4369 save_rgb(
const bfs::path & fn_save,
4372 const base_transform_t * xform,
4373 const mask_t * fi_mask = 0,
4374 const mask_t * mi_mask = 0,
4377 std::vector<typename T::ConstPointer> image(2);
4378 std::vector<mask_t::ConstPointer> mask(2);
4379 std::vector<base_transform_t::ConstPointer> transform(2);
4387 transform[0] = identity_transform_t::New();
4388 transform[1] = xform;
4390 typename T::Pointer mosaic[3];
4391 make_mosaic_rgb(mosaic,
4392 std::vector<bool>(2,
false),
4400 save_rgb<typename T::Pointer>(mosaic, fn_save, blab);
4409 inline static translate_transform_t::Pointer
4410 inverse(
const translate_transform_t * transform)
4412 translate_transform_t::Pointer inv = NULL;
4413 if (transform != NULL)
4415 inv = translate_transform_t::New();
4416 inv->SetOffset(neg(transform->GetOffset()));
4428 template <
class data_t>
4430 remap(
const std::list<unsigned int> & mapping,
4431 const std::vector<data_t> & in,
4432 std::vector<data_t> & out)
4434 unsigned int size = mapping.size();
4437 typename std::list<unsigned int>::const_iterator iter = mapping.begin();
4438 for (
unsigned int i = 0; i < size; i++, ++iter)
4449 template <
class data_t>
4451 remap(
const std::list<unsigned int> & mapping,
4452 const std::list<data_t> & in,
4453 std::list<data_t> & out)
4455 unsigned int size = in.size();
4458 std::vector<const data_t *> rapid(size);
4460 typename std::list<data_t>::const_iterator iter = in.begin();
4461 for (
unsigned int i = 0; i < size; i++, ++iter)
4463 rapid[i] = &(*iter);
4469 typename std::list<unsigned int>::const_iterator iter = mapping.begin();
4470 for (; iter != mapping.end(); ++iter)
4472 out.push_back(*(rapid[*iter]));
4481 template <
class container_t>
4483 remap(
const std::list<unsigned int> & mapping,
4484 const container_t & container)
4487 remap(mapping, container, out);
4497 template <
typename T>
4499 mark(
typename T::Pointer & image,
4500 const typename T::IndexType & index,
4501 const typename T::PixelType & mark_value,
4502 const int arm_length = 2,
4503 const char symbol =
'+')
4505 typedef typename T::SpacingType spacing_t;
4506 typedef typename T::RegionType::SizeType image_size_t;
4507 typedef typename T::IndexType index_t;
4509 image_size_t sz = image->GetLargestPossibleRegion().GetSize();
4512 for (
int j = -arm_length; j <= arm_length; j++)
4514 int x = index[0] + j;
4515 int y = index[1] + j;
4522 if (xy[0] >= 0 && image_size_value_t(xy[0]) < sz[0] &&
4523 xy[1] >= 0 && image_size_value_t(xy[1]) < sz[1])
4525 image->SetPixel(xy, mark_value);
4530 if (xy[0] >= 0 && image_size_value_t(xy[0]) < sz[0] &&
4531 xy[1] >= 0 && image_size_value_t(xy[1]) < sz[1])
4533 image->SetPixel(xy, mark_value);
4541 if (xy[0] >= 0 && image_size_value_t(xy[0]) < sz[0] &&
4542 xy[1] >= 0 && image_size_value_t(xy[1]) < sz[1])
4544 image->SetPixel(xy, mark_value);
4547 xy[1] = index[1] - j;
4548 if (xy[0] >= 0 && image_size_value_t(xy[0]) < sz[0] &&
4549 xy[1] >= 0 && image_size_value_t(xy[1]) < sz[1])
4551 image->SetPixel(xy, mark_value);
4562 template <
typename T>
4564 mark(
typename T::Pointer & image,
4565 const pnt2d_t & mark_coords,
4566 const typename T::PixelType & mark_value,
4567 const int arm_length = 2,
4568 const char symbol =
'+')
4570 typedef typename T::IndexType index_t;
4573 if (!image->TransformPhysicalPointToIndex(mark_coords, index))
4579 mark<T>(image, index, mark_value, arm_length, symbol);
4587 template <
typename T>
4589 fill(
typename T::Pointer & a,
4594 const typename T::PixelType & fill_value =
4595 itk::NumericTraits<typename T::PixelType>::Zero)
4597 WRAP(itk_terminator_t terminator(
"fill"));
4600 typedef typename T::IndexType ix_t;
4601 typedef typename T::RegionType rn_t;
4602 typedef typename T::SizeType sz_t;
4604 sz_t sz = a->GetLargestPossibleRegion().GetSize();
4615 region.SetIndex(origin);
4616 region.SetSize(extent);
4618 typedef typename itk::ImageRegionIterator<T> iter_t;
4619 iter_t iter(a, region);
4620 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
4623 WRAP(terminator.terminate_on_request());
4625 ix_t ix = iter.GetIndex();
4626 if (image_size_value_t(ix[0]) >= sz[0] ||
4627 image_size_value_t(ix[1]) >= sz[1])
4632 iter.Set(fill_value);
4642 save_transform(std::ostream & so,
const itk::TransformBase * t);
4649 extern itk::TransformBase::Pointer
4650 load_transform(std::istream & si,
const bfs::path & transform_type);
4658 extern itk::TransformBase::Pointer
4659 load_transform(std::istream & si);
4668 save_mosaic(std::ostream & so,
4669 const unsigned int & num_images,
4670 const double & pixel_spacing,
4671 const bool & use_std_mask,
4672 const std::vector<bfs::path> & images,
4673 const std::vector<const itk::TransformBase *>& transform);
4681 load_mosaic(std::istream & si,
4682 double & pixel_spacing,
4683 bool & use_std_mask,
4684 std::vector<bfs::path> & image,
4685 std::vector<itk::TransformBase::Pointer> & transform);
4693 template <
class transform_t>
4695 save_mosaic(std::ostream & so,
4696 const double & pixel_spacing,
4697 const bool & use_std_mask,
4698 const std::list<bfs::path> & images,
4699 const std::vector<typename transform_t::Pointer> & transforms)
4701 unsigned int num_images = transforms.size();
4702 std::vector<bfs::path> image(num_images);
4703 std::vector<const itk::TransformBase *> tbase(num_images);
4705 std::vector<typename transform_t::Pointer> & ttmp =
4706 const_cast<std::vector<typename transform_t::Pointer> &
>(transforms);
4708 std::list<bfs::path>::const_iterator iter = images.begin();
4709 for (
unsigned int i = 0; i < images.size(); i++, ++iter)
4713 tbase[i] = ttmp[i].GetPointer();
4729 template <
class transform_t>
4731 load_mosaic(std::istream & si,
4732 double & pixel_spacing,
4733 bool & use_std_mask,
4734 std::list<bfs::path> & images,
4735 std::vector<typename transform_t::Pointer> & transforms,
4736 const bfs::path & image_path)
4738 std::vector<bfs::path> image;
4739 std::vector<itk::TransformBase::Pointer> tbase;
4741 load_mosaic(si, pixel_spacing, use_std_mask, image, tbase);
4742 transforms.resize(tbase.size());
4743 for (
unsigned int i = 0; i < tbase.size(); i++)
4745 images.push_back(image[i]);
4746 transforms[i] =
dynamic_cast<transform_t *
>(tbase[i].GetPointer());
4749 if ( image_path.empty() )
4753 for (std::list<bfs::path>::iterator iter = images.begin();
4754 iter != images.end(); ++iter)
4756 (*iter) = image_path / iter->filename();
4768 template <
typename T>
4770 histogram_equalization(
const T * in,
4771 const unsigned int bins = 256,
4772 typename T::PixelType new_min =
4773 std::numeric_limits<typename T::PixelType>::max(),
4774 typename T::PixelType new_max =
4775 -std::numeric_limits<typename T::PixelType>::max(),
4776 const mask_t * mask = NULL)
4779 typedef typename T::RegionType rn_t;
4780 typedef typename T::IndexType ix_t;
4781 typedef typename T::SizeType sz_t;
4782 typedef typename T::PixelType pixel_t;
4787 image_min_max<T>(in, p_min, p_max, mask);
4788 pixel_t p_rng = p_max - p_min;
4790 typename T::Pointer image = cast<T, T>(in);
4792 if (p_rng == pixel_t(0))
4798 if (new_min == std::numeric_limits<pixel_t>::max()) new_min = p_min;
4799 if (new_max == -std::numeric_limits<pixel_t>::max()) new_max = p_max;
4800 pixel_t new_rng = new_max - new_min;
4802 sz_t sz = in->GetLargestPossibleRegion().GetSize();
4805 std::vector<unsigned int> pdf(bins);
4806 std::vector<double> clipped_pdf(bins);
4807 std::vector<double> cdf(bins);
4809 for (
unsigned int i = 0; i < bins; i++)
4812 clipped_pdf[i] = 0.0;
4816 typedef typename itk::ImageRegionConstIteratorWithIndex<T> iter_t;
4817 iter_t iter(in, in->GetLargestPossibleRegion());
4818 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
4820 ix_t ix = iter.GetIndex();
4822 if (pixel_in_mask<T>(in, mask, ix))
4824 pixel_t p = iter.Get();
4826 static_cast<unsigned int>(
static_cast<double>(p - p_min) / static_cast<double>(p_rng) *
4827 static_cast<double>(bins - 1));
4833 cdf[0] =
static_cast<double>(pdf[0]);
4834 for (
unsigned int i = 1; i < bins; i++)
4836 cdf[i] = cdf[i - 1] +
static_cast<double>(pdf[i]);
4840 iter = iter_t(in, in->GetLargestPossibleRegion());
4841 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
4843 ix_t ix = iter.GetIndex();
4846 pixel_t p_out = new_min;
4847 if (pixel_in_mask<T>(in, mask, ix))
4849 pixel_t p_in = iter.Get();
4850 unsigned int bin =
static_cast<unsigned int>((
static_cast<double>(p_in - p_min) /
4851 static_cast<double>(p_rng)) *
4852 static_cast<double>(bins - 1));
4853 p_out = pixel_t(static_cast<double>(new_min) + static_cast<double>(new_rng) *
4854 static_cast<double>(cdf[bin]) / static_cast<double>(cdf[bins - 1]));
4857 image->SetPixel(ix, p_out);
4870 clip_histogram(
const double & clipping_height,
4871 const unsigned int & pdf_size,
4872 const unsigned int * pdf,
4873 double * clipped_pdf);
4883 template <
typename T>
4889 const unsigned int bins = 256,
4890 typename T::PixelType new_min =
4891 std::numeric_limits<typename T::PixelType>::max(),
4892 typename T::PixelType new_max =
4893 -std::numeric_limits<typename T::PixelType>::max(),
4894 const mask_t * mask = NULL)
4897 typedef typename T::RegionType rn_t;
4898 typedef typename T::IndexType ix_t;
4899 typedef typename T::SizeType sz_t;
4900 typedef typename T::PixelType pixel_t;
4904 if ( nx <= 1 && ny <= 1 )
4906 CORE_THROW_EXCEPTION(
"Window dimensions (nx, ny) fail sanity check");
4910 if ( max_slope < 1.0 && max_slope != 0 )
4912 CORE_THROW_EXCEPTION(
"Max_slope fails sanity check");
4917 CORE_THROW_EXCEPTION(
"Null input image");
4923 image_min_max<T>(in, p_min, p_max, mask);
4924 pixel_t p_rng = p_max - p_min;
4926 typename T::Pointer image = cast<T, T>(in);
4928 if (p_rng == pixel_t(0))
4934 if (new_min == std::numeric_limits<pixel_t>::max()) new_min = p_min;
4935 if (new_max == -std::numeric_limits<pixel_t>::max()) new_max = p_max;
4936 pixel_t new_rng = new_max - new_min;
4938 sz_t sz = in->GetLargestPossibleRegion().GetSize();
4939 const int image_w = sz[0];
4940 const int image_h = sz[1];
4943 nx = std::min(nx, image_w);
4944 ny = std::min(ny, image_h);
4947 const int cx = nx / 2;
4948 const int cy = ny / 2;
4951 std::vector<unsigned int> pdf(bins);
4952 std::vector<double> clipped_pdf(bins);
4953 std::vector<double> cdf(bins);
4955 for (
unsigned int i = 0; i < bins; i++)
4958 clipped_pdf[i] = 0.0;
4962 for (
int x = 0; x < nx; x++)
4964 for (
int y = 0; y < ny; y++)
4970 if (pixel_in_mask<T>(in, mask, ix))
4972 pixel_t p = in->GetPixel(ix);
4974 static_cast<unsigned int>(
static_cast<double>(p - p_min) / static_cast<double>(p_rng) *
4975 static_cast<double>(bins - 1));
4982 if (max_slope != 0.0)
4984 double clipping_height =
4985 (
static_cast<double>(nx * ny) / static_cast<double>(bins)) * max_slope;
4986 clip_histogram(clipping_height, bins, &(pdf[0]), &(clipped_pdf[0]));
4990 for (
unsigned int i = 0; i < bins; i++)
4992 clipped_pdf[i] =
static_cast<double>(pdf[i]);
4997 cdf[0] =
static_cast<double>(clipped_pdf[0]);
4998 for (
unsigned int i = 1; i < bins; i++)
5000 cdf[i] = cdf[i - 1] +
static_cast<double>(clipped_pdf[i]);
5007 for (
int x = 0; x < image_w; x++)
5010 int y0 = (x % 2 == 0) ? 0 : image_h - 1;
5011 int y1 = (x % 2 == 0) ? image_h - 1 : 0;
5012 int dy = (x % 2 == 0) ? 1 : -1;
5014 for (
int y = y0; y != (y1 + dy); y += dy)
5029 int spill_x0 = std::max(0, cx - x);
5030 int spill_y0 = std::max(0, cy - y);
5031 int spill_x1 = std::max(0, x - (image_w - nx + cx));
5032 int spill_y1 = std::max(0, y - (image_h - ny + cy));
5034 int new_hx = x + spill_x0 - spill_x1;
5035 int new_hy = y + spill_y0 - spill_y1;
5037 int shift_x = new_hx - hist_x;
5038 int shift_y = new_hy - hist_y;
5044 if ( shift_x != 1 && shift_x != -1 )
5046 CORE_THROW_EXCEPTION(
"bad histogram shift");
5049 for (
int ty = 0; ty < ny; ty++)
5052 ix[1] = hist_y + ty - cy;
5055 ix[0] = (shift_x > 0) ? new_hx - cx + nx - 1 : new_hx - cx;
5057 if (pixel_in_mask<T>(in, mask, ix))
5059 pixel_t a = in->GetPixel(ix);
5060 unsigned int bin =
static_cast<unsigned int>(
5061 (
static_cast<double>(a - p_min) / static_cast<double>(p_rng)) * static_cast<double>(bins - 1));
5066 ix[0] = (shift_x > 0) ? hist_x - cx : hist_x - cx + nx - 1;
5067 if (pixel_in_mask<T>(in, mask, ix))
5069 pixel_t d = in->GetPixel(ix);
5070 unsigned int bin =
static_cast<unsigned int>(
5071 (
static_cast<double>(d - p_min) / static_cast<double>(p_rng)) * static_cast<double>(bins - 1));
5083 if ( shift_y != 1 && shift_y != -1 )
5085 CORE_THROW_EXCEPTION(
"bad histogram shift");
5088 for (
int tx = 0; tx < nx; tx++)
5091 ix[0] = hist_x + tx - cx;
5094 ix[1] = (shift_y > 0) ? new_hy - cy + ny - 1 : new_hy - cy;
5095 if (pixel_in_mask<T>(in, mask, ix))
5097 pixel_t a = in->GetPixel(ix);
5098 unsigned int bin =
static_cast<unsigned int>(
5099 (
static_cast<double>(a - p_min) / static_cast<double>(p_rng)) * static_cast<double>(bins - 1));
5104 ix[1] = (shift_y > 0) ? hist_y - cy : hist_y - cy + ny - 1;
5105 if (pixel_in_mask<T>(in, mask, ix))
5107 pixel_t d = in->GetPixel(ix);
5108 unsigned int bin =
static_cast<unsigned int>(
5109 (
static_cast<double>(d - p_min) / static_cast<double>(p_rng)) * static_cast<double>(bins - 1));
5117 if (shift_x != 0 || shift_y != 0)
5120 if (max_slope != 0.0)
5122 double clipping_height =
5123 (
static_cast<double>(nx * ny) / static_cast<double>(bins)) * max_slope;
5124 clip_histogram(clipping_height, bins, &(pdf[0]), &(clipped_pdf[0]));
5128 for (
unsigned int i = 0; i < bins; i++)
5130 clipped_pdf[i] =
static_cast<double>(pdf[i]);
5135 cdf[0] =
static_cast<double>(clipped_pdf[0]);
5136 for (
unsigned int i = 1; i < bins; i++)
5138 cdf[i] = cdf[i - 1] +
static_cast<double>(clipped_pdf[i]);
5147 pixel_t p_out = new_min;
5148 if (pixel_in_mask<T>(in, mask, ix))
5150 pixel_t p_in = in->GetPixel(ix);
5151 unsigned int bin =
static_cast<unsigned int>(
5152 (
static_cast<double>(p_in - p_min) / static_cast<double>(p_rng)) * static_cast<double>(bins - 1));
5153 p_out = pixel_t(static_cast<double>(new_min) + static_cast<double>(new_rng) *
5154 static_cast<double>(cdf[bin]) / static_cast<double>(cdf[bins - 1]));
5157 image->SetPixel(ix, p_out);
5170 template <
typename T>
5172 median(
const T * a,
const unsigned int & median_radius)
5174 typedef itk::MedianImageFilter<T, T> filter_t;
5175 typename filter_t::Pointer filter = filter_t::New();
5176 typename filter_t::InputSizeType radius;
5177 radius[0] = median_radius;
5178 radius[1] = median_radius;
5179 filter->SetInput(a);
5180 filter->SetRadius(radius);
5185 WRAP(terminator_t<filter_t> terminator(filter));
5187 return filter->GetOutput();
5197 template <
typename T>
5199 normalize(
const T * a,
const mask_t * ma)
5202 typename filter_t::Pointer filter = filter_t::New();
5203 filter->SetInput(a);
5204 filter->SetImageMask(mask_so(ma));
5206 WRAP(terminator_t<filter_t> terminator(filter));
5208 return filter->GetOutput();
5217 pixel_weight(
const image_t::IndexType & min,
5218 const image_t::IndexType & max,
5219 const image_t::IndexType & ix)
5221 double w =
static_cast<double>(max[0]) - static_cast<double>(min[0]);
5222 double h =
static_cast<double>(max[1]) - static_cast<double>(min[1]);
5223 double r = 0.5 * ((w > h) ? h : w);
5224 double sx = std::min(static_cast<double>(ix[0]) - static_cast<double>(min[0]),
5225 static_cast<double>(max[0]) - static_cast<double>(ix[0]));
5226 double sy = std::min(static_cast<double>(ix[1]) - static_cast<double>(min[1]),
5227 static_cast<double>(max[1]) - static_cast<double>(ix[1]));
5228 double s = (1.0 + std::min(sx, sy)) / (r + 1.0);
5241 template <
typename T>
5243 normalize(
const T * image,
5244 const unsigned int cols,
5245 const unsigned int rows,
5246 typename T::PixelType new_min =
5247 std::numeric_limits<typename T::PixelType>::max(),
5248 typename T::PixelType new_max =
5249 -std::numeric_limits<typename T::PixelType>::max(),
5250 const mask_t * mask = NULL)
5252 WRAP(itk_terminator_t terminator(
"normalize"));
5254 if (new_min == std::numeric_limits<typename T::PixelType>::max() ||
5255 new_max == -std::numeric_limits<typename T::PixelType>::max())
5258 typename T::PixelType p_min;
5259 typename T::PixelType p_max;
5260 image_min_max<T>(image, p_min, p_max, mask);
5262 if (new_min == std::numeric_limits<typename T::PixelType>::max())
5267 if (new_max == -std::numeric_limits<typename T::PixelType>::max())
5274 typename T::SizeType sz = image->GetLargestPossibleRegion().GetSize();
5276 double half_tw =
static_cast<double>(sz[0]) / static_cast<double>(cols + 1);
5277 double half_th =
static_cast<double>(sz[1]) / static_cast<double>(rows + 1);
5279 typename T::Pointer out = cast<T, T>(image);
5281 array2d(
typename T::Pointer) tile;
5282 resize<typename T::Pointer>(tile, cols, rows);
5284 array2d(mask_t::Pointer) tile_mask;
5285 resize<mask_t::Pointer>(tile_mask, cols, rows);
5287 array2d(typename T::IndexType) tile_min;
5288 resize<typename T::IndexType>(tile_min, cols, rows);
5290 array2d(typename T::IndexType) tile_max;
5291 resize<typename T::IndexType>(tile_max, cols, rows);
5293 for (
unsigned int i = 0; i < cols; i++)
5295 double x0 =
static_cast<double>(i) * half_tw;
5296 unsigned int ix0 =
static_cast<unsigned int>(floor(x0));
5297 double x1 =
static_cast<double>(ix0) + (x0 - static_cast<double>(ix0)) + 2.0 * half_tw;
5298 unsigned int ix1 = std::min(static_cast<unsigned int>(sz[0] - 1),
5299 static_cast<unsigned int>(ceil(x1)));
5301 for (
unsigned int j = 0; j < rows; j++)
5303 double y0 =
static_cast<double>(j) * half_th;
5304 unsigned int iy0 =
static_cast<unsigned int>(floor(y0));
5305 double y1 =
static_cast<double>(iy0) + (y0 - static_cast<double>(iy0)) + 2.0 * half_th;
5306 unsigned int iy1 = std::min(static_cast<unsigned int>(sz[1] - 1),
5307 static_cast<unsigned int>(ceil(y1)));
5309 tile_min[i][j][0] = ix0;
5310 tile_min[i][j][1] = iy0;
5311 tile_max[i][j][0] = ix1;
5312 tile_max[i][j][1] = iy1;
5314 tile[i][j] = crop<T>(image, tile_min[i][j], tile_max[i][j]);
5315 tile_mask[i][j] = crop<mask_t>(mask, tile_min[i][j], tile_max[i][j]);
5317 typename T::Pointer v1 =
5318 normalize<T>(tile[i][j], tile_mask[i][j]);
5320 typename T::Pointer v2 =
5321 threshold<T>(v1, -3, 3, -3, 3);
5328 typedef itk::ImageRegionIteratorWithIndex<T> itex_t;
5329 itex_t itex(out, out->GetLargestPossibleRegion());
5330 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
5333 WRAP(terminator.terminate_on_request());
5335 typename T::IndexType ix = itex.GetIndex();
5339 for (
unsigned int i = 0; i < cols; i++)
5341 for (
unsigned int j = 0; j < rows; j++)
5343 if (ix[0] >= tile_min[i][j][0] &&
5344 ix[0] <= tile_max[i][j][0] &&
5345 ix[1] >= tile_min[i][j][1] &&
5346 ix[1] <= tile_max[i][j][1])
5348 typename T::IndexType index;
5349 index[0] = ix[0] - tile_min[i][j][0];
5350 index[1] = ix[1] - tile_min[i][j][1];
5352 double weight = pixel_weight(tile_min[i][j], tile_max[i][j], ix);
5353 wsum += weight * tile[i][j]->GetPixel(index);
5359 if (mass != 0.0) wsum /= mass;
5360 out->SetPixel(ix, wsum);
5363 remap_min_max_inplace<T>(out, new_min, new_max);
5374 template <
typename T,
class transform_vec_t>
5375 typename T::PointType
5376 forward_transform(
const transform_vec_t & t,
5377 const unsigned int t_size,
5378 const typename T::PointType & in)
5380 typename T::PointType out = in;
5381 for (
unsigned int i = 0; i < t_size; i++)
5383 out = t[i]->TransformPoint(out);
5395 template <
typename T,
class transform_vec_t>
5396 typename T::PointType
5397 inverse_transform(
const transform_vec_t & t_inverse,
5398 const unsigned int t_size,
5399 const typename T::PointType & in)
5401 typename T::PointType out = in;
5402 for (
int i = t_size - 1; i >= 0; i--)
5404 out = t_inverse[i]->TransformPoint(out);
5418 template <
typename T>
5421 const bool flip_x =
true,
5422 const bool flip_y =
false)
5424 WRAP(itk_terminator_t terminator(
"flip"));
5427 typedef typename T::RegionType rn_t;
5428 typedef typename T::IndexType ix_t;
5429 typedef typename T::SizeType sz_t;
5431 typename T::Pointer out = cast<T, T>(in);
5433 if (flip_x || flip_y)
5435 rn_t rn = in->GetLargestPossibleRegion();
5436 sz_t sz = rn.GetSize();
5438 typedef itk::ImageRegionIteratorWithIndex<T> itex_t;
5439 itex_t itex(out, rn);
5441 for (itex.GoToBegin(); !itex.IsAtEnd(); ++itex)
5444 WRAP(terminator.terminate_on_request());
5446 ix_t ix = itex.GetIndex();
5447 if (flip_x) ix[0] = sz[0] - ix[0] - 1;
5448 if (flip_y) ix[1] = sz[1] - ix[1] - 1;
5450 itex.Set(in->GetPixel(ix));
5464 template <
typename T>
5466 overlap_ratio(
const T * fi,
5468 const base_transform_t * fi_to_mi)
5470 if (fi_to_mi == NULL)
return 0.0;
5472 typename T::PointType fi_min = fi->GetOrigin();
5473 typename T::PointType mi_min = mi->GetOrigin();
5475 typename T::SpacingType fi_sp = fi->GetSpacing();
5476 typename T::SpacingType mi_sp = mi->GetSpacing();
5478 typename T::SizeType fi_sz = fi->GetLargestPossibleRegion().GetSize();
5479 typename T::SizeType mi_sz = mi->GetLargestPossibleRegion().GetSize();
5481 typename T::PointType fi_max =
5482 fi_min + vec2d((fi_sz[0]) * fi_sp[0],
5483 (fi_sz[1]) * fi_sp[1]);
5485 typename T::PointType mi_max =
5486 mi_min + vec2d((mi_sz[0]) * mi_sp[0],
5487 (mi_sz[1]) * mi_sp[1]);
5489 const double w0 = fi_max[0] - fi_min[0];
5490 const double h0 = fi_max[1] - fi_min[1];
5492 const double w1 = mi_max[0] - mi_min[0];
5493 const double h1 = mi_max[1] - mi_min[1];
5495 const double smaller_area = std::min(w0, w1) * std::min(h0, h1);
5497 typename T::PointType ul = fi_to_mi->TransformPoint(fi_min);
5498 ul[0] = std::max(0.0, std::min(w1, ul[0] - mi_min[0]));
5499 ul[1] = std::max(0.0, std::min(h1, ul[1] - mi_min[1]));
5501 typename T::PointType lr = fi_to_mi->TransformPoint(fi_max);
5502 lr[0] = std::max(0.0, std::min(w1, lr[0] - mi_min[0]));
5503 lr[1] = std::max(0.0, std::min(h1, lr[1] - mi_min[1]));
5505 const double dx = lr[0] - ul[0];
5506 const double dy = lr[1] - ul[1];
5507 const double area_ratio = (dx * dy) / smaller_area;
5519 find_inverse(
const pnt2d_t & tile_min,
5520 const pnt2d_t & tile_max,
5521 const base_transform_t * mosaic_to_tile,
5524 const unsigned int max_iterations = 100,
5525 const double min_step_scale = 1e-12,
5526 const double min_error_sqrd = 1e-16,
5527 const unsigned int pick_up_pace_steps = 5);
5536 find_inverse(
const pnt2d_t & tile_min,
5537 const pnt2d_t & tile_max,
5538 const base_transform_t * mosaic_to_tile,
5539 const base_transform_t * tile_to_mosaic,
5542 const unsigned int max_iterations = 100,
5543 const double min_step_scale = 1e-12,
5544 const double min_error_sqrd = 1e-16,
5545 const unsigned int pick_up_pace_steps = 5);
5554 find_inverse(
const base_transform_t * mosaic_to_tile,
5555 const base_transform_t * tile_to_mosaic,
5558 const unsigned int max_iterations = 100,
5559 const double min_step_scale = 1e-12,
5560 const double min_error_sqrd = 1e-16,
5561 const unsigned int pick_up_pace_steps = 5);
5575 generate_landmarks(
const pnt2d_t & tile_min,
5576 const pnt2d_t & tile_max,
5577 const mask_t * tile_mask,
5578 const base_transform_t * mosaic_to_tile,
5579 const unsigned int samples,
5580 std::vector<pnt2d_t> & xy,
5581 std::vector<pnt2d_t> & uv,
5582 const unsigned int version,
5597 generate_landmarks(
const image_t * tile,
5598 const mask_t * mask,
5599 const base_transform_t * mosaic_to_tile,
5600 const unsigned int samples,
5601 std::vector<pnt2d_t> & xy,
5602 std::vector<pnt2d_t> & uv,
5603 const unsigned int version = 1,
5604 const bool refine =
false);
5617 template <
class legendre_transform_t>
5618 typename legendre_transform_t::Pointer
5619 approx_transform(
const pnt2d_t & tile_min,
5620 const pnt2d_t & tile_max,
5621 const mask_t * tile_mask,
5622 const base_transform_t * forward,
5623 const unsigned int samples = 16,
5624 const unsigned int version = 1,
5625 const bool refine =
false)
5627 base_transform_t::Pointer inverse = forward->GetInverseTransform();
5629 if (inverse.GetPointer() == NULL)
5631 CORE_THROW_EXCEPTION(
"Null inverse transform");
5635 pnt2d_t center = pnt2d(tile_min[0] + (tile_max[0] - tile_min[0]) / 2.0,
5636 tile_min[1] + (tile_max[1] - tile_min[1]) / 2.0);
5637 vec2d_t shift = center - inverse->TransformPoint(center);
5639 typename legendre_transform_t::Pointer approx =
5640 setup_transform<legendre_transform_t>(tile_min, tile_max);
5641 approx->setup_translation(shift[0], shift[1]);
5643 std::vector<pnt2d_t> xy;
5644 std::vector<pnt2d_t> uv;
5645 generate_landmarks(tile_min,
5655 unsigned int order = legendre_transform_t::Degree + 1;
5656 unsigned int loworder = std::min(2u, order);
5659 approx->solve_for_parameters(0, loworder, uv, xy);
5660 approx->solve_for_parameters(loworder, order - loworder, uv, xy);
5680 template <
class legendre_transform_t>
5682 solve_for_transform(
const pnt2d_t & tile_min,
5683 const pnt2d_t & tile_max,
5684 const mask_t * tile_mask,
5685 const base_transform_t * mosaic_to_tile_0,
5686 typename legendre_transform_t::Pointer & mosaic_to_tile_1,
5687 const vec2d_t & shift,
5688 const unsigned int samples = 16,
5689 const unsigned int version = 1,
5690 const bool refine =
false)
5692 mosaic_to_tile_1->setup_translation(shift[0], shift[1]);
5700 std::vector<pnt2d_t> xy;
5701 std::vector<pnt2d_t> uv;
5702 generate_landmarks(tile_min,
5712 unsigned int order = legendre_transform_t::Degree + 1;
5713 unsigned int loworder = std::min(2u, order);
5716 mosaic_to_tile_1->solve_for_parameters(0, loworder, uv, xy);
5717 mosaic_to_tile_1->solve_for_parameters(loworder, order - loworder, uv, xy);
5740 template <
typename T,
class legendre_transform_t>
5742 solve_for_transform(
const T * tile,
5743 const mask_t * mask,
5744 const base_transform_t * mosaic_to_tile_0,
5745 typename legendre_transform_t::Pointer & mosaic_to_tile_1,
5746 const vec2d_t & shift,
5747 const unsigned int samples = 16,
5748 const unsigned int version = 1,
5749 const bool refine =
false)
5751 typename T::SpacingType sp = tile->GetSpacing();
5752 typename T::SizeType sz = tile->GetLargestPossibleRegion().GetSize();
5753 const pnt2d_t min = tile->GetOrigin();
5754 const pnt2d_t max = min + vec2d(sp[0] * static_cast<double>(sz[0]),
5755 sp[1] * static_cast<double>(sz[1]));
5757 solve_for_transform<legendre_transform_t>(min,
5779 template <
class legendre_transform_t>
5781 solve_for_transform(
const pnt2d_t & tile_min,
5782 const pnt2d_t & tile_max,
5783 const mask_t * tile_mask,
5784 const base_transform_t * mosaic_to_tile_0,
5785 typename legendre_transform_t::Pointer & mosaic_to_tile_1,
5786 const unsigned int samples = 16,
5787 const unsigned int version = 1,
5788 const bool refine =
false)
5790 base_transform_t::Pointer tile_to_mosaic = mosaic_to_tile_0->GetInverseTransform();
5792 if (tile_to_mosaic.GetPointer() == NULL)
5794 CORE_THROW_EXCEPTION(
"Null inverse transform");
5798 pnt2d_t center = pnt2d(tile_min[0] + (tile_max[0] - tile_min[0]) / 2.0,
5799 tile_min[1] + (tile_max[1] - tile_min[1]) / 2.0);
5800 vec2d_t shift = center - tile_to_mosaic->TransformPoint(center);
5802 solve_for_transform<legendre_transform_t>(tile_min,
5824 template <
typename T,
class legendre_transform_t>
5826 solve_for_transform(
const T * tile,
5827 const mask_t * mask,
5828 const base_transform_t * mosaic_to_tile_0,
5829 typename legendre_transform_t::Pointer & mosaic_to_tile_1,
5830 const unsigned int samples = 16,
5831 const unsigned int version = 1,
5832 const bool refine =
false)
5834 base_transform_t::Pointer tile_to_mosaic = mosaic_to_tile_0->GetInverseTransform();
5836 if (tile_to_mosaic.GetPointer() == NULL)
5838 CORE_THROW_EXCEPTION(
"Null inverse transform");
5841 typename T::SizeType sz = tile->GetLargestPossibleRegion().GetSize();
5842 typename T::SpacingType sp = tile->GetSpacing();
5843 pnt2d_t tile_min = tile->GetOrigin();
5845 tile_max[0] = tile_min[0] + sp[0] *
static_cast<double>(sz[0]);
5846 tile_max[1] = tile_min[1] + sp[1] *
static_cast<double>(sz[1]);
5848 return solve_for_transform<legendre_transform_t>(tile_min,
5865 extern mask_t::Pointer
5866 std_mask(
const itk::Point<double, 2> & origin,
5867 const itk::Vector<double, 2> & spacing,
5868 const itk::Size<2> & sz,
5869 bool use_std_mask =
true);
5877 template <
typename T>
5879 std_mask(
const T * tile,
bool use_std_mask =
true)
5881 return std_mask(tile->GetOrigin(),
5883 tile->GetLargestPossibleRegion().GetSize(),
5895 template <
typename T>
5897 std_tile(
const bfs::path& fn_image,
5898 const unsigned int & shrink_factor,
5899 const double & pixel_spacing,
5900 const double & clahe_slope,
5901 const unsigned int & clahe_window,
5904 typename T::Pointer image = load<T>(fn_image, blab);
5907 typename T::PointType origin = image->GetOrigin();
5910 image->SetOrigin(origin);
5912 typename T::SpacingType spacing = image->GetSpacing();
5915 image->SetSpacing(spacing);
5918 if (shrink_factor > 1)
5920 image = shrink<T>(image, shrink_factor);
5923 typename T::SpacingType sp = image->GetSpacing();
5925 sp[0] *= pixel_spacing;
5926 sp[1] *= pixel_spacing;
5927 image->SetSpacing(sp);
5929 if (clahe_slope > 1.0)
5931 image = CLAHE<T>(image,
5950 template <
typename T>
5952 std_tile(
const bfs::path& fn_image,
5953 const unsigned int & shrink_factor,
5954 const double & pixel_spacing,
5957 return std_tile<T>(fn_image,
5971 template <
class transform_t>
5973 save_volume_slice(std::ostream & so,
5974 const unsigned int & index,
5975 const bfs::path & image,
5976 const double & sp_x,
5977 const double & sp_y,
5978 const transform_t * transform,
5979 const pnt2d_t & overall_min,
5980 const pnt2d_t & overall_max,
5981 const pnt2d_t & slice_min,
5982 const pnt2d_t & slice_max,
5985 std::ios::fmtflags old_flags = so.setf(std::ios::scientific);
5986 int old_precision = so.precision();
5989 so <<
"index: " << index << std::endl
5990 <<
"overall_min: " << overall_min[0] <<
' ' << overall_min[1] << std::endl
5991 <<
"overall_max: " << overall_max[0] <<
' ' << overall_max[1] << std::endl
5992 <<
"slice_min: " << slice_min[0] <<
' ' << slice_min[1] << std::endl
5993 <<
"slice_max: " << slice_max[0] <<
' ' << slice_max[1] << std::endl
5994 <<
"flip: " << flip << std::endl
5995 <<
"sp: " << sp_x <<
' ' << sp_y << std::endl
5996 <<
"image:" << std::endl
5997 << image << std::endl;
5998 save_transform(so, transform);
6002 so.precision(old_precision);
6011 template <
class transform_t>
6013 load_volume_slice(std::istream & si,
6014 unsigned int & index,
6018 typename transform_t::Pointer & transform,
6019 pnt2d_t & overall_min,
6020 pnt2d_t & overall_max,
6021 pnt2d_t & slice_min,
6022 pnt2d_t & slice_max,
6029 if (si.eof() && token.size() == 0)
break;
6031 if (token ==
"index:")
6035 else if (token ==
"overall_min:")
6037 si >> overall_min[0] >> overall_min[1];
6039 else if (token ==
"overall_max:")
6041 si >> overall_max[0] >> overall_max[1];
6043 else if (token ==
"slice_min:")
6045 si >> slice_min[0] >> slice_min[1];
6047 else if (token ==
"slice_max:")
6049 si >> slice_max[0] >> slice_max[1];
6051 else if (token ==
"flip:")
6055 else if (token ==
"sp:")
6059 else if (token ==
"image:")
6062 while (image.empty())
6065 std::getline(si, line);
6067 if (! bfs::exists(image))
6069 std::ostringstream oss;
6070 oss <<
"load_volume_slice cannot find " << image.string();
6071 CORE_LOG_WARNING(oss.str());
6075 itk::TransformBase::Pointer t_base = load_transform(si);
6076 transform =
dynamic_cast<transform_t *
>(t_base.GetPointer());
6078 if (transform.GetPointer() == NULL)
6080 CORE_THROW_EXCEPTION(
"Null transform");
6085 std::ostringstream oss;
6086 oss <<
"WARNING: unknown token: '" << token <<
"', ignoring ...";
6087 CORE_LOG_WARNING(oss.str());
6099 extern image_t::SizeType
6100 calc_size(
const pnt2d_t & min,
6101 const pnt2d_t & max,
6102 const double & spacing);
6110 track_progress(
bool track)
6124 set_major_progress(
double major_percent)
6138 set_minor_progress(
double minor_percent,
double major_percent)
6145 #endif // COMMON_HXX_
Definition: common.hxx:2696
Normalize an image by setting its mean to zero and variance to one.
Definition: itkNormalizeImageFilterWithMask.h:63
Definition: common.hxx:3512
Definition: the_transaction.hxx:55
Definition: the_thread_pool.hxx:105
Definition: common.hxx:619
Definition: the_thread_interface.hxx:57