elastix 5.2.0,参考官方文档可知我们需要一个.txt参数文件启动配准操作,例如将本地MRI影像配准到MNI标准空间中。
(1)基于Elastix配准
using namespace elastix;
typedef ELASTIX::ParameterMapType RegistrationParametersType;
typedef itk::ParameterFileParser ParserType;
// Create parser for transform parameters text file.
ParserType::Pointer file_parser = ParserType::New();
// Try parsing transform parameters text file.
file_parser->SetParameterFileName("..."); // parametersaffine parametersBspline
try
{
file_parser->ReadParameterFile();
}
catch (itk::ExceptionObject& e)
{
std::cout << e.what() << std::endl;
// Do some error handling!
}
// Retrieve parameter settings as map.
RegistrationParametersType parameters = file_parser->GetParameterMap();
printf("Successful!");
// 参数定义
const char* fixedImagePath = "..."; // MNI模板路径
const char* movingImagePath = "..."; // 用户MRI路径
const char* outputImagePath = "...";// 配准后图像输出路径
// 图像类型定义
constexpr unsigned int Dimension = 3;
using PixelType = float;
using FixedImageType = itk::Image<PixelType, Dimension>;
using MovingImageType = itk::Image<PixelType, Dimension>;
using FixedReaderType = itk::ImageFileReader<FixedImageType>;
using MovingReaderType = itk::ImageFileReader<MovingImageType>;
using ImageIOType = itk::NiftiImageIO;
// 读图
FixedReaderType::Pointer FixedReader = FixedReaderType::New();
ImageIOType::Pointer niftiIO = ImageIOType::New();
FixedReader->SetImageIO(niftiIO);
FixedReader->SetFileName(fixedImagePath);
FixedReader->Update();
FixedImageType::Pointer fixedImage = FixedReader->GetOutput();
MovingReaderType::Pointer MovingReader = MovingReaderType::New();
MovingReader->SetImageIO(niftiIO);
MovingReader->SetFileName(movingImagePath);
MovingReader->Update();
MovingImageType::Pointer movingImage = MovingReader->GetOutput();
// 创建参数映射
elastix::ELASTIX::ParameterMapType params;
// 配准
elastix:: ELASTIX elastix;
int error = 0;
try
{
error = elastix.RegisterImages(
static_cast<typename itk::DataObject::Pointer>(fixedImage.GetPointer()),
static_cast<typename itk::DataObject::Pointer>(movingImage.GetPointer()),
parameters, // Parameter map read in previous code
".", // 输出目录(当前目录)
false, // 禁用日志文件
true, // 控制台输出
nullptr, // 固定图像掩膜
nullptr // 移动图像掩膜
);
}
catch (itk::ExceptionObject& e) {
std::cerr << "Registration error: " << e.what() << std::endl;
}
if (error != 0) {
std::cerr << "Registration failed with error code: " << error << std::endl;
}
// 应用变换到移动图像
using ResampleFilterType = itk::ResampleImageFilter<MovingImageType, FixedImageType>;
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
// 获取结果图像
using RegistredImageType = itk::Image<PixelType, Dimension>;
if (elastix.GetResultImage().IsNotNull()) {
RegistredImageType* resultImage = static_cast<RegistredImageType*>(
elastix.GetResultImage().GetPointer()
);
// 应用变换到移动图像
using ResampleFilterType = itk::ResampleImageFilter<MovingImageType, FixedImageType>;
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
// 写入配准后的图像
// 配置NIFTI头
using WriterType = itk::ImageFileWriter<RegistredImageType>;
WriterType::Pointer writer = WriterType::New();
writer->SetImageIO(niftiIO);
writer->SetFileName(outputImagePath);
writer->SetInput(resultImage);
writer->Update();
}
else {
cout << "No image written!" << endl;
}
// 获取变换参数
elastix::ELASTIX::ParameterMapListType transformParams =
elastix.GetTransformParameterMapList();
// 可选的变换参数处理...
(2)获取参数文件
参数文件可以通过3D Slicer中的Elastix参数文件路径获取,里面包含了刚体变换、仿射变换、非刚性BSpline变换等,可以学习。如下图所示:
注意!如果要输出图像,需要在参数文件中检查如下设置是否存在并且正确
(WriteResultImage "true")
(ResultImagePixelType "float")
后者需要和打开影像的格式一样(这里代码我为float)