# Gradient magnitude (0) in registration.

**URL:** https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266
**Category:** Beginner Questions
**Created:** [September 26, 2019, 1:10am UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266 "2019-09-26T01:10:18Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![spic](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/ea5d25/32.png) [@spic](https://discourse.itk.org/u/spic)
#### Post date: [September 26, 2019, 1:10am UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/1 "2019-09-26T01:10:18Z")

</div>

I am trying to register 2 3D volumes. I know that there is significant (rigid) shift between the two images, but registration keep stopping after first iteration. The gradient value is zero at the first iteration! The metric value is however non-zero.  
The core of the code is as shown below. After a whole day to debugging my guess is that I am missing setting something correctly, but can’t figure out what it is!  
Is there any obvious mistake that could lead to this problem?

```
    using FixedImageType = ImageType;
using MovingImageType = ImageType;
using FixedImageReaderType = itk::ImageFileReader< FixedImageType >;
using MovingImageReaderType = itk::ImageFileReader< MovingImageType >;
using InternalPixelType = float;
using InternalImageType = itk::Image< InternalPixelType, ImageType::ImageDimension >;

// read input images
typename FixedImageReaderType::Pointer fixedImageReader = FixedImageReaderType::New();
typename MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();

fixedImageReader->SetFileName( filename1 );
movingImageReader->SetFileName( filename2 );
std::cout << "Setup input file readers."<<std::endl;
try
{
    fixedImageReader->Update();
    movingImageReader->Update();
}
catch (itk::ExceptionObject & error)
{
    std::cerr << "Error while reading images: " << error << std::endl;
    return EXIT_FAILURE;
}

FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
MovingImageType::Pointer movingImage = movingImageReader->GetOutput();

// Setup registration framework...
using TransformType = itk::Euler3DTransform< double >;//, ImageType::ImageDimension >;
using OptimizerType = itk::RegularStepGradientDescentOptimizerv4<double>;
using InterpolatorType = itk::LinearInterpolateImageFunction< InternalImageType, double>;
using RegistrationType = itk::ImageRegistrationMethodv4< InternalImageType, InternalImageType >;

//using MetricType = itk::MattesMutualInformationImageToImageMetricv4< InternalImageType, InternalImageType >;
using MetricType = itk::MeanSquaresImageToImageMetricv4< InternalImageType, InternalImageType >;

typename TransformType::Pointer transform = TransformType::New();
typename OptimizerType::Pointer optimizer = OptimizerType::New();
typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
typename RegistrationType::Pointer registration = RegistrationType::New();
typename MetricType::Pointer metric = MetricType::New();

registration->SetOptimizer(optimizer);
registration->SetMetric( metric );
registration->SetFixedImage( fixedImageReader->GetOutput() );
registration->SetMovingImage( movingImageReader->GetOutput() );
registration->SetObjectName("Registration Method");

using ParametersType = OptimizerType::ParametersType;
TransformType::NumberOfParametersType numberOfParameters = transform->GetNumberOfParameters();

using TransformInitializerType = itk::CenteredTransformInitializer<TransformType, FixedImageType, MovingImageType>;
TransformInitializerType::Pointer initializer = TransformInitializerType::New();

initializer->SetTransform(transform);
initializer->SetFixedImage(fixedImageReader->GetOutput());
initializer->SetMovingImage(movingImageReader->GetOutput());
initializer->GeometryOn();
initializer->InitializeTransform();

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[4] = translationScale;

optimizer->SetScales(optimizerScales);

registration->SetMovingInitialTransform( transform );

typename TransformType::Pointer identityTransform = TransformType::New();
identityTransform->SetIdentity();
registration->SetFixedInitialTransform( identityTransform );

std::cout << "Setup registration method"<<std::endl;

constexpr unsigned int numberOfLevels1 = 1;

RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel1;
shrinkFactorsPerLevel1.SetSize(numberOfLevels1);
shrinkFactorsPerLevel1[0] = 3;

RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel1;
smoothingSigmasPerLevel1.SetSize(numberOfLevels1);
smoothingSigmasPerLevel1[0] = 2;

registration->SetNumberOfLevels(numberOfLevels1);
registration->SetShrinkFactorsPerLevel(shrinkFactorsPerLevel1);
registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel1);

registration->SetMetricSamplingPercentage(0.5);
registration->MetricSamplingReinitializeSeed(121212);

using MaskObjectType = itk::ImageMaskSpatialObject< FixedImageType::ImageDimension >;
MaskObjectType::Pointer fixedMaskObject = MaskObjectType::New();
MaskObjectType::Pointer movingMaskObject = MaskObjectType::New();

using FixedThresholdFilterType = itk::BinaryThresholdImageFilter<FixedImageType, MaskObjectType::ImageType >;
FixedThresholdFilterType::Pointer fixedImageThresholdFilter = FixedThresholdFilterType::New();
fixedImageThresholdFilter->SetInput(fixedImageReader->GetOutput());
fixedImageThresholdFilter->SetOutsideValue(0);
fixedImageThresholdFilter->SetInsideValue( itk::NumericTraits< MaskObjectType::ImageType::PixelType>::max() );
fixedImageThresholdFilter->SetLowerThreshold(10);
fixedImageThresholdFilter->SetUpperThreshold(4098);

using MovingThresholdFilterType = itk::BinaryThresholdImageFilter<MovingImageType, MaskObjectType::ImageType >;
MovingThresholdFilterType::Pointer movingImageThresholdFilter = MovingThresholdFilterType::New();
movingImageThresholdFilter->SetInput(movingImageReader->GetOutput());
movingImageThresholdFilter->SetOutsideValue(0);
movingImageThresholdFilter->SetInsideValue( itk::NumericTraits< MaskObjectType::ImageType::PixelType >::max() );
movingImageThresholdFilter->SetLowerThreshold(10);
movingImageThresholdFilter->SetUpperThreshold(4098);

fixedImageThresholdFilter->Update();
fixedMaskObject->SetImage( fixedImageThresholdFilter->GetOutput() );
movingImageThresholdFilter->Update();
movingMaskObject->SetImage( movingImageThresholdFilter->GetOutput() );
//output of threshold filter looks OK
fixedMaskObject->Update();
movingMaskObject->Update();
// not sure how to verify if this object is generated correctly
metric->SetFixedImageMask(fixedMaskObject);
metric->SetMovingImageMask(movingMaskObject);

optimizer->SetNumberOfIterations( 200 );
optimizer->SetRelaxationFactor(0.5);
optimizer->SetLearningRate( 0.15 );
optimizer->SetMinimumStepLength(0.00001);
optimizer->SetGradientMagnitudeTolerance(0.0000000001);

std::cout << "Setup optimizer settings" << std::endl;

CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
optimizer->AddObserver( itk::IterationEvent(), observer );

using TranslationCommandType = RegistrationInterfaceCommand<RegistrationType>;
TranslationCommandType::Pointer command1 = TranslationCommandType::New();
registration->AddObserver(itk::MultiResolutionIterationEvent(), command1);

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

---

<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: [September 26, 2019, 1:51pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/2 "2019-09-26T13:51:03Z")

</div>

Maybe examine `transform` before and after `initializer->InitializeTransform();`, see if the initialization does what you expect.

`optimizer->SetMinimumStepLength(0.00001);` is a pretty small step. What is the maximum/initial step size? A too small optimizer step might be causing no change to the metric.

---

<div class="post-metadata">

### Author: ![spic](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/ea5d25/32.png) [@spic](https://discourse.itk.org/u/spic)
#### Post date: [September 26, 2019, 2:19pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/3 "2019-09-26T14:19:25Z")

</div>

The transform initialization looks alright…

> Before initializationEuler3DTransform (0x55c99a287de0)  
> RTTI typeinfo: itk::Euler3DTransform  
> Reference Count: 3  
> Modified Time: 442  
> Debug: Off  
> Object Name:  
> Observers:  
> none  
> Matrix:  
> 1 0 0  
> 0 1 0  
> 0 0 1  
> Offset: [0, 0, 0]  
> Center: [0, 0, 0]  
> Translation: [0, 0, 0]  
> Inverse:  
> 1 0 0  
> 0 1 0  
> 0 0 1  
> Singular: 0  
> Euler’s angles: AngleX=0 AngleY=0 AngleZ=0  
> m\_ComputeZYX = 0
> 
> After initializationEuler3DTransform (0x55c99a287de0)  
> RTTI typeinfo: itk::Euler3DTransform  
> Reference Count: 3  
> Modified Time: 804  
> Debug: Off  
> Object Name:  
> Observers:  
> none  
> Matrix:  
> 1 0 0  
> 0 1 0  
> 0 0 1  
> Offset: [0, 0, 0]  
> Center: [159.5, 159.5, 74.5]  
> Translation: [0, 0, 0]  
> Inverse:  
> 1 0 0  
> 0 1 0  
> 0 0 1  
> Singular: 0  
> Euler’s angles: AngleX=0 AngleY=0 AngleZ=0  
> m\_ComputeZYX = 0

changing miminumsteplength (to 1) doesn’t seem to help…

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [September 26, 2019, 3:02pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/4 "2019-09-26T15:02:33Z")

</div>

You might want to try a [parameter scales estimator](https://itk.org/Doxygen/html/classitk_1_1RegistrationParameterScalesFromIndexShift.html) like done in this example:  
[https://itk.org/Doxygen/html/Examples\_2RegistrationITKv4\_2ImageRegistration1\_8cxx-example.html](https://itk.org/Doxygen/html/Examples_2RegistrationITKv4_2ImageRegistration1_8cxx-example.html)

---

<div class="post-metadata">

### Author: ![spic](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/ea5d25/32.png) [@spic](https://discourse.itk.org/u/spic)
#### Post date: [September 26, 2019, 10:54pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/5 "2019-09-26T22:54:49Z")

</div>

Scalling doesn’t seem to help.

---

<div class="post-metadata">

### Author: ![dwml](https://discourse.itk.org/user_avatar/discourse.itk.org/dwml/32/3045_2.png) [@dwml](https://discourse.itk.org/u/dwml)
#### Post date: [November 15, 2022, 3:30pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/6 "2022-11-15T15:30:34Z")

</div>

I ran into this thread when googling the same problem. After a while I figured out what the problem was, hence I’m posting to help anyone running into this thread. You have to give Euler3DTransformType as an input to the ImageRegistrationMethodv4 template. So it should become something like:

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

```

---

<div class="post-metadata">

### Author: ![suzume](https://discourse.itk.org/letter_avatar_proxy/v4/letter/s/6a8cbe/32.png) [@suzume](https://discourse.itk.org/u/suzume)
#### Post date: [January 14, 2023, 1:30pm UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/7 "2023-01-14T13:30:08Z")

</div>

Hi @dwml , I also met this problem. And the registrationmethod is [itk::MultiResolutionImageRegistrationMethod\< TFixedImage, TMovingImage \>] and there is no need to set TransformType in the definition. How can I solve the Gradient magnitude (0) in registration?

---

<div class="post-metadata">

### Author: ![dwml](https://discourse.itk.org/user_avatar/discourse.itk.org/dwml/32/3045_2.png) [@dwml](https://discourse.itk.org/u/dwml)
#### Post date: [January 17, 2023, 8:24am UTC](https://discourse.itk.org/t/gradient-magnitude-0-in-registration/2266/8 "2023-01-17T08:24:38Z")

</div>

Hi @suzume, these problems might not be related, so I’m not sure I can help. I think you get the best help if you create a separate thread/question and post all your code there. You can tag me in the question and I can try to help. Best, Dirk
