ITK读取裸数据方法
关键词:ITK、裸数据、MRIcro、itk::RawImageIO
ITK多用于医学图像的配置和分割,所以其对DICOM文件读写操作的支持是很好的(ITK内部使用GDCM对DICOM文件进行操作,有关GDCM的信息可直接访问其主页: 点击打开链接获取更多信息),但很多时候,特别是做研究的,往往会把处理后的数据以裸数据的形成临时保存,以便进行其它后续操作,而在ITK关于IO的例子中没有关于读取裸数据的信息。使用GOOGLE检索后,得到一条很有用的信息,自己测试了下,把自己翻译和测试的代码记录下来。
1、裸数据的获得
将DICOM文件转化为裸数据的方法很多,使用现成的软件---MRIcro进行转化是最简单的方法,MRIcro的主页: http://www.mccauslandcenter.sc.edu/mricro/mricro/mricro.html,在其主页的
Installation部分可以下载到安装文件,具体讲DICOM文件转化为裸数据的方法可以查看MRIcro的使用说明,如果还不会,可以联系我。另外建议使用DCMTK软件包来读取和保存DICOM文件中的数据信息,很简单,也很方便,可以作很多的中间处理,代码量也很少,可以参考DCMTK的说明文档。如果你使用MRIcro来转化,那么转化之后会产生两个文件,一个后缀名称是*.hdr,另外一个是*.img,后缀为hdr的文件内是数据的相关信息,如果你感兴趣可以在网上找到关于hdr文件格式的说明和详细的读写hdr文件c代码,而后缀为img的文件就是数据文件,里面保存的是纯粹的数据。
2、使用ITK对裸数据进行读取并保存为裸数据
使用ITK读取裸数据要在ImageFileReader中使用
itk:RawImageIO对象,直接调用ImageFileReader类的SetImageIO函数即可,和读取DICOM文件相似。在这里先贴出itk:RawImageIO的具体使用方法,然后再对其进行简单说明:
typedef itk::RawImageIO<DicomPixelType, InputDimension> ImageIOType;
ImageIOType::Pointer gdcmImageIO = ImageIOType::New();
gdcmImageIO->SetHeaderSize(0); // 可选
// The number of dimensions stored in a file. Defaults to two.
gdcmImageIO->SetFileDimensionality(2); // 可选
gdcmImageIO->SetNumberOfComponents(1);
gdcmImageIO->SetDimensions( 0, 512 );
gdcmImageIO->SetDimensions( 1, 512 );
gdcmImageIO->SetSpacing( 0, 0.414 );
gdcmImageIO->SetSpacing( 1, 0.414 );
gdcmImageIO->SetHeaderSize(0);
reader->SetImageIO( gdcmImageIO );
reader->SetFileName( "..\\test_img\\IM-0001-0009.img" );
reader->Update();
学习itk:RawImageIO的方法可以从
Insight/Testing/Code/IO/itkRawImageIOTest.cxx开始,由于裸数据没有固定的文件扩展名或格式,所以很难说一个文件是否为裸数据,同样在使用itk::RawImageIO读取裸数据的时候要设置相关的数据信息。
void itk::RawImageIO::SetHeaderSize(unsigned long size);
该函数用来指定头文件的长度,以字节为单位,如果要读取的文件内全部是数据则设置为0;
void itk::RawImageIO::SetFileDimensionality(unsigned long dim);
指定数据的维数,二维或三维等等,默认为2;
void itk::ImageIOBase::SetDimensions(unsigned int i, int dim);
设置数据的长、宽和高;
void itk::ImageIOBase::SetNumberOfComponents(unsigned int num_componen=ts);
设置数据中每个像素点用多少位表示,如果是RGB数据,则设置为3;如果是灰度图像则为1.
//*******************************************************************************************************
附录完整的测试代码:
// TODO: Add your control notification handler code here
typedef unsigned short RawPixelType;
typedef float SmoothPixelType;
const unsigned int InputDimension = 2;
typedef itk::Image< RawPixelType, 2 > RawImageType;
typedef itk::Image< SmoothPixelType, 2 > SmoothImageType;
typedef itk::ImageFileReader< RawImageType > ReaderType;
ReaderType::Pointer reader = ReaderType::New();
typedef itk::RawImageIO<RawPixelType, InputDimension> ImageIOType;
ImageIOType::Pointer rawImageIO = ImageIOType::New();
rawImageIO->SetFileTypeToBinary(); // 二进制方式打开
rawImageIO->SetFileDimensionality(2); // 读取二维数据
rawImageIO->SetByteOrderToLittleEndian();// 小端方式
rawImageIO->SetPixelType(itk::ImageIOBase::SCALAR); // 像素类型
rawImageIO->SetHeaderSize(0); // 头文件大小
rawImageIO->SetNumberOfComponents(1); // 单个像素的位数
rawImageIO->SetDimensions( 0, 512 ); // 图像宽
rawImageIO->SetDimensions( 1, 512 ); // 图像高
rawImageIO->SetSpacing( 0, 0.414 ); // X 方向像素间距
rawImageIO->SetSpacing( 1, 0.414 ); // Y 方向像素间距
rawImageIO->SetOrigin(0,0.0); // 图像原点
rawImageIO->SetOrigin(1,0.0); // 图像原点
reader->SetFileName( "..\\test_img\\IM-0001-0009.img" );
reader->SetImageIO( rawImageIO );
reader->Update();
typedef itk::CastImageFilter< RawImageType, SmoothImageType > CastingFilterType;
CastingFilterType::Pointer casterIn = CastingFilterType::New();
typedef itk::CastImageFilter< SmoothImageType, RawImageType > CastingFilterType1;
CastingFilterType1::Pointer casterOut = CastingFilterType1::New();
typedef itk::CurvatureFlowImageFilter< SmoothImageType, SmoothImageType > CurvatureFlowImageFilterType;
CurvatureFlowImageFilterType::Pointer smoothing = CurvatureFlowImageFilterType::New();
smoothing->SetNumberOfIterations( 5 );
smoothing->SetTimeStep( 0.125 );
casterIn->SetInput( reader->GetOutput() );
smoothing->SetInput( casterIn->GetOutput() );
casterOut->SetInput( smoothing->GetOutput() );
typedef itk::ImageFileWriter< RawImageType > Writer1Type;
Writer1Type::Pointer writer = Writer1Type::New();
writer->SetFileName( "..\\test_img\\smooth.img" );
writer->SetImageIO( rawImageIO );
writer->SetInput( casterOut->GetOutput() );
try
{
writer->Update();
}
catch( itk::ExceptionObject & excep )
{
std::cerr << "Exception caught !" << std::endl;
std::cerr << excep << std::endl;
}