3D Pointset to Pointset registration issue

Hi everyone,

I’m trying to make this example work with 3D pointsets.
I’m using the same methods as the example (AffineTransform, JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4, RegistrationParameterScalesFromPhysicalShift and GradientDescentOptimizerv4)

However, it seems like the optimization doesn’t converge towards a reasonable solution. I would appreciate any thoughts or ideas about what could be causing this issue.

Here are my input data : fix in blue, moving in yellow

And the output : fix in blue, registered moving data in red

The inputs I have are vtkPolyData, so I first create an itk pointset from the polydata using this simple method:

vtkPoints* points = polyData->GetPoints();
PointSetType::Pointer mesh = PointSetType::New();
mesh->Initialize();
for (unsigned int i = 0; i < points->GetNumberOfPoints(); ++i) {
	mesh->SetPoint(i, points->GetPoint(i));
}	

The parameters for the metric:

using PointSetMetricType = itk::JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4<PointSetType>;
PointSetMetricType::Pointer metric = PointSetMetricType::New();
metric->SetFixedPointSet(fixedPoints);
metric->SetMovingPointSet(movingPoints);
metric->SetMovingTransform(transform);
metric->SetPointSetSigma(1.0);
metric->SetUseAnisotropicCovariances(false);
metric->SetEvaluationKNeighborhood(50); 
metric->SetCovarianceKNeighborhood(5); 
metric->SetKernelSigma(10.0); 
metric->SetAlpha(1.1);
metric->Initialize();

And for the optimizer:

using OptimizerType = itk::GradientDescentOptimizerv4;
OptimizerType::Pointer optimizer = OptimizerType::New();
optimizer->SetMetric(metric);
optimizer->SetNumberOfIterations(10);
optimizer->SetScalesEstimator(shiftScaleEstimator);
optimizer->SetMaximumStepSizeInPhysicalUnits(3.0);
optimizer->SetConvergenceWindowSize(10);
optimizer->StartOptimization();

Maybe @Pranjal_Sahu has a comment?

Can you please print the metric values after each iteration also ?

def print_iteration():
    print( f"It: {optimizer.GetCurrentIteration()}"
            f" metric value: {optimizer.GetCurrentMetricValue():.6f} ")

optimizer.AddObserver(itk.IterationEvent(), print_iteration)

Do the values decrease with each iteration ?
Also, you can try this example: Register Two Point Sets — v5.3.0

1 Like

Thanks for the insight, I should have thought of doing that.
The metric is jumping around, so I’m guessing this has to do with the learning rate or the scale estimator maybe?

It: 0 metric value: -0.00289889
It: 1 metric value: -0.00346599
It: 2 metric value: -0.00335903
It: 3 metric value: -0.00317761
It: 4 metric value: -0.00172806
It: 5 metric value: -0.00258818
It: 6 metric value: -0.00177315
It: 7 metric value: -0.00245881
It: 8 metric value: -0.00201539

Yes, you can try changing some hyperparameters (learning rate, number of iterations, etc.) and observe the output.

Thank you for your help, it was indeed a hyperparameter problem.
It works when using a fixed learning rate with optimizer->SetLearningRate().

But when trying to estimate the learning rate with the optimizer->SetDoEstimateLearningRateAtEachIteration(); and optimizer->SetDoEstimateLearningRateOnce(); methods, the optimizer doesn’t converge.

1 Like