Skip to content

Commit

Permalink
ENH: Add ElastixRegistrationMethod::SetExternalInitialTransform
Browse files Browse the repository at this point in the history
  • Loading branch information
N-Dekker committed Aug 9, 2023
1 parent edcf557 commit ef22cdd
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
79 changes: 79 additions & 0 deletions Core/Main/GTesting/itkElastixRegistrationMethodGTest.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,85 @@ GTEST_TEST(itkElastixRegistrationMethod, SetExternalTransformAsInitialTransform)
}


GTEST_TEST(itkElastixRegistrationMethod, SetExternalInitialTransform)
{
constexpr unsigned int ImageDimension{ 2 };

using PixelType = float;
using SizeType = itk::Size<ImageDimension>;
const SizeType imageSize{ { 5, 6 } };

using ImageType = itk::Image<PixelType, ImageDimension>;
using TransformixFilterType = itk::TransformixFilter<ImageType>;

const ImageDomain<ImageDimension> imageDomain(imageSize);

elx::DefaultConstruct<itk::TranslationTransform<double, ImageDimension>> itkTransform;
itkTransform.SetOffset(itk::MakeVector(1.0, -2.0));

using ImageType = itk::Image<PixelType, ImageDimension>;
using SizeType = itk::Size<ImageDimension>;
using IndexType = itk::Index<ImageDimension>;
using OffsetType = itk::Offset<ImageDimension>;

const OffsetType initialTranslation{ { 1, -2 } };
const auto regionSize = SizeType::Filled(2);
const IndexType fixedImageRegionIndex{ { 1, 3 } };

const auto fixedImage = CreateImage<PixelType>(imageSize);
FillImageRegion(*fixedImage, fixedImageRegionIndex, regionSize);

const auto movingImage = CreateImage<PixelType>(imageSize);

elx::DefaultConstruct<elx::ParameterObject> registrationParameterObject{};
elx::DefaultConstruct<elx::ParameterObject> initialTransformParameterObject{};
elx::DefaultConstruct<ElastixRegistrationMethodType<ImageType>> registration{};
registration.SetFixedImage(fixedImage);
registration.SetExternalInitialTransform(&itkTransform);
registration.SetParameterObject(&registrationParameterObject);
registration.SetLogToConsole(true);

const elx::ParameterObject::ParameterMapType registrationParameterMap{
// Parameters in alphabetic order:
{ "ImageSampler", { "Full" } },
{ "MaximumNumberOfIterations", { "2" } },
{ "Metric", { "AdvancedNormalizedCorrelation" } },
{ "Optimizer", { "AdaptiveStochasticGradientDescent" } },
{ "Transform", { "TranslationTransform" } }
};

registrationParameterObject.SetParameterMap(registrationParameterMap);

const ParameterMapType initialTransformParameterMap{ { "NumberOfParameters", { "0" } },
{ "Transform", { "ExternalTransform" } },
{ "TransformAddress",
{ elx::Conversion::ObjectPtrToString(&itkTransform) } } };

// Do the test for a few possible translations.
for (const auto index :
itk::ImageRegionIndexRange<ImageDimension>(itk::ImageRegion<ImageDimension>({ 0, -2 }, { 2, 3 })))
{
const auto actualTranslation = ConvertIndexToOffset(index);
movingImage->FillBuffer(0);
FillImageRegion(*movingImage, fixedImageRegionIndex + actualTranslation, regionSize);
registration.SetMovingImage(movingImage);
registration.Update();

const auto & transformParameterMaps =
DerefRawPointer(registration.GetTransformParameterObject()).GetParameterMaps();

ASSERT_EQ(transformParameterMaps.size(), 2);

EXPECT_EQ(transformParameterMaps.front(), initialTransformParameterMap);

// Together the initial translation and the first registration should have the actual image translation.
const auto transformParameters =
ConvertStringsToVectorOfDouble(transformParameterMaps.back().at("TransformParameters"));
EXPECT_EQ(initialTranslation + ConvertToOffset<ImageDimension>(transformParameters), actualTranslation);
}
}


GTEST_TEST(itkElastixRegistrationMethod, SetInitialTransformParameterObjectVersusTransformix)
{
{
Expand Down
9 changes: 8 additions & 1 deletion Core/Main/itkElastixRegistrationMethod.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ class ITK_TEMPLATE_EXPORT ElastixRegistrationMethod : public itk::ImageSource<TF
void
SetInitialTransform(const TransformType *);

/** Set the initial transformation by means of an external ITK Transform. */
void
SetExternalInitialTransform(const TransformType *);

/** Set/Get/Remove fixed point set filename. */
itkSetMacro(FixedPointSetFileName, std::string);
itkGetConstMacro(FixedPointSetFileName, std::string);
Expand Down Expand Up @@ -336,12 +340,14 @@ class ITK_TEMPLATE_EXPORT ElastixRegistrationMethod : public itk::ImageSource<TF
m_InitialTransform = nullptr;
m_InitialTransformParameterFileName.clear();
m_InitialTransformParameterObject = nullptr;
m_ExternalInitialTransform = nullptr;
}

void
ResetInitialTransformAndModified()
{
if (m_InitialTransform || m_InitialTransformParameterObject || !m_InitialTransformParameterFileName.empty())
if (m_InitialTransform || m_InitialTransformParameterObject || m_ExternalInitialTransform ||
!m_InitialTransformParameterFileName.empty())
{
ResetInitialTransformWithoutModified();
this->Modified();
Expand All @@ -358,6 +364,7 @@ class ITK_TEMPLATE_EXPORT ElastixRegistrationMethod : public itk::ImageSource<TF
std::string m_InitialTransformParameterFileName{};
elx::ParameterObject::ConstPointer m_InitialTransformParameterObject{};
SmartPointer<const TransformType> m_InitialTransform{};
SmartPointer<const TransformType> m_ExternalInitialTransform{};

std::string m_FixedPointSetFileName{};
std::string m_MovingPointSetFileName{};
Expand Down
27 changes: 27 additions & 0 deletions Core/Main/itkElastixRegistrationMethod.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ ElastixRegistrationMethod<TFixedImage, TMovingImage>::GenerateData()
// For a single transform, there should be only a single transform parameter map.
return ParameterMapVectorType{ transformToMap(*m_InitialTransform) };
}
if (m_ExternalInitialTransform)
{
return ParameterMapVectorType{ ParameterMapType{
{ "NumberOfParameters", { "0" } },
{ "Transform", { "ExternalTransform" } },
{ "TransformAddress", { elx::Conversion::ObjectPtrToString(m_ExternalInitialTransform) } } } };
}
return {};
};

Expand Down Expand Up @@ -846,6 +853,26 @@ ElastixRegistrationMethod<TFixedImage, TMovingImage>::SetInitialTransform(const
}


template <typename TFixedImage, typename TMovingImage>
void
ElastixRegistrationMethod<TFixedImage, TMovingImage>::SetExternalInitialTransform(const TransformType * const transform)
{
if (transform)
{
if (m_ExternalInitialTransform != transform)
{
ResetInitialTransformWithoutModified();
m_ExternalInitialTransform = transform;
this->Modified();
}
}
else
{
ResetInitialTransformAndModified();
}
}


template <typename TFixedImage, typename TMovingImage>
void
ElastixRegistrationMethod<TFixedImage, TMovingImage>::SetLogFileName(const std::string logFileName)
Expand Down

0 comments on commit ef22cdd

Please sign in to comment.