# Are there any instances about the registration of 3D medical image by landmark?

**URL:** https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256
**Category:** Beginner Questions
**Tags:** itk, registration
**Created:** [October 18, 2023, 6:34am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256 "2023-10-18T06:34:14Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![SeanHan](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/6f9a4e/32.png) [@SeanHan](https://discourse.itk.org/u/SeanHan)
#### Post date: [October 18, 2023, 6:34am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/1 "2023-10-18T06:34:14Z")

</div>

When I set LandmarkBasedTransformInitializer instead of CenteredTransformInitializer, it seems a wrong result. Any suggestions?

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [October 18, 2023, 2:12pm UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/2 "2023-10-18T14:12:57Z")

</div>

Hi,

Here is a [LandmarkBasedTransformInitializer example](https://examples.itk.org/src/registration/common/registerimagetoanotherusinglandmarks/documentation).

---

<div class="post-metadata">

### Author: ![SeanHan](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/6f9a4e/32.png) [@SeanHan](https://discourse.itk.org/u/SeanHan)
#### Post date: [October 19, 2023, 1:20am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/3 "2023-10-19T01:20:49Z")

</div>

Many thanks, but I think 3D landmark is quite difference from 2D landmark.

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [October 19, 2023, 2:45am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/4 "2023-10-19T02:45:20Z")

</div>

ITK handles both 2D and 3D.

---

<div class="post-metadata">

### Author: ![SeanHan](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/6f9a4e/32.png) [@SeanHan](https://discourse.itk.org/u/SeanHan)
#### Post date: [October 19, 2023, 5:51am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/5 "2023-10-19T05:51:36Z")

</div>

The following is my code, is that correct? I can’t get the right output from this registration.

```
using TransformType = itk::VersorRigid3DTransform<double>;

using OptimizerType = itk::RegularStepGradientDescentOptimizerv4<double>;
using MetricType = itk::MattesMutualInformationImageToImageMetricv4<InternalImageType, InternalImageType>;

using RegistrationType = itk::
	ImageRegistrationMethodv4<InternalImageType, InternalImageType, TransformType>;

auto metric = MetricType::New();
auto optimizer = OptimizerType::New();
auto registration = RegistrationType::New();

registration->SetMetric(metric);
unsigned int iBins = 24;
metric->SetNumberOfHistogramBins(iBins);
metric->SetUseFixedImageGradientFilter(false);
metric->SetUseMovingImageGradientFilter(false);

using LandmarkBasedTransformInitializerType =
	itk::LandmarkBasedTransformInitializer<TransformType, InternalImageType, InternalImageType>;

LandmarkBasedTransformInitializerType::Pointer landmarkBasedTransformInitializer =
	LandmarkBasedTransformInitializerType::New();
// Create source and target landmarks.
using LandmarkContainerType = LandmarkBasedTransformInitializerType::LandmarkPointContainer;
using LandmarkPointType = LandmarkBasedTransformInitializerType::LandmarkPointType;

LandmarkContainerType fixedLandmarks;
LandmarkContainerType movingLandmarks;

LandmarkPointType fixedPoint;
LandmarkPointType movingPoint;

for (size_t i = 0; i < fixedpoints.size(); i++)
{
	fixedPoint[0] = fixedpoints[i].x;
	fixedPoint[1] = fixedpoints[i].y;
	fixedPoint[2] = fixedpoints[i].z;
	fixedLandmarks.push_back(fixedPoint);
}

for (size_t i = 0; i < movedpoints.size(); i++)
{
	movingPoint[0] = movedpoints[i].x;
	movingPoint[1] = movedpoints[i].y;
	movingPoint[2] = movedpoints[i].z;
	movingLandmarks.push_back(movingPoint);
}

landmarkBasedTransformInitializer->SetFixedLandmarks(fixedLandmarks);
landmarkBasedTransformInitializer->SetMovingLandmarks(movingLandmarks);

auto transform = TransformType::New();
transform->SetIdentity();
using VersorType = TransformType::VersorType;
using VectorType = VersorType::VectorType;
VersorType rotation;
VectorType axis;
axis[0] = 0.0;
axis[1] = 0.0;
axis[2] = 1.0;
constexpr double angle = 0;
rotation.Set(axis, angle);
transform->SetRotation(rotation);

landmarkBasedTransformInitializer->SetTransform(transform);
landmarkBasedTransformInitializer->SetReferenceImage(casterfix->GetOutput());
landmarkBasedTransformInitializer->InitializeTransform();

registration->SetOptimizer(optimizer);
registration->SetFixedImage(casterfix->GetOutput());
registration->SetMovingImage(castermove->GetOutput());
registration->SetInitialTransform(transform);

using OptimizerScalesType = OptimizerType::ScalesType;
OptimizerScalesType optimizerScales(transform->GetNumberOfParameters());
const double translationScale = 1.0 / 1000.0;
optimizerScales[0] = 1.0;
optimizerScales[1] = 1.0;
optimizerScales[2] = 1.0;
optimizerScales[3] = translationScale;
optimizerScales[4] = translationScale;
optimizerScales[5] = translationScale;
optimizer->SetScales(optimizerScales);
optimizer->SetNumberOfIterations(100);
optimizer->SetLearningRate(0.5);
optimizer->SetMinimumStepLength(0.001);
optimizer->SetReturnBestParametersAndValue(true);

optimizer->SetRelaxationFactor(0.8);

auto observer = CommandIterationUpdatev4::New();
optimizer->AddObserver(itk::IterationEvent(), observer);

constexpr unsigned int numberOfLevels = 3;

RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel;
shrinkFactorsPerLevel.SetSize(3);
shrinkFactorsPerLevel[0] = 4;
shrinkFactorsPerLevel[1] = 2;
shrinkFactorsPerLevel[2] = 1;

RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel;
smoothingSigmasPerLevel.SetSize(3);
smoothingSigmasPerLevel[0] = 2;
smoothingSigmasPerLevel[0] = 1;
smoothingSigmasPerLevel[0] = 1;

registration->SetNumberOfLevels(numberOfLevels);
registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel);
registration->SetShrinkFactorsPerLevel(shrinkFactorsPerLevel);

RegistrationType::MetricSamplingStrategyEnum samplingStrategy =
	RegistrationType::MetricSamplingStrategyEnum::RANDOM;
double samplingPercentage = 0.2;

registration->SetMetricSamplingStrategy(samplingStrategy);
registration->SetMetricSamplingPercentage(samplingPercentage);
registration->MetricSamplingReinitializeSeed(121213);

try
{
	registration->Update();
	std::cout << "Optimizer stop condition: "
		<< registration->GetOptimizer()->GetStopConditionDescription()
		<< std::endl;
}
catch (const itk::ExceptionObject & err)
{
	std::cerr << "ExceptionObject caught !" << std::endl;
	std::cerr << err << std::endl;
}

```

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [October 20, 2023, 8:19pm UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/6 "2023-10-20T20:19:45Z")

</div>

There are extra calls that are not needed, but I do not see anything standing out that would cause an issue. Was the landmark-based initialization evaluated outside the broader registration?

---

<div class="post-metadata">

### Author: ![SeanHan](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/6f9a4e/32.png) [@SeanHan](https://discourse.itk.org/u/SeanHan)
#### Post date: [October 23, 2023, 7:16am UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/7 "2023-10-23T07:16:06Z")

</div>

I just don’t know whether this is the right process of registration based on landmark or not.

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)
#### Post date: [October 23, 2023, 2:32pm UTC](https://discourse.itk.org/t/are-there-any-instances-about-the-registration-of-3d-medical-image-by-landmark/6256/8 "2023-10-23T14:32:11Z")

</div>

Registering based on landmarks should be as simple as this:

> <https://github.com/KitwareMedical/HASI/blob/d58acf4cda836bdedd1b7531dddc8ca7b20b396a/src/hasi/mouse_femur_tibia_ct_morphometry.py#L80-L94>

The code in C++ should be only a little bit more verbose, but otherwise the same.
