ITK 2D图像刚性配准

开发环境:VS 2022,Windows 10,ITK5.3

使用数据为"D:\Windows\ITK-5.2.1\Examples\Data"下的BrainProtonDensitySliceBorder20.png和BrainProtonDensitySliceR10X13Y17.png
Fixed Image
Moving Image

1. 导入所需头文件

#include "itkImageRegistrationMethodv4.h" //包含配准方法
#include "itkTranslationTransform.h" //空间变换
#include "itkMeanSquaresImageToImageMetricv4.h" //损失函数
#include "itkRegularStepGradientDescentOptimizerv4.h"//优化算法
#include "itkImageFileReader.h"//读取图像
#include "itkImageFileWriter.h"//写入结果
#include "itkPNGImageIOFactory.h" //读取PNG图像所需
using namespace std;

2. 实例化所需对象

定义读取图像的维度和像素类型

constexpr unsigned int Dimension = 2;
using PixelType = float;

实例化对象

//参考和浮动图像的类型在实例化的时候需要指定
using FixedImageType = itk::Image<PixelType, Dimension>;
using MovingImageType = itk::Image<PixelType, Dimension>;
// 空间变换类型和维度
using TransformType = itk::TranslationTransform<double, Dimension>;
//优化算法处理数据的类型
using OptimizerType = itk::RegularStepGradientDescentOptimizerv4<double>;
//计算损失函数的对象,需要指定参考和浮动图像
using MetricType =
	itk::MeanSquaresImageToImageMetricv4<FixedImageType, MovingImageType>;
//配准方法实例化,需要指定参考和浮动图像
using RegistrationType = itk::
	ImageRegistrationMethodv4<FixedImageType, MovingImageType, TransformType>;

3.创建部分对象

通过New()创建,通过itk::SmartPointer赋值

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

4. 配置配准方法

将声明的部分对象赋值给配准方法(如优化器,损失函数)

registration->SetMetric(metric);
registration->SetOptimizer(optimizer);

5.配置损失函数

//配置之前需要用到插值方法,因此需要实例化和创建参考和浮动图像的插值对象
using FixedLinearInterpolatorType =
		itk::LinearInterpolateImageFunction<FixedImageType, double>;
using MovingLinearInterpolatorType =
	itk::LinearInterpolateImageFunction<MovingImageType, double>;
FixedLinearInterpolatorType::Pointer fixedInterpolator =
		FixedLinearInterpolatorType::New();
MovingLinearInterpolatorType::Pointer movingInterpolator =
	MovingLinearInterpolatorType::New();
metric->SetFixedInterpolator(fixedInterpolator);
metric->SetMovingInterpolator(movingInterpolator);

6. 读取图像并放入配准方法中

typedef itk::ImageFileReader< FixedImageType  >   FixedImageReaderType;
typedef itk::ImageFileReader< MovingImageType >   MovingImageReaderType;
FixedImageReaderType::Pointer   fixedImageReader = FixedImageReaderType::New();
MovingImageReaderType::Pointer  movingImageReader = MovingImageReaderType::New();
itk::PNGImageIOFactory::RegisterOneFactory();
fixedImageReader->SetFileName(R"(C:\Users\Richard\Desktop\BrainProtonDensitySliceBorder20.png)");
movingImageReader->SetFileName(R"(C:\Users\Richard\Desktop\BrainProtonDensitySliceR10X13Y17.png)");

registration->SetFixedImage(fixedImageReader->GetOutput());
registration->SetMovingImage(movingImageReader->GetOutput());

7.配置空间变换矩阵

TransformType::Pointer movingInitialTransform = TransformType::New();
TransformType::ParametersType initialParameters(
	movingInitialTransform->GetNumberOfParameters());
initialParameters[0] = 0.0; // Initial offset in mm along X
initialParameters[1] = 0.0; // Initial offset in mm along Y
movingInitialTransform->SetParameters(initialParameters);
registration->SetMovingInitialTransform(movingInitialTransform);
TransformType::Pointer identityTransform = TransformType::New();
identityTransform->SetIdentity();
registration->SetFixedInitialTransform(identityTransform);

8.配置优化器参数

optimizer->SetLearningRate(4);
optimizer->SetMinimumStepLength(0.001);
optimizer->SetRelaxationFactor(0.5);
optimizer->SetNumberOfIterations(200);
constexpr unsigned int numberOfLevels = 1;
RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel;
shrinkFactorsPerLevel.SetSize(1);
shrinkFactorsPerLevel[0] = 1;
RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel;
smoothingSigmasPerLevel.SetSize(1);
smoothingSigmasPerLevel[0] = 0;
registration->SetNumberOfLevels(numberOfLevels);
registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel);

9. 开始配准并输出最终结果

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;
		return EXIT_FAILURE;
	}
	TransformType::ConstPointer transform = registration->GetTransform();
	TransformType::ParametersType finalParameters = transform->GetParameters();
	const double TranslationAlongX = finalParameters[0];
	const double TranslationAlongY = finalParameters[1];
	const unsigned int numberOfIterations = optimizer->GetCurrentIteration();
	const double bestValue = optimizer->GetValue();
	cout << bestValue<<endl;
	cout << TranslationAlongX << endl;
	cout << TranslationAlongY << endl;
}

输出结果

##完整代码


#include "itkImageRegistrationMethodv4.h"
#include "itkTranslationTransform.h"
#include "itkMeanSquaresImageToImageMetricv4.h"
#include "itkRegularStepGradientDescentOptimizerv4.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkPNGImageIOFactory.h"
using namespace std;
int main()
{
	constexpr unsigned int Dimension = 2;
	using PixelType = float;
	using FixedImageType = itk::Image<PixelType, Dimension>;
	using MovingImageType = itk::Image<PixelType, Dimension>;
	using TransformType = itk::TranslationTransform<double, Dimension>;
	using OptimizerType = itk::RegularStepGradientDescentOptimizerv4<double>;
	using MetricType =
		itk::MeanSquaresImageToImageMetricv4<FixedImageType, MovingImageType>;
	using RegistrationType = itk::
		ImageRegistrationMethodv4<FixedImageType, MovingImageType, TransformType>;

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

	registration->SetMetric(metric);
	registration->SetOptimizer(optimizer);
	using FixedLinearInterpolatorType =
		itk::LinearInterpolateImageFunction<FixedImageType, double>;
	using MovingLinearInterpolatorType =
		itk::LinearInterpolateImageFunction<MovingImageType, double>;
	FixedLinearInterpolatorType::Pointer fixedInterpolator =
		FixedLinearInterpolatorType::New();
	MovingLinearInterpolatorType::Pointer movingInterpolator =
		MovingLinearInterpolatorType::New();
	metric->SetFixedInterpolator(fixedInterpolator);
	metric->SetMovingInterpolator(movingInterpolator);
	typedef itk::ImageFileReader< FixedImageType  >   FixedImageReaderType;
	typedef itk::ImageFileReader< MovingImageType >   MovingImageReaderType;
	FixedImageReaderType::Pointer   fixedImageReader = FixedImageReaderType::New();
	MovingImageReaderType::Pointer  movingImageReader = MovingImageReaderType::New();
	itk::PNGImageIOFactory::RegisterOneFactory();
	fixedImageReader->SetFileName(R"(C:\Users\Richard\Desktop\BrainProtonDensitySliceBorder20.png)");
	movingImageReader->SetFileName(R"(C:\Users\Richard\Desktop\BrainProtonDensitySliceR10X13Y17.png)");
	registration->SetFixedImage(fixedImageReader->GetOutput());
	registration->SetMovingImage(movingImageReader->GetOutput());
	TransformType::Pointer movingInitialTransform = TransformType::New();
	TransformType::ParametersType initialParameters(
		movingInitialTransform->GetNumberOfParameters());
	initialParameters[0] = 0.0; // Initial offset in mm along X
	initialParameters[1] = 0.0; // Initial offset in mm along Y
	
	movingInitialTransform->SetParameters(initialParameters);
	registration->SetMovingInitialTransform(movingInitialTransform);
	TransformType::Pointer identityTransform = TransformType::New();
	identityTransform->SetIdentity();
	registration->SetFixedInitialTransform(identityTransform);
	optimizer->SetLearningRate(4);
	optimizer->SetMinimumStepLength(0.001);
	optimizer->SetRelaxationFactor(0.5);
	optimizer->SetNumberOfIterations(200);
	constexpr unsigned int numberOfLevels = 1;
	RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel;
	shrinkFactorsPerLevel.SetSize(1);
	shrinkFactorsPerLevel[0] = 1;
	RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel;
	smoothingSigmasPerLevel.SetSize(1);
	smoothingSigmasPerLevel[0] = 0;
	registration->SetNumberOfLevels(numberOfLevels);
	registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel);
	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;
		return EXIT_FAILURE;
	}
	TransformType::ConstPointer transform = registration->GetTransform();
	TransformType::ParametersType finalParameters = transform->GetParameters();
	const double TranslationAlongX = finalParameters[0];
	const double TranslationAlongY = finalParameters[1];
	const unsigned int numberOfIterations = optimizer->GetCurrentIteration();
	const double bestValue = optimizer->GetValue();
	cout << bestValue<<endl;
	cout << TranslationAlongX << endl;
	cout << TranslationAlongY << endl;
}

猜你喜欢

转载自blog.csdn.net/Gastby_/article/details/126732551
今日推荐