ITK对DICOM数据的读与写
发布时间
阅读量:
阅读量
该文本介绍了使用ITK库进行DICOM序列读写和处理的方法,重点包括:1)通过GDCMImageIO实现DICOM序列的读写,支持三维到二维的转换;2)处理单张DICOM数据时,避免了文件头信息从reader获取可能导致的错误;3)针对输入输出类型转换的问题,使用RescaleIntensityImageFilter进行类型转换;4)在使用fastMarching算法时,需要手动设置输出原点、间距和尺寸以匹配输入图像。代码示例展示了完整的读写流程和相关设置细节。
1.读写DICOM序列
首先,通过读取一系列DICOM数据,构建三维体数据。随后,经过必要的处理过程后,输出二维DICOM数据。其中,GDCMImageIO被选作满足DICOM格式需求的ImageIO库。
读写过程如下:
//IO相关
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
#include "itkImageSeriesReader.h"
#include "itkImageSeriesWriter.h"
int main(int argc, char *argv[])
{
typedef float InternalPixelType;
const unsigned int Dimension = 3;//输入为三维
typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
typedef float OutputPixelType;
const unsigned int OutputDimension = 2;//输出为二维
typedef itk::Image< OutputPixelType, OutputDimension > OutputImageType;
typedef itk::ImageSeriesReader< InternalImageType > ReaderType;
typedef itk::ImageSeriesWriter< InternalImageType,OutputImageType > WriterType;//自动在输入和输出之间转换
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
//DICOM数据的ImageIO
typedef itk::GDCMImageIO ImageIOType;
ImageIOType::Pointer gdcmIO = ImageIOType::New();
//文件生成器
typedef itk::GDCMSeriesFileNames NamesGeneratorType;
NamesGeneratorType::Pointer namesGenerator = NamesGeneratorType::New();
namesGenerator->SetInputDirectory("D:/VTKCode/Data/Threshold");
//保存文件名
const ReaderType::FileNamesContainer & filenames =
namesGenerator->GetInputFileNames();
reader->SetImageIO(gdcmIO);
reader->SetFileNames(filenames);
try
{
reader->Update();
}
catch (itk::ExceptionObject &excp)
{
std::cerr << "Exception thrown while writing the image" << std::endl;
std::cerr << excp << std::endl;
system("pause");
return EXIT_FAILURE;
}
//显示Image Space的不同方法
std::cout << "Spacing = ";
std::cout << gdcmIO->GetSpacing(0) <<" "<<gdcmIO->GetSpacing(1)<<" "<<gdcmIO->GetSpacing(2) << std::endl;
std::cout << "Origin = ";
std::cout << gdcmIO->GetOrigin(0) << " " << gdcmIO->GetOrigin(1) << " " << gdcmIO->GetOrigin(2) << std::endl;
const InternalImageType::SpacingType& inputSpacing = reader->GetOutput()->GetSpacing();
std::cout << "Spacing=";
std::cout << inputSpacing[0] << " " << inputSpacing[1] << " " << inputSpacing[2] << std::endl;
//输出文件夹
const char * outputDirectory = "D:/image";
itksys::SystemTools::MakeDirectory(outputDirectory);
//设置输出文件夹
namesGenerator->SetOutputDirectory(outputDirectory);
writer->SetFileNames(namesGenerator->GetOutputFileNames());
//用原来的文件头
writer->SetMetaDataDictionaryArray(
reader->GetMetaDataDictionaryArray());
writer->SetInput(reader->GetOutput());
writer->SetImageIO(gdcmIO);
try
{
writer->Update();
}
catch (itk::ExceptionObject & excep)
{
std::cerr << "Exception caught !" << std::endl;
std::cerr << excep << std::endl;
system("pause");
return EXIT_FAILURE;
}
system("pause");
return EXIT_SUCCESS;
}
2.读写单张DICOM数据
在读写单张DICOM数据时,输入与输出的格式保持一致,同时采用GDCMImageIO作为ImageIO工具。其中,文件头信息不通过reader获取,而是由GDCMImageIO提供,否则可能会遇到如下问题。
itk::ExceptionObject (00000014AA4FD6D8)
Location: "void __cdecl itk::GDCMImageIO::Write(const void *)"
File: D:\S\D\ITKv4\Modules\IO\GDCM\src\itkGDCMImageIO.cxx
Line: 1036
Description: itk::ERROR: GDCMImageIO(000001BB3A34A4D0): A Floating point buffer was passed but the stored pixel type was not specified.This is currently not supported
读写代码如下:
//IO相关
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkGDCMImageIO.h"
#include "itkGDCMSeriesFileNames.h"
int main(int argc, char *argv[])
{
typedef float InternalPixelType;
const unsigned int Dimension = 2;
typedef itk::Image< InternalPixelType, Dimension > InternalImageType;
typedef float OutputPixelType;
typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
typedef itk::ImageFileReader< InternalImageType > ReaderType;
typedef itk::ImageFileWriter< OutputImageType > WriterType;
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
//DICOM数据的ImageIO
typedef itk::GDCMImageIO ImageIOType;
ImageIOType::Pointer gdcmIO = ImageIOType::New();
reader->SetImageIO(gdcmIO);
reader->SetFileName("D:/VTKCode/Data/digest_article/84485356.dcm");
try
{
reader->Update();
}
catch (itk::ExceptionObject &excp)
{
std::cerr << "Exception thrown while writing the image" << std::endl;
std::cerr << excp << std::endl;
system("pause");
return EXIT_FAILURE;
}
//设置输出文件
writer->SetFileName("D:/image/84485356.dcm");
//设置文件头
writer->UseInputMetaDataDictionaryOff();
writer->SetInput(reader->GetOutput());
writer->SetImageIO(gdcmIO);
try
{
writer->Update();
}
catch (itk::ExceptionObject & excep)
{
std::cerr << "Exception caught !" << std::endl;
std::cerr << excep << std::endl;
system("pause");
return EXIT_FAILURE;
}
system("pause");
return EXIT_SUCCESS;
}
3.关于输入输出类型转换的问题
在DICOM序列输出中,可以通过指定输入和输出类型来实现类型转换。因此,不同类型的输入和输出类型可以实现相互转换。对于单张的情况,通常需要手动进行转换操作。通过指定输入和输出类型参数来完成转换任务,相关代码如下:
typedef itk::RescaleIntensityImageFilter<
InternalImageType,
OutputImageType > CastFilterType;
CastFilterType::Pointer caster = CastFilterType::New();
caster->SetInput( reader->GetOutput() );
writer->SetInput( caster->GetOutput() );
caster->SetOutputMinimum( 0 );
caster->SetOutputMaximum( 255 );
writer->Update();
4.关于fastMarching的问题
ITK的GeodesicActiveContourImageFilter等算法通常采用fastMarching方法求解方程。若未指定输入参数,则默认采用spacing和origin参数进行计算,这种做法通常不够理想。因此,在实际应用中,建议用户根据输入图像调整相关属性,以确保计算的一致性和准确性。相关代码如下:
typedef itk::FastMarchingImageFilter<
InternalImageType,
InternalImageType > FastMarchingFilterType;
FastMarchingFilterType::Pointer fastMarching = FastMarchingFilterType::New();
const InternalImageType::PointType& point = reader->GetOutput()->GetOrigin();
InternalImageType::SpacingType spacing = reader->GetOutput()->GetSpacing();
fastMarching->SetOutputOrigin(point);
fastMarching->SetOutputSpacing(spacing);
fastMarching->SetOutputSize(
reader->GetOutput()->GetBufferedRegion().GetSize());
全部评论 (0)
还没有任何评论哟~
