ITK配准:基于DeformationFieldTransform的配准

本文采用DeformationFieldTransform进行图像的配准。

注意在ITKv4中 DeformationFieldTransform被命名为 DisplacementFieldTransform。

1、DeformationFieldTransform提供一个进行局部、稠密和高纬度的变换场,也称为位移场。该位移场存储着向量的 移位,向量的维度记为N。在给定 的输入点上面增加一个位移以实现变换!(Transformation is performed at a given point by adding the displacement at that point to the input point.)

T(x, p), x为所在位置, p 为在x点上面的局部参数( the local parameter at position x)。 For a 2D example:

x = (x0, x1), p = (p0, p1)

then T(x, p) is defined as:

T(x, p) = (T0, T1) = (x0+p0, x1+p1)

变换期间, 超出边界的输入点返回的是0位移(zero displacement)

2、位移场是通过一张itkImage来定义的,所以需要在使用之前进行设置,通过 SetDisplacementField来实现设置。 该图像和输入图像、输出图像的维度是一致的。此外,需要对位移场图像设置一个类型 VectorInterpolateImageFunction 的插值器。默认情况下为 VectorLinearInterpolateImageFunction ,也可以通过 SetInterpolator进行重载。

实现过程与之前所撰写的两篇文章为互补。在刚性配准该文章中,并不是就有位移场进行配准的,而基于手动设置配准点的图像配准则是与本文相同的思路;但是在设置滤波器与插值器进行关联时,本文所采用的是刚性配准文章中所用的ResampleFilterType,而不是“基于手动设置配准点的配准”中的WarpImageFilterType所定义的warpImageFilter。


代码如下:


#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkImage.h"
#include "itkVector.h"
#if ITK_VERSION_MAJOR < 4
#include "itkDeformationFieldTransform.h"
#include "itkDeformationFieldSource.h"
#else
#include "itkVectorLinearInterpolateImageFunction.h"
#include "itkDisplacementFieldTransform.h"
#include "itkLandmarkDisplacementFieldSource.h"
#endif
#include "itkResampleImageFilter.h"

const     unsigned int   Dimension = 2;
typedef   unsigned char  PixelType;
typedef   itk::Image< PixelType, Dimension > ImageType;

static void CreateFixedImage(ImageType::Pointer image);
static void CreateMovingImage(ImageType::Pointer image);

int main(int argc, char * argv[])
{
	
#if ITK_VERSION_MAJOR < 4
	typedef   float           VectorComponentType;
#else
	typedef   double          VectorComponentType;
#endif
	typedef   itk::Vector< VectorComponentType, Dimension >    VectorType;
	typedef   itk::Image< VectorType,  Dimension >   DeformationFieldType;
	//创建图像
	ImageType::Pointer fixedImage = ImageType::New();
	CreateFixedImage(fixedImage);

	ImageType::Pointer movingImage = ImageType::New();
	CreateMovingImage(movingImage);
	//定义位移场的场源类型
#if ITK_VERSION_MAJOR < 4
	typedef itk::DeformationFieldSource<DeformationFieldType>  DeformationFieldSourceType;
#else
	typedef itk::LandmarkDisplacementFieldSource<DeformationFieldType>  DeformationFieldSourceType;
#endif
	DeformationFieldSourceType::Pointer deformationFieldSource = DeformationFieldSourceType::New();
	deformationFieldSource->SetOutputSpacing( fixedImage->GetSpacing() );
	deformationFieldSource->SetOutputOrigin(  fixedImage->GetOrigin() );
	deformationFieldSource->SetOutputRegion(  fixedImage->GetLargestPossibleRegion() );
	deformationFieldSource->SetOutputDirection( fixedImage->GetDirection() );

	//  Create source and target landmarks.
	typedef DeformationFieldSourceType::LandmarkContainerPointer   LandmarkContainerPointer;
	typedef DeformationFieldSourceType::LandmarkContainer          LandmarkContainerType;
	typedef DeformationFieldSourceType::LandmarkPointType          LandmarkPointType;

	LandmarkContainerType::Pointer sourceLandmarks = LandmarkContainerType::New();
	LandmarkContainerType::Pointer targetLandmarks = LandmarkContainerType::New();

	LandmarkPointType sourcePoint;
	LandmarkPointType targetPoint;
	//添加地标点
	sourcePoint[0] = 40;
	sourcePoint[1] = 40;
	targetPoint[0] = 20;
	targetPoint[1] = 20;
	sourceLandmarks->InsertElement( 0, sourcePoint );
	targetLandmarks->InsertElement( 0, targetPoint );

	sourcePoint[0] = 40;
	sourcePoint[1] = 60;
	targetPoint[0] = 20;
	targetPoint[1] = 80;
	sourceLandmarks->InsertElement( 1, sourcePoint );
	targetLandmarks->InsertElement( 1, targetPoint );

	sourcePoint[0] = 60;
	sourcePoint[1] = 40;
	targetPoint[0] = 80;
	targetPoint[1] = 20;
	sourceLandmarks->InsertElement( 2, sourcePoint );
	targetLandmarks->InsertElement( 2, targetPoint );

	sourcePoint[0] = 60;
	sourcePoint[1] = 60;
	targetPoint[0] = 80;
	targetPoint[1] = 80;
	sourceLandmarks->InsertElement( 3, sourcePoint );
	targetLandmarks->InsertElement( 3, targetPoint );
	//为位移场场源设置地标点
	deformationFieldSource->SetSourceLandmarks( sourceLandmarks.GetPointer() );
	deformationFieldSource->SetTargetLandmarks( targetLandmarks.GetPointer() );
	deformationFieldSource->UpdateLargestPossibleRegion();
	//将设置好的位移场场源进行保存
	// Write the deformation field
	{
		typedef itk::ImageFileWriter<  DeformationFieldType  > WriterType;
		WriterType::Pointer writer = WriterType::New();
		writer->SetInput (  deformationFieldSource->GetOutput() );
		writer->SetFileName( "deformation.mhd" );
		writer->Update();
	}
	//设置位移场的变换类型
#if ITK_VERSION_MAJOR < 4
	typedef itk::DeformationFieldTransform<VectorComponentType, 2>  DeformationFieldTransformType;
#else
	typedef itk::DisplacementFieldTransform<VectorComponentType, 2>  DeformationFieldTransformType;
#endif
	DeformationFieldTransformType::Pointer deformationFieldTransform = DeformationFieldTransformType::New();
	//设置位移场的变换
#if ITK_VERSION_MAJOR < 4
	deformationFieldTransform->SetDeformationField( deformationFieldSource->GetOutput() );
#else
	deformationFieldTransform->SetDisplacementField( deformationFieldSource->GetOutput() );//设置位移场,将场源与其关联
#endif  
	typedef itk::ResampleImageFilter<ImageType, ImageType, VectorComponentType >    ResampleFilterType;
	ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
	resampleFilter->SetInput( movingImage );
	resampleFilter->SetTransform( deformationFieldTransform );
	resampleFilter->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
	resampleFilter->SetOutputOrigin(  fixedImage->GetOrigin() );
	resampleFilter->SetOutputSpacing( fixedImage->GetSpacing() );
	resampleFilter->SetOutputDirection( fixedImage->GetDirection() );
	resampleFilter->SetDefaultPixelValue( 200 );
	resampleFilter->GetOutput();

	// Write the output
	typedef itk::ImageFileWriter<  ImageType  > WriterType;
	WriterType::Pointer writer = WriterType::New();
	writer->SetInput (  resampleFilter->GetOutput() );
	writer->SetFileName( "output.png" );
	writer->Update();

	return EXIT_SUCCESS;
}

void CreateFixedImage(ImageType::Pointer image)
{
	// Create a black image with a white square
	ImageType::IndexType start;
	start.Fill(0);

	ImageType::SizeType size;
	size.Fill(100);

	ImageType::RegionType region;
	region.SetSize(size);
	region.SetIndex(start);

	image->SetRegions(region);
	image->Allocate();
	image->FillBuffer(0);

	itk::ImageRegionIterator<ImageType> imageIterator(image,region);

	while(!imageIterator.IsAtEnd())
	{
		if(imageIterator.GetIndex()[0] > 40 && imageIterator.GetIndex()[0] < 60 &&
			imageIterator.GetIndex()[1] > 40 && imageIterator.GetIndex()[1] < 60)
		{
			imageIterator.Set(255);
		}
		++imageIterator;
	}

	// Write the deformation field
	typedef itk::ImageFileWriter<  ImageType  > WriterType;
	WriterType::Pointer writer = WriterType::New();
	writer->SetInput (  image );
	writer->SetFileName( "fixed.png" );
	writer->Update();
}


void CreateMovingImage(ImageType::Pointer image)
{
	// Create a black image with a white square
	ImageType::IndexType start;
	start.Fill(0);

	ImageType::SizeType size;
	size.Fill(100);

	ImageType::RegionType region;
	region.SetSize(size);
	region.SetIndex(start);

	image->SetRegions(region);
	image->Allocate();
	image->FillBuffer(0);

	itk::ImageRegionIterator<ImageType> imageIterator(image,region);

	while(!imageIterator.IsAtEnd())
	{
		if(imageIterator.GetIndex()[0] > 20 && imageIterator.GetIndex()[0] < 80 &&
			imageIterator.GetIndex()[1] > 20 && imageIterator.GetIndex()[1] < 80)
		{
			imageIterator.Set(100);
		}
		++imageIterator;
	}

	// Write the deformation field
	typedef itk::ImageFileWriter<  ImageType  > WriterType;
	WriterType::Pointer writer = WriterType::New();
	writer->SetInput (  image );
	writer->SetFileName( "moving.png" );
	writer->Update();
}

结果图如下所示:


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SimpleITK是一个用于图像处理和分析的开源软件库。它提供了一个简单的界面,用于进行图像,即将不同图像或不同时间点的图像对齐。 SimpleITK功能非常强大和灵活。它可以对不同类型的图像进行,包括二维和三维图像,以及不同的图像模态(如MRI、CT等)。的目标是找到最佳的转换参数,使得两个或多个图像的空间位置最为接近。 SimpleITK提供了多种方法,包括刚性和非刚性。刚性是通过旋转、平移和缩放等刚性变换来对图像进行对齐。非刚性则允许更复杂的变换,如弯曲、拉伸和扭曲。 使用SimpleITK进行非常简单。首先,我们需要载入要的图像,并将其转换为SimpleITK图像对象。然后,选择适当的方法,并设置一些参数,如迭代次数和步长等。最后,调用函数,将原始图像和参考图像作为输入,并得到后的图像。结果可以通过将图像保存到文件或在可视化工具中显示来进行验证。 SimpleITK功能在医学影像领域广泛应用。它可以用于病灶检测、手术导航、疾病诊断等任务。可以提高确性,使得不同时间点的图像能够更好地比较,帮助医生做出更可靠的诊断和治疗决策。 总之,SimpleITK提供了一种简单而强大的方法来进行图像。它使得变得容易,并且具有广泛的适用性。无论是医学影像还是其他领域的图像任务,SimpleITK都是一个值得使用的工具。 ### 回答2: SimpleITK是一个用于医学图像处理的简单、快速且强大的开源工具包。(registration)是SimpleITK中一个重要的功能,用于对医学图像进行对齐、校正或匹,以帮助研究人员更好地分析和比较不同图像。下面将详细介绍SimpleITK的主要步骤和功能。 第一步是加载需要进行的医学图像。SimpleITK可以读取常见的医学图像格式,如DICOM、NIFTI等,使得数据的获取变得十分简单。 第二步是选择适合的方法。SimpleITK提供了多种算法,包括刚体(rigid)、非刚体(affine)和形变(BSpline)等。根据实际需求,选择合适的方法进行。 第三步是定义图像对齐的度量标。SimpleITK提供了各种度量标,如均方差(MeanSquares)、互信息(MutualInformation)和精度(MattesMutualInformation)等。通过度量标,可以评估结果的好坏,并根据实际需求进行调整。 第四步是设置优化器和迭代次数。SimpleITK提供了多种优化器选择,如最小化梯度下降(GradientDescent)、自适应学习率(AdaptiveStochasticGradientDescent)等,同时还可以设置迭代次数来控制的精度和速度。 第五步是执行操作。通过调用SimpleITK中的函数,将需要的图像和以上参数传入进行操作。完成后,可获得后的图像结果。 最后一步是保存结果。SimpleITK支持将后的图像保存到磁盘上,以便后续的分析和使用。 SimpleITK功能提供了一种快速、简单且有效的方法来对医学图像进行对齐和校正操作。通过使用SimpleITK,能够方便地实现医学图像的各个步骤,并根据实际需求进行调整和优化,帮助研究人员更好地利用医学图像进行研究和分析。 ### 回答3: SimpleITK是一个用于医学图像处理的工具包,其中的功能对于医学图像的分析和处理非常重要。 首先,是一种将不同图像或不同时间点的同一图像对齐的技术。在医学领域,图像可以用于将来自不同患者的医学图像对齐,以便进行比较和分析。此外,在手术前和手术后的图像对齐,可以用于手术规划和评估手术的效果。 SimpleITK中的功能可以通过一系列的步骤来实现。首先,我们需要加载要对齐的图像,并将其转为SimpleITK的图像格式。然后,我们可以选择合适的算法,比如最小均方差(Mean Squares)或最小单元(MinimumUnit),并设置相应的参数。 接下来,我们可以使用SimpleITK提供的不同方法进行图像。例如,使用ElasticTransform可以通过估计图像变形来对齐图像,而使用AffineTransform可以利用刚性变换来对齐图像。 在完成后,我们可以进一步评估确性。这可以通过计算对齐图像之间的相似性度量,比如均方根误差(RMSE)或互信息(Mutual Information)来进行。 最后,我们可以保存后的图像,并进行后续的处理和分析。 简而言之,SimpleITK中的功能提供了一种方便且高效的方法来对医学图像进行对齐。它具有多种算法和参数可以选择,并提供了评估和保存结果的功能。通过使用SimpleITK功能,我们可以更好地利用医学图像进行研究和临床应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值