概述
实现基于手动设置地标的刚性配准。所谓的刚性配准是指变换前后图像中任意两点的距离不变。不考虑坐标轴尺度缩放时,刚性变换仅存在坐标轴的平移和旋转。
1、生成图像
参考图像:图像尺寸100X100,在以坐标点(10,10)和(20,20)所包围的区域内灰度值为255,其余区域灰度值为0;
待配准图像:图像尺寸100X100,在以坐标点(50,50)和(60,60)所包围区域内灰度值值为100,其余区域灰度值为0;
2、定义基于地标集合的变换类型,相当于上一篇文章的DeformationFieldSourceType。
并将该类型进行实例化,该对象与上一篇中的deformationFieldSource相对应。
3、创建参考图和待配准图的地标集
其中涉及到地标容器和地标点,如下所示:
LandmarkContainerType movingLandmarks;
LandmarkPointType fixedPoint;
LandmarkPointType movingPoint;
通过往容器中添加地标点以收集地标点集。
fixedLandmarks.push_back( fixedPoint );
movingLandmarks.push_back( movingPoint );
4、设置基于地标点的变换的地标集合。使得变换场与参考图和待配准图的地标点进行关联!
landmarkBasedTransformInitializer->SetFixedLandmarks( fixedLandmarks );
landmarkBasedTransformInitializer->SetMovingLandmarks( movingLandmarks );
5、定义刚性变换类型
Rigid2DTransformType::Pointer transform = Rigid2DTransformType::New();
transform->SetIdentity();
并将基于地标点的变换对象设置为刚性变换
landmarkBasedTransformInitializer->SetTransform(transform);
6、定义ResampleFilterType,相当于上一篇文章中的WarpImageFilterType,将其与变换对象进行关联
设置该滤波器的输入为待配准图像
resampleFilter->SetInput( movingImage );
设置其变换为刚性变换
resampleFilter->SetTransform( transform );//
7、将配准结果进行输出
writer->SetInput ( resampleFilter->GetOutput() );
代码如下:
#include "itkImageFileWriter.h"
#include "itkImage.h"
#include "itkVector.h"
#include "itkResampleImageFilter.h"
#include "itkLandmarkBasedTransformInitializer.h"
#include "itkRigid2DTransform.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[])
{
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);
//定义刚性变换类型
typedef itk::Rigid2DTransform< double > Rigid2DTransformType;
//基于地标集合的变换类型。相当于上一篇文章的DeformationFieldSourceType
typedef itk::LandmarkBasedTransformInitializer< Rigid2DTransformType, ImageType, ImageType >
LandmarkBasedTransformInitializerType;
//进行实例化,该对象与上一篇中的deformationFieldSource相对应
LandmarkBasedTransformInitializerType::Pointer landmarkBasedTransformInitializer =
LandmarkBasedTransformInitializerType::New();
//
Create source and target landmarks.
typedef LandmarkBasedTransformInitializerType::LandmarkPointContainer
LandmarkContainerType;
typedef LandmarkBasedTransformInitializerType::LandmarkPointType
LandmarkPointType;
LandmarkContainerType fixedLandmarks;
LandmarkContainerType movingLandmarks;
LandmarkPointType fixedPoint;
LandmarkPointType movingPoint;
//添加参考图的地标点(10,10);待配准图(50,50)
fixedPoint[0] = 10;
fixedPoint[1] = 10;
movingPoint[0] = 50;
movingPoint[1] = 50;
fixedLandmarks.push_back( fixedPoint );
movingLandmarks.push_back( movingPoint );
//添加第二个地标点:参考图中的(10,20)和待配准图中的(50,60)
fixedPoint[0] = 10;
fixedPoint[1] = 20;
movingPoint[0] = 50;
movingPoint[1] = 60;
fixedLandmarks.push_back( fixedPoint );
movingLandmarks.push_back( movingPoint );
//添加第3个地标点
fixedPoint[0] = 20;
fixedPoint[1] = 10;
movingPoint[0] = 60;
movingPoint[1] = 50;
fixedLandmarks.push_back( fixedPoint );
movingLandmarks.push_back( movingPoint );
//添加第4个地标点
fixedPoint[0] = 20;
fixedPoint[1] = 20;
movingPoint[0] = 60;
movingPoint[1] = 60;
fixedLandmarks.push_back( fixedPoint );
movingLandmarks.push_back( movingPoint );
//设置基于地标点的变换的地标集合。使得变换场与参考图和待配准图的地标点进行关联!
landmarkBasedTransformInitializer->SetFixedLandmarks( fixedLandmarks );
landmarkBasedTransformInitializer->SetMovingLandmarks( movingLandmarks );
//将已经初始化的基于地标点的变换设置为2D的刚性变换!
Rigid2DTransformType::Pointer transform = Rigid2DTransformType::New();
transform->SetIdentity();
landmarkBasedTransformInitializer->SetTransform(transform);
landmarkBasedTransformInitializer->InitializeTransform();
//相当于上一篇文章中的WarpImageFilterType,将其与变换对象进行关联
typedef itk::ResampleImageFilter<ImageType, ImageType, double >
ResampleFilterType;
ResampleFilterType::Pointer resampleFilter = ResampleFilterType::New();
resampleFilter->SetInput( movingImage );
resampleFilter->SetTransform( transform );//
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] > 10 && imageIterator.GetIndex()[0] < 20 &&
imageIterator.GetIndex()[1] > 10 && imageIterator.GetIndex()[1] < 20)
{
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] > 50 && imageIterator.GetIndex()[0] < 60 &&
imageIterator.GetIndex()[1] > 50 && imageIterator.GetIndex()[1] < 60)
{
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();
}
配准结果如下图所示:
最后
以上就是靓丽哑铃为你收集整理的ITK配准:基于手动设置地标的刚性配准的全部内容,希望文章能够帮你解决ITK配准:基于手动设置地标的刚性配准所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复