ITK配准:基于手动设置配准点的图像配准

本例子是通过手动设置定标点对待配准图像进行移动,使其与参考图像配准!

本文是基于位移场将图像进行wrap操作,以实现最终的配准!该实现是基于WarpImageFilter 进行操作的,WarpImageFilter 在给定的位移场的作用下将已有图像进行wrap(空间扭曲)操作。位移场可以看做是一张图像,其pixel type是长度至少为N的向量型(vector type)。其中N是输入图像的维数。位移场中每个向量表示输入空间中的几何点和输出空间上点的距离。P(in)=P(out)+d。

WarpImageFilter的输出是通过逆向映射实现的,输出像素被映射到输入图像。该方案避免了创建输出图像中的任何漏洞和重叠。在映射过程中存在不能映射到输入图像的整数位置,所以需要用到插值函数,用以计算在非整数位置的像素值。默认的插值方式是 LinearInterpolateImageFunction,可以通过 SetInterpolator()来进行设置。
映射到输入图像缓冲区的外部的位置,将分配一个边缘填充的值。

1、生成图像

参考图为:像素尺寸100X100,在以(40,40)和(60,60)为坐标所包围的区域像素值为255,其余区域像素值为0;

待配准图为:像素尺寸100X100,在以(20,20)和(80,80)为坐标所包围的区域像素值为100,其余区域像素值为0;

在配准的过程手动设置移动场源的定标点,即为配准导航点。

2、基于两个定标集合(即所谓的导航点,也称为简单称为配准点)产生位移场(displacement field)

1)设置形变场源对象的参数时,向参考图看起,如deformationFieldSource->SetOutputSpacing( fixedImage->GetSpacing() );等

2)生成参考图和待配准图的landmarks,即两者的地标!通过InsertElement( 2, sourcePoint );对地标点进行添加!

3)将地标点与形变场源进行关联

3、建立一个WarpImageFilterType的warpImageFilter。

1)需要设置其所对应的插值器

2)根据形变场源设置warpImageFilter的SetOutputSpacing和SetOutputOrigin

3)需要将其与2中的形变场源进行关联。warpImageFilter->SetDisplacementField( deformationFieldSource->GetOutput() );

同时也需要设置其待配准图像的输入:warpImageFilter->SetInput( movingImage );

4、输出配准结果

只需要利用一个writer将warpImageFilter的结果进行输出即可!

writer->SetInput (  warpImageFilter->GetOutput() );

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

#include "itkWarpImageFilter.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, char *[])
{
	typedef   float          VectorComponentType;

	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);
//Computes a displacement field(位移场) from two sets of landmarks. 
#if ITK_VERSION_MAJOR < 4
	typedef itk::DeformationFieldSource<DeformationFieldType>  DeformationFieldSourceType;
#else
	typedef itk::LandmarkDisplacementFieldSource<DeformationFieldType>  DeformationFieldSourceType;
#endif
	DeformationFieldSourceType::Pointer deformationFieldSource =
		DeformationFieldSourceType::New();
	//std::cout<<fixedImage->GetSpacing();
	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;//设置第3个配准点!
	sourcePoint[1] = 40;
	targetPoint[0] = 80;
	targetPoint[1] = 20;
	sourceLandmarks->InsertElement( 2, sourcePoint );
	targetLandmarks->InsertElement( 2, targetPoint );

	sourcePoint[0] = 60;//设置第4个配准点
	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();
	}


	typedef itk::WarpImageFilter< ImageType,
		ImageType,
		DeformationFieldType  >  WarpImageFilterType;

	WarpImageFilterType::Pointer warpImageFilter =
		WarpImageFilterType::New();
	//插值器类型
	typedef itk::LinearInterpolateImageFunction<ImageType, double >  InterpolatorType;
	InterpolatorType::Pointer interpolator =
		InterpolatorType::New();

	warpImageFilter->SetInterpolator( interpolator );
	warpImageFilter->SetOutputSpacing( deformationFieldSource->GetOutput()->GetSpacing() );
	warpImageFilter->SetOutputOrigin(  deformationFieldSource->GetOutput()->GetOrigin() );
#if ITK_VERSION_MAJOR < 4
	warpImageFilter->SetDeformationField( deformationFieldSource->GetOutput() );
#else
	warpImageFilter->SetDisplacementField( deformationFieldSource->GetOutput() );
#endif
	warpImageFilter->SetInput( movingImage );
	warpImageFilter->Update();

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

	return EXIT_SUCCESS;
}

void CreateFixedImage(ImageType::Pointer image)
{
	// Create a black image with a white square
	//参考图像为(40,40)和(60,60)之间所包围的一个矩形框,且该区域灰度值为255
	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
	//待配准图像为(20,20)和(80,80)所围成的矩形框,且该区域灰度值为100
	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();
}
结果图如下所示:


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值