C++ 在示例代码中运行仿射变换时出错。”;
我下载了仿射格式表单Wiki示例,并将其修改为仿射两个DICOM文件。我成功地构建了它。但当我运行它时。它有一个错误消息:C++ 在示例代码中运行仿射变换时出错。”;,c++,itk,C++,Itk,我下载了仿射格式表单Wiki示例,并将其修改为仿射两个DICOM文件。我成功地构建了它。但当我运行它时。它有一个错误消息: terminate called after throwing an instance of 'itk::ExceptionObject' what(): /usr/local/include/ITK-4.4/itkImageFileWriter.hxx:123: itk::ERROR: ImageFileWriter(0x9808fd8): No filename
terminate called after throwing an instance of 'itk::ExceptionObject'
what(): /usr/local/include/ITK-4.4/itkImageFileWriter.hxx:123:
itk::ERROR: ImageFileWriter(0x9808fd8): No filename was specified
Aborted (core dumped)
这是我的编辑代码。请帮我编辑一下。我正在为Linux使用ITK最新版本4.3.1
#include "itkCastImageFilter.h"``
#include "itkEllipseSpatialObject.h"
#include "itkImage.h"
#include "itkImageRegistrationMethod.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkRegularStepGradientDescentOptimizer.h"
#include "itkResampleImageFilter.h"
#include "itkRescaleIntensityImageFilter.h"
#include "itkSpatialObjectToImageFilter.h"
#include "itkAffineTransform.h"
#include "itkGDCMImageIO.h"
// Software Guide : EndCodeSnippet
#include <list>
#include <fstream>
const unsigned int Dimension = 2;
typedef unsigned char PixelType;
typedef itk::Image< PixelType, Dimension > ImageType;
static void CreateEllipseImage(ImageType::Pointer image);
static void CreateSphereImage(ImageType::Pointer image);
int main(int, char *[] )
{
// The transform that will map the fixed image into the moving image.
typedef itk::AffineTransform< double, Dimension > TransformType;
// An optimizer is required to explore the parameter space of the transform
// in search of optimal values of the metric.
typedef itk::RegularStepGradientDescentOptimizer OptimizerType;
// The metric will compare how well the two images match each other. Metric
// types are usually parameterized by the image types as it can be seen in
// the following type declaration.
typedef itk::MeanSquaresImageToImageMetric<
ImageType,
ImageType > MetricType;
// Finally, the type of the interpolator is declared. The interpolator will
// evaluate the intensities of the moving image at non-grid positions.
typedef itk:: LinearInterpolateImageFunction<
ImageType,
double > InterpolatorType;
// The registration method type is instantiated using the types of the
// fixed and moving images. This class is responsible for interconnecting
// all the components that we have described so far.
typedef itk::ImageRegistrationMethod<
ImageType,
ImageType > RegistrationType;
// Create components
MetricType::Pointer metric = MetricType::New();
TransformType::Pointer transform = TransformType::New();
OptimizerType::Pointer optimizer = OptimizerType::New();
InterpolatorType::Pointer interpolator = InterpolatorType::New();
RegistrationType::Pointer registration = RegistrationType::New();
// Each component is now connected to the instance of the registration method.
registration->SetMetric( metric );
registration->SetOptimizer( optimizer );
registration->SetTransform( transform );
registration->SetInterpolator( interpolator );
// Write the two synthetic inputs
typedef itk::Image< PixelType, Dimension > FixedImageType;
typedef itk::Image< PixelType, Dimension > MovingImageType;
// Software Guide : EndCodeSnippet
// Set up the file readers
typedef itk::ImageFileReader< FixedImageType > FixedImageReaderType;
typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;
FixedImageReaderType::Pointer fixedImageReader = FixedImageReaderType::New();
MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
fixedImageReader->SetFileName("fix.dcm" );
movingImageReader->SetFileName( "mov.dcm" );
typedef itk::ImageFileWriter< ImageType > WriterType;
WriterType::Pointer fixedWriter = WriterType::New();
//ixedWriter->SetFileName("fixed.png");
fixedWriter->SetInput( fixedImageReader->GetOutput());
fixedWriter->Update();
WriterType::Pointer movingWriter = WriterType::New();
// movingWriter->SetFileName("moving.png");
movingWriter->SetInput( movingImageReader->GetOutput());
movingWriter->Update();
// Set the registration inputs
registration->SetFixedImage(fixedImageReader->GetOutput());
registration->SetMovingImage(movingImageReader->GetOutput());
registration->SetFixedImageRegion(
fixedImageReader->GetOutput()->GetLargestPossibleRegion() );
// Initialize the transform
typedef RegistrationType::ParametersType ParametersType;
ParametersType initialParameters( transform->GetNumberOfParameters() );
// rotation matrix
initialParameters[0] = 1.0; // R(0,0)
initialParameters[1] = 0.0; // R(0,1)
initialParameters[2] = 0.0; // R(1,0)
initialParameters[3] = 1.0; // R(1,1)
// translation vector
initialParameters[4] = 0.0;
initialParameters[5] = 0.0;
registration->SetInitialTransformParameters( initialParameters );
optimizer->SetMaximumStepLength( .1 ); // If this is set too high, you will get a
//"itk::ERROR: MeanSquaresImageToImageMetric(0xa27ce70): Too many samples map outside moving image buffer: 1818 / 10000" error
optimizer->SetMinimumStepLength( 0.01 );
// Set a stopping criterion
optimizer->SetNumberOfIterations( 200 );
// Connect an observer
//CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
//optimizer->AddObserver( itk::IterationEvent(), observer );
try
{
registration->Update();
}
catch( itk::ExceptionObject & err )
{
std::cerr << "ExceptionObject caught !" << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
// The result of the registration process is an array of parameters that
// defines the spatial transformation in an unique way. This final result is
// obtained using the \code{GetLastTransformParameters()} method.
ParametersType finalParameters = registration->GetLastTransformParameters();
std::cout << "Final parameters: " << finalParameters << std::endl;
// The value of the image metric corresponding to the last set of parameters
// can be obtained with the \code{GetValue()} method of the optimizer.
const double bestValue = optimizer->GetValue();
// Print out results
//
std::cout << "Result = " << std::endl;
std::cout << " Metric value = " << bestValue << std::endl;
// It is common, as the last step of a registration task, to use the
// resulting transform to map the moving image into the fixed image space.
// This is easily done with the \doxygen{ResampleImageFilter}.
typedef itk::ResampleImageFilter<
ImageType,
ImageType > ResampleFilterType;
ResampleFilterType::Pointer resampler = ResampleFilterType::New();
resampler->SetInput( movingImageReader->GetOutput());
// The Transform that is produced as output of the Registration method is
// also passed as input to the resampling filter. Note the use of the
// methods \code{GetOutput()} and \code{Get()}. This combination is needed
// here because the registration method acts as a filter whose output is a
// transform decorated in the form of a \doxygen{DataObject}. For details in
// this construction you may want to read the documentation of the
// \doxygen{DataObjectDecorator}.
resampler->SetTransform( registration->GetOutput()->Get() );
// As described in Section \ref{sec:ResampleImageFilter}, the
// ResampleImageFilter requires additional parameters to be specified, in
// particular, the spacing, origin and size of the output image. The default
// pixel value is also set to a distinct gray level in order to highlight
// the regions that are mapped outside of the moving image.
resampler->SetSize( fixedImageReader->GetOutput()->GetLargestPossibleRegion().GetSize() );
resampler->SetOutputOrigin( fixedImageReader->GetOutput()->GetOrigin() );
resampler->SetOutputSpacing( fixedImageReader->GetOutput()->GetSpacing() );
resampler->SetOutputDirection( fixedImageReader->GetOutput()->GetDirection() );
resampler->SetDefaultPixelValue( 100 );
// The output of the filter is passed to a writer that will store the
// image in a file. An \doxygen{CastImageFilter} is used to convert the
// pixel type of the resampled image to the final type used by the
// writer. The cast and writer filters are instantiated below.
typedef unsigned char OutputPixelType;
typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
typedef itk::CastImageFilter<
ImageType,
ImageType > CastFilterType;
WriterType::Pointer writer = WriterType::New();
CastFilterType::Pointer caster = CastFilterType::New();
writer->SetFileName("output.png");
caster->SetInput( resampler->GetOutput() );
writer->SetInput( caster->GetOutput() );
writer->Update();
return EXIT_SUCCESS;
}
#包括“itkCastImageFilter.h”``
#包括“itkEllipseSpatialObject.h”
#包括“itkImage.h”
#包括“itkimagerRegistrationMethod.h”
#包括“itkLinearInterpolateImageFunction.h”
#包括“itkImageFileReader.h”
#包括“itkImageFileWriter.h”
#包括“itkMeanSquaresImageToImageMetric.h”
#包括“itkRegularStepGradientDescentOptimizer.h”
#包括“itkresamplemagefilter.h”
#包括“itkRescaleIntensityImageFilter.h”
#包括“itkSpatialObjectToImageFilter.h”
#包括“itkAffineTransform.h”
#包括“itkGDCMImageIO.h”
//软件指南:EndCodeSnippet
#包括
#包括
常量无符号整数维=2;
typedef无符号字符PixelType;
typedef itk::ImageImageType;
静态void CreateEllipseImage(ImageType::指针图像);
静态void CreateSphereImage(ImageType::指针图像);
int main(int,char*[])
{
//将固定图像映射到运动图像的变换。
typedef itk::仿射变换TransformType;
//需要一个优化器来探索转换的参数空间
//搜索度量的最佳值。
typedef itk::RegularStepGradientDescentOptimizer优化器类型;
//度量将比较两个图像彼此匹配的程度。度量
//类型通常由图像类型参数化,如中所示
//下面是类型声明。
typedef itk::MeanSquaresImageToImageMetric<
图像类型,
ImageType>MetricType;
//最后,声明插值器的类型
//在非栅格位置评估运动图像的强度。
typedef itk::LinearinterpoliteImageFunction<
图像类型,
双>插值型;
//注册方法类型是使用
//固定和移动图像。此类负责互连
//到目前为止,我们描述的所有组件。
typedef itk::ImageRegistrationMethod<
图像类型,
图像类型>注册类型;
//创建组件
MetricType::Pointer metric=MetricType::New();
TransformType::Pointer transform=TransformType::New();
优化器类型::指针优化器=优化器类型::新建();
插值器类型::指针插值器=插值器类型::新();
注册类型::指针注册=注册类型::新建();
//现在,每个组件都连接到注册方法的实例。
注册->设置公制(公制);
注册->设置优化器(优化器);
注册->设置转换(转换);
注册->设置插值器(插值器);
//编写两个合成输入
typedef itk::ImageFixedImageType;
typedef itk::ImageMovingImageType;
//软件指南:EndCodeSnippet
//设置文件读取器
类型定义itk::ImageFileReaderFixedImageReaderType;
类型定义itk::ImageFileReaderMovingImageReaderType;
FixedImageReaderType::指针fixedImageReader=FixedImageReaderType::New();
MovingImageReaderType::指针movingImageReader=MovingImageReaderType::New();
fixedImageReader->SetFileName(“fix.dcm”);
movingImageReader->SetFileName(“mov.dcm”);
typedef itk::ImageFileWriterWriterType;
WriterType::Pointer fixedWriter=WriterType::New();
//ixedWriter->SetFileName(“fixed.png”);
fixedWriter->SetInput(fixedImageReader->GetOutput());
fixedWriter->Update();
WriterType::Pointer movingWriter=WriterType::New();
//movingWriter->SetFileName(“moving.png”);
movingWriter->SetInput(movingImageReader->GetOutput());
movingWriter->Update();
//设置注册输入
注册->设置固定图像(固定图像阅读器->获取输出());
注册->设置移动图像(移动图像阅读器->获取输出());
注册->设置固定图像区域(
fixedImageReader->GetOutput()->GetLargestPossibleRegion());
//初始化转换
typedef RegistrationType::ParametersType ParametersType;
ParametersType初始参数(transform->GetNumberOfParameters());
//旋转矩阵
initialParameters[0]=1.0;//R(0,0)
initialParameters[1]=0.0;//R(0,1)
initialParameters[2]=0.0;//R(1,0)
initialParameters[3]=1.0;//R(1,1)
//平移向量
初始参数[4]=0.0;
初始参数[5]=0.0;
注册->设置InitialTransformParameters(initialParameters);
optimizer->SetMaximumStepLength(.1);//如果设置得太高,您将得到一个
//“itk::错误:MeanSquaresImageToImageMetric(0xa27ce70):运动图像缓冲区外映射的样本太多:1818/10000”错误
优化器->设置最小步长(0.01);
//设置停止标准
优化器->SetNumberOfIterations(200);
//连接观察者
//CommandIterationUpdate::Pointer observer=CommandIterationUpdate::New();
//优化器->添加观察者(itk::IterationEvent(),观察者);
尝试
{
注册->更新();
}
捕获(itk::例外对象和错误)
{
std::cerr SetOutputOrigin(fixedImageReader->GetOutput()->GetOrigin());
重采样器->设置输出间距(fixedImageReader->GetOutput()->GetSpacing());
重采样器->设置输出方向(fixedImageReader->GetOutput()->GetDirection());
重采样器->设置默认像素值(100);
//过滤器的输出被传递给一个将存储
//文件中的图像。使用\doxygen{CastImageFilter}转换
//将重采样图像的像素类型转换为用户使用的最终类型
//编剧演员和编剧都很肮脏
WriterType::Pointer fixedWriter = WriterType::New();
// fixedWriter->SetFileName("fixed.png");
WriterType::Pointer movingWriter = WriterType::New();
// movingWriter->SetFileName("moving.png");