Mercurial > hg > minc-tools
changeset 2613:356008a3c7e6
Making DWI conversion utility
author | Vladimir S. FONOV <vladimir.fonov@gmail.com> |
---|---|
date | Tue, 14 Feb 2012 18:42:50 -0500 |
parents | 4648ed43d78e |
children | 36848f798715 |
files | minc4itk/conversion/itk_convert.cpp |
diffstat | 1 files changed, 160 insertions(+), 108 deletions(-) [+] |
line wrap: on
line diff
--- a/minc4itk/conversion/itk_convert.cpp +++ b/minc4itk/conversion/itk_convert.cpp @@ -8,6 +8,7 @@ #include <itkFlipImageFilter.h> #include <itkMetaDataObject.h> #include <itkMetaDataDictionary.h> +#include <itkCastImageFilter.h> #include "itkMincImageIOFactory.h" #include "itkMincImageIO.h" @@ -31,21 +32,32 @@ << "Usage: "<<name<<" <input> <output> " << std::endl << "--clobber clobber output files"<<std::endl << "--verbose be verbose"<<std::endl + << "--show-meta show meta information (if present)"<<std::endl + << " Spatial transformation flags:"<<std::endl << "--inv-x invert X axis"<<std::endl << "--inv-y invert Y axis"<<std::endl << "--inv-z invert Z axis"<<std::endl << "--center set origin to the center of the image"<<std::endl - << "--show-meta show meta information (if present)"<<std::endl + << " DWI related flags "<<std::endl << "--dwi - assume that we are dealing with DWI scan"<<std::endl << "--use-b-matrix - convert b-matrix (if present) into DWI gradient directions and b-value, implies DWI"<<std::endl - << "--char - save as signed char"<<std::endl - << "--byte - save as unsigned char"<<std::endl - << "--short - save as signed short"<<std::endl - << "--ushort - save as unsigned short"<<std::endl - << "--int - save as signed int"<<std::endl - << "--uint - save as unsigned int"<<std::endl - << "--float - save as float"<<std::endl - << "--double - save as double"<<std::endl + << "--dwi-flip-z - flip Z component of DWI gradient direction (for compatibility with MINC)"<<std::endl + << " Data conversion flags: "<<std::endl + << "--char - cast data as signed char"<<std::endl + << "--byte - cast data as unsigned char"<<std::endl + << "--short - cast data as signed short"<<std::endl + << "--ushort - cast data as unsigned short"<<std::endl + << "--int - cast data as signed int"<<std::endl + << "--uint - cast data as unsigned int"<<std::endl + << "--float - cast data as float"<<std::endl + << "--double - cast data as double"<<std::endl + << " MINC file format related flags:" << std::endl + << "--mbyte - save pixel value using signed char"<<std::endl + << "--mshort - save pixel value using short"<<std::endl + << "--mint - save pixel value using int"<<std::endl + << "--mfloat - save pixel value using float"<<std::endl + << "--mdouble - save pixel value using double"<<std::endl + ; } @@ -57,6 +69,7 @@ protected: bool assume_dti; bool use_b_matrix; + bool dwi_flip_z; std::string history; bool verbose; bool inv_x; @@ -64,18 +77,23 @@ bool inv_z; bool center; bool show_meta; + int minc_type; public: void setup(bool _verbose=false, bool _assume_dti=false, bool _use_b_matrix=false, + bool _dwi_flip_z=false, bool _inv_x=false,bool _inv_y=false,bool _inv_z=false, bool _center=false, bool _show_meta=false, - const std::string _history="") + const std::string _history="", + int _minc_type=-1 + ) { assume_dti=_assume_dti; use_b_matrix=_use_b_matrix; + dwi_flip_z=_dwi_flip_z; history=_history; verbose=_verbose; inv_x=_inv_x; @@ -83,28 +101,33 @@ inv_z=_inv_z; center=_center; show_meta=_show_meta; + minc_type=_minc_type; } - virtual void load_and_save_image(IOBase* base,const char *fname)=0; + virtual void load_and_save_image(IOBase* base,const char *fname,itk::ImageIOBase::IOComponentType oct)=0; virtual ~ImageConverterBase() {} }; -template<class TInputImage,class TOutputImage=TInputImage> class ImageConverter: public ImageConverterBase +template<class TInputImage> class ImageConverter: public ImageConverterBase { protected: + + typedef TInputImage InputImageType; + typedef typename InputImageType::PixelType InputImagePixelType; + public: - ~ImageConverter() - {} + { + + } ImageConverter() { setup(); } - void convert_meta_minc_to_nrrd(itk::MetaDataDictionary& dict) { @@ -189,7 +212,7 @@ direction[0]*=b_scale; direction[1]*=b_scale; - direction[2]*=b_scale; + direction[2]*=(dwi_flip_z&&!use_b_matrix)?-b_scale:b_scale; } std::ostringstream ossKey; @@ -221,9 +244,8 @@ void convert_meta_nrrd_to_minc(itk::MetaDataDictionary& dict) { //1. get b-value - std::string b_value_,gradient_value_; - double bval=0.0,vect3d[3],vmag=0.0; + double bval=0.0,vect3d[3]; double_vector bvalues,direction_x,direction_y,direction_z; if(itk::ExposeMetaData<std::string>( dict,"DWMRI_b-value", b_value_)) @@ -240,20 +262,27 @@ std::istringstream iss(gradient_value_); iss >> vect3d[0] >> vect3d[1] >> vect3d[2]; - direction_x.push_back(vect3d[0]); - direction_y.push_back(vect3d[1]); - direction_z.push_back(vect3d[2]); + //? normalize to unit vector and modulate bvalue + double b_scale=vect3d[0]*vect3d[0]+vect3d[1]*vect3d[1]+vect3d[2]*vect3d[2]; + double vmag=::sqrt(b_scale); - //? normalize to unit vector and modulate bvalue instead? - vmag=::sqrt(vect3d[0]*vect3d[0]+vect3d[1]*vect3d[1]+vect3d[2]*vect3d[2]); if(vmag<0.1) //Zero + { bvalues.push_back(0.0); - else - bvalues.push_back(bval); + direction_x.push_back(0.0); + direction_y.push_back(0.0); + direction_z.push_back(0.0); + } else { + bvalues.push_back(bval*b_scale); + direction_x.push_back(vect3d[0]/vmag); + direction_y.push_back(vect3d[1]/vmag); + direction_z.push_back(((dwi_flip_z&&!use_b_matrix)?-vect3d[2]:vect3d[2])/vmag); + } } else { break; } } + if(!bvalues.empty()) { itk::EncapsulateMetaData<double_vector>( dict , "acquisition:bvalues",bvalues); @@ -325,18 +354,19 @@ direction_x[i] = svd.U(0,0); direction_y[i] = svd.U(1,0); - direction_z[i] = svd.U(2,0); + direction_z[i] = dwi_flip_z?svd.U(2,0):svd.U(2,0); bvalues[i] = bvalue; } } return max_bval; } - - virtual void load_and_save_image(IOBase* base,const char *fname) + + template<class TOutputImage> void _load_and_save_image(IOBase* base,const char *fname) { typename itk::ImageFileReader<TInputImage >::Pointer reader = itk::ImageFileReader<TInputImage >::New(); typename itk::FlipImageFilter<TInputImage >::Pointer flip=itk::FlipImageFilter<TInputImage >::New(); + reader->SetImageIO(base); reader->SetFileName(base->GetFileName()); reader->Update(); @@ -390,8 +420,6 @@ //We have got NRRD-style DTI metadata convert_meta_nrrd_to_minc(thisDic); } - - if(verbose) std::cout<<"Writing "<<fname<<"..."<<std::endl; @@ -432,19 +460,57 @@ } if(!history.empty()) minc::append_history(img,history); - - typename itk::ImageFileWriter< TInputImage >::Pointer writer = itk::ImageFileWriter<TInputImage >::New(); + + typename itk::CastImageFilter< TInputImage, TOutputImage >::Pointer cast=itk::CastImageFilter< TInputImage, TOutputImage >::New(); + + cast->SetInput(img); + + typename itk::ImageFileWriter< TOutputImage >::Pointer writer = itk::ImageFileWriter<TOutputImage >::New(); writer->SetFileName(fname); - writer->SetInput( img ); - writer->Update(); + cast->Update(); + + if(minc_type!=-1) + minc::set_minc_storage_type(cast->GetOutput(),(nc_type)minc_type,minc_type!=NC_BYTE); //store byte as unsigned only + writer->SetInput( cast->GetOutput() ); + writer->Update(); } + + virtual void load_and_save_image(IOBase* io,const char *fname,itk::ImageIOBase::IOComponentType oct) + { + switch(oct) + { + case itk::ImageIOBase::UCHAR: + this->_load_and_save_image<itk::VectorImage<unsigned char, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::CHAR: + this->_load_and_save_image<itk::VectorImage<char, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::USHORT: + _load_and_save_image<itk::VectorImage<unsigned short, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::SHORT: + _load_and_save_image<itk::VectorImage<short, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::INT: + _load_and_save_image<itk::VectorImage<int, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::UINT: + _load_and_save_image<itk::VectorImage<unsigned int, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::FLOAT: + _load_and_save_image<itk::VectorImage<float, InputImageType::ImageDimension> >(io,fname); + break; + case itk::ImageIOBase::DOUBLE: + _load_and_save_image<itk::VectorImage<double, InputImageType::ImageDimension> >(io,fname); + break; + default: + itk::ExceptionObject("Unsupported component type"); + } + } }; - - - int main(int argc,char **argv) { int verbose=0; @@ -455,6 +521,8 @@ char *_history = time_stamp(argc, argv); std::string history=_history; int use_b_matrix=0; + int dwi_flip_z=0; + int minc_type=-1; int store_char=0,store_uchar=0,store_short=0,store_ushort=0,store_float=0,store_int=0,store_uint=0,store_double=0; @@ -472,6 +540,7 @@ {"dti", no_argument, &assume_dti, 1}, {"dwi", no_argument, &assume_dti, 1}, {"use-b-matrix",no_argument, &use_b_matrix, 1}, + {"dwi-flip-z",no_argument, &dwi_flip_z, 1}, {"float", no_argument, &store_float, 1}, {"double", no_argument, &store_double, 1}, @@ -481,7 +550,13 @@ {"ushort", no_argument, &store_ushort, 1}, {"int", no_argument, &store_int, 1}, {"uint", no_argument, &store_uint, 1}, - + + {"mfloat", no_argument, &minc_type, NC_FLOAT}, + {"mdouble", no_argument, &minc_type, NC_DOUBLE}, + {"mbyte", no_argument, &minc_type, NC_BYTE}, + {"mshort", no_argument, &minc_type, NC_SHORT}, + {"mint", no_argument, &minc_type, NC_INT}, + {0, 0, 0, 0} }; @@ -545,137 +620,114 @@ size_t nd = io->GetNumberOfDimensions(); size_t nc = io->GetNumberOfComponents(); itk::ImageIOBase::IOComponentType ct = io->GetComponentType(); + itk::ImageIOBase::IOComponentType oct = ct; + + + if(store_char) + oct=itk::ImageIOBase::CHAR; + else if(store_uchar) + oct=itk::ImageIOBase::UCHAR; + else if(store_short) + oct=itk::ImageIOBase::SHORT; + else if(store_ushort) + oct=itk::ImageIOBase::USHORT; + else if(store_int) + oct=itk::ImageIOBase::INT; + else if(store_uint) + oct=itk::ImageIOBase::UINT; + else if(store_float) + oct=itk::ImageIOBase::FLOAT; + else if(store_double) + oct=itk::ImageIOBase::DOUBLE; + std::string ct_s = io->GetComponentTypeAsString(ct); + std::string oct_s = io->GetComponentTypeAsString(oct); + if(verbose) { std::cout<<"dimensions:"<< nd << std::endl <<"components:"<< nc << std::endl - <<"type:"<<ct_s.c_str()<<std::endl; + <<"input type:"<< ct_s.c_str() <<std::endl + <<"output type:"<<oct_s.c_str()<<std::endl; } - if(store_char) - ct=itk::ImageIOBase::CHAR; - else if(store_uchar) - ct=itk::ImageIOBase::UCHAR; - else if(store_short) - ct=itk::ImageIOBase::SHORT; - else if(store_ushort) - ct=itk::ImageIOBase::USHORT; - else if(store_int) - ct=itk::ImageIOBase::INT; - else if(store_uint) - ct=itk::ImageIOBase::UINT; - else if(store_float) - ct=itk::ImageIOBase::FLOAT; - else if(store_double) - ct=itk::ImageIOBase::DOUBLE; ImageConverterBase *converter=NULL; - if(nd==3 && nc==1) + if(nd==3 || assume_dti) { if(verbose) std::cout<<"Writing 3D image..."<<std::endl; switch(ct) { case itk::ImageIOBase::UCHAR : - converter=new ImageConverter<itk::Image<unsigned char, 3> >(); + converter=new ImageConverter<itk::VectorImage<unsigned char, 3> >(); break; case itk::ImageIOBase::CHAR : - converter=new ImageConverter<itk::Image<char, 3> >(); + converter=new ImageConverter<itk::VectorImage<char, 3> >(); break; case itk::ImageIOBase::USHORT : - converter=new ImageConverter<itk::Image<unsigned short, 3> >(); + converter=new ImageConverter<itk::VectorImage<unsigned short, 3> >(); break; case itk::ImageIOBase::SHORT : - converter=new ImageConverter<itk::Image<short, 3> >(); + converter=new ImageConverter<itk::VectorImage<short, 3> >(); break; case itk::ImageIOBase::INT : - converter=new ImageConverter<itk::Image<int, 3> >(); + converter=new ImageConverter<itk::VectorImage<int, 3> >(); break; case itk::ImageIOBase::UINT: - converter=new ImageConverter<itk::Image<unsigned int, 3> >(); + converter=new ImageConverter<itk::VectorImage<unsigned int, 3> >(); break; case itk::ImageIOBase::FLOAT : - converter=new ImageConverter<itk::Image<float, 3> >(); + converter=new ImageConverter<itk::VectorImage<float, 3> >(); break; case itk::ImageIOBase::DOUBLE: - converter=new ImageConverter<itk::Image<double, 3> >(); + converter=new ImageConverter<itk::VectorImage<double, 3> >(); break; default: itk::ExceptionObject("Unsupported component type"); } - } else if((nd==4 && nc==1 && !assume_dti)) { + } else if(nd==4 ) { //|| (nd==3 && nc>1) if(verbose) std::cout<<"Writing 4D image..."<<std::endl; switch(ct) { case itk::ImageIOBase::UCHAR: - converter=new ImageConverter<itk::Image<unsigned char, 4> >(); + converter=new ImageConverter<itk::VectorImage<unsigned char, 4> >(); break; case itk::ImageIOBase::CHAR: - converter=new ImageConverter<itk::Image<char, 4> >(); + converter=new ImageConverter<itk::VectorImage<char, 4> >(); break; case itk::ImageIOBase::USHORT: - converter=new ImageConverter<itk::Image<unsigned short, 4> >(); + converter=new ImageConverter<itk::VectorImage<unsigned short, 4> >(); break; case itk::ImageIOBase::SHORT: - converter=new ImageConverter<itk::Image<short, 4> >(); + converter=new ImageConverter<itk::VectorImage<short, 4> >(); break; case itk::ImageIOBase::INT: - converter=new ImageConverter<itk::Image<int, 4> >(); + converter=new ImageConverter<itk::VectorImage<int, 4> >(); break; case itk::ImageIOBase::UINT: - converter=new ImageConverter<itk::Image<unsigned int, 4> >(); + converter=new ImageConverter<itk::VectorImage<unsigned int, 4> >(); break; case itk::ImageIOBase::FLOAT: - converter=new ImageConverter<itk::Image<float, 4> >(); + converter=new ImageConverter<itk::VectorImage<float, 4> >(); break; case itk::ImageIOBase::DOUBLE: - converter=new ImageConverter<itk::Image<double, 4> >(); + converter=new ImageConverter<itk::VectorImage<double, 4> >(); break; default: itk::ExceptionObject("Unsupported component type"); } - } else if(((nd==3 && nc>1) || assume_dti)) { - if(verbose) std::cout<<"Writing multicomponent 3D image..."<<std::endl; - - switch(ct) - { - case itk::ImageIOBase::UCHAR: - converter=new ImageConverter<itk::VectorImage<unsigned char, 3> >(); - break; - case itk::ImageIOBase::CHAR: - converter=new ImageConverter<itk::VectorImage<char, 3> >(); - break; - case itk::ImageIOBase::USHORT: - converter=new ImageConverter<itk::VectorImage<unsigned short, 3> >(); - break; - case itk::ImageIOBase::SHORT: - converter=new ImageConverter<itk::VectorImage<short, 3> >(); - break; - case itk::ImageIOBase::INT: - converter=new ImageConverter<itk::VectorImage<int, 3> >(); - break; - case itk::ImageIOBase::UINT: - converter=new ImageConverter<itk::VectorImage<unsigned int, 3> >(); - break; - case itk::ImageIOBase::FLOAT: - converter=new ImageConverter<itk::VectorImage<float, 3> >(); - break; - case itk::ImageIOBase::DOUBLE: - converter=new ImageConverter<itk::VectorImage<double, 3> >(); - break; - default: - itk::ExceptionObject("Unsupported component type"); - } - } else { + } + else { throw itk::ExceptionObject("Unsupported number of dimensions"); } if(converter) { - converter->setup(verbose,assume_dti,use_b_matrix,inv_x,inv_y,inv_z,center,show_meta,history); - converter->load_and_save_image(io,output.c_str()); + converter->setup(verbose,assume_dti,use_b_matrix,dwi_flip_z,inv_x,inv_y,inv_z,center,show_meta,history,minc_type); + converter->load_and_save_image(io,output.c_str(),oct); + delete converter; } }