11 #include "4DImageMathCLP.h" 13 #include "itkRegionOfInterestImageFilter.h" 14 #include "itkPermuteAxesImageFilter.h" 32 template <
class IndexType>
34 IsOutsideBox (
const IndexType& index,
const std::vector<int>& box )
36 return index[0]<box[0] || index[0]>box[1] || index[1]<box[2] || index[1]>box[3] || index[2]<box[4] || index[2]>box[5];
93 #define _SetOperationWithChecking(op, value, numberOfInputsCond) \ 96 SetOperationWithChecking(op, value); \ 97 utlSAGlobalException(!(numberOfInputsCond))(numberOfInputsCond).msg("wrong number of inputs!"); \ 102 GetImageFiles(
const std::vector<std::string>& imageVec, std::string& inImage0, std::string& outImage)
104 utlGlobalException(imageVec.size()<2,
"need to set at least 2 image files (at least one input image, and one output image)");
105 inImage0 = imageVec[0];
106 outImage = imageVec.back();
111 if (axis==
"X" || axis==
"x" || axis==
"0")
return 0;
112 else if (axis==
"Y" || axis==
"y" || axis==
"1" )
return 1;
113 else if (axis==
"Z" || axis==
"z" || axis==
"2" )
return 2;
114 else if (axis==
"T" || axis==
"t" || axis==
"3" )
return 3;
119 template <
class ImageType,
class Image2Type>
121 ConvertImage (
const itk::SmartPointer<ImageType>& image, itk::SmartPointer<Image2Type>& imageOut )
165 #define __SetImage(ImageType, fileName, imageName, imageItName, axis) \ 166 typename ImageType::Pointer imageName = ImageType::New(); \ 167 itk::VectorImageRegionIteratorWithIndex<ImageType> imageItName; \ 170 itk::ReadImage<ImageType>(fileName, imageName); \ 171 std::vector<int> sizeTmp = itk::GetVectorImage3DVolumeSize(imageName); \ 172 utlGlobalException(!utl::IsSameVector(_size,sizeTmp), "images have different size"); \ 173 imageItName = itk::VectorImageRegionIteratorWithIndex<ImageType> (imageName, imageName->GetLargestPossibleRegion(),axis); \ 177 #define __SetImageOrScalar(ImageType, fileName, imageName, imageItName, valueName) \ 178 typename ImageType::Pointer imageName = ImageType::New(); \ 179 itk::VectorImageRegionIteratorWithIndex<ImageType> imageItName; \ 180 double valueName=0; \ 183 if (utl::IsNumber(fileName)) \ 185 valueName = utl::ConvertStringToNumber<double>(fileName); \ 189 itk::ReadImage<ImageType>(fileName, imageName); \ 190 std::vector<int> sizeTmp = itk::GetVectorImage3DVolumeSize(imageName); \ 191 utlGlobalException(!utl::IsSameVector(_size,sizeTmp), "images have different size"); \ 192 imageItName = itk::VectorImageRegionIteratorWithIndex<ImageType> (imageName, imageName->GetLargestPossibleRegion()); \ 213 #define __FunctionFromStringOpImage(funcStr) \ 216 itk::FunctorFromStringOPImage(imageVec, outImage, funcStr, mask, _numberOfThreads); \ 220 #define __UnaryScalarFunctor(argNoAxis, opNoAxis, funcName) \ 221 if (argNoAxis##Arg.isSet()) \ 223 _SetOperationWithChecking(_Operation, OP_##opNoAxis, imageVec.size()==1); \ 224 utl::Functor::ScalarFunctorWrapper<funcName > func; \ 225 itk::UnaryVectorOPImage<ImageType, ImageOutType>(image, outImage, func, mask, _numberOfThreads); \ 229 #define __XYZTUnaryVectorFunctor(axisNum, argNoAxis, opNoAxis, funcName) \ 230 if (argNoAxis##Arg.isSet()) \ 232 _SetOperationWithChecking(_Operation, OP_##opNoAxis, imageVec.size()==1); \ 234 itk::UnaryVectorOPImage<ImageType, ImageOutType>(image, outImage, func, mask, _numberOfThreads, axisNum); \ 238 #define __XYZTUnaryVectorFunctorWithArguments(axisNum, argNoAxis, opNoAxis, funcName) \ 239 if (argNoAxis##Arg.isSet()) \ 241 _SetOperationWithChecking(_Operation, OP_##opNoAxis, imageVec.size()==1); \ 243 func.SetArguments(argNoAxis); \ 244 itk::UnaryVectorOPImage<ImageType, ImageOutType>(image, outImage, func, mask, _numberOfThreads, axisNum); \ 248 #define __XYZTMultiVectorFunctor(axisNum, argNoAxis, opNoAxis, funcName) \ 249 if (argNoAxis##Arg.isSet()) \ 251 _SetOperationWithChecking(_Operation, OP_##opNoAxis, imageVec.size()>=2); \ 253 itk::MultiVariableVectorOPImage<ImageType, ImageOutType>(imageVec, outImage, func, mask, _numberOfThreads, axisNum); \ 257 #define __XYZTMultiVectorFunctor_FixedSize(axisNum, argNoAxis, opNoAxis, funcName, inSize) \ 258 if (argNoAxis##Arg.isSet()) \ 260 _SetOperationWithChecking(_Operation, OP_##opNoAxis, imageVec.size()==inSize); \ 262 itk::MultiVariableVectorOPImage<ImageType, ImageOutType>(imageVec, outImage, func, mask, _numberOfThreads, axisNum); \ 319 template <
class ImageType,
class ImageOutType,
class OpFunctor>
321 BinaryOPImage(
const itk::SmartPointer<ImageType>& image, itk::SmartPointer<ImageOutType>& outImage, std::string _MaskImageFile, std::string _opImageFile,
const OpFunctor& func)
328 typedef itk::Image<double, 4> ScalarImageType;
329 __SetImage(ScalarImageType, _MaskImageFile, mask, maskIt, -1);
338 (opImageVecSize)(imageVecSize).msg(
"wrong size of inputImage and opImage");
341 outImage = ImageOutType::New();
343 outImage->Allocate();
346 typename ImageType::IndexType index;
347 itk::VariableLengthVector<double> inPixel, outPixel, inTmp;
348 outPixel.SetSize(imageVecSize);
349 for (it.GoToBegin(), maskIt.GoToBegin(), opIt.GoToBegin(), outIt.GoToBegin();
351 ++it, ++maskIt, ++opIt, ++outIt)
353 if (_MaskImageFile!=
"" && maskIt.Get()<=0)
354 { outPixel.Fill(0.0); outIt.
SetVector(outPixel);
continue; }
356 index = it.GetIndex();
358 { outPixel.Fill(0.0); outIt.
SetVector(outPixel);
continue; }
360 it.GetVector(inPixel);
364 for (
int i = 0; i < inPixel.GetSize(); ++i )
365 outPixel[i] = func(inPixel[i], opValue);
369 opIt.GetVector(inTmp);
370 for (
int i = 0; i < inPixel.GetSize(); ++i )
371 outPixel[i] = inTmp.Size()==1 ? func(inPixel[i], inTmp[0]) : func(inPixel[i], inTmp[i]);
376 std::cout <<
"index = " << index << std::endl << std::flush;
380 outIt.SetVector(outPixel);
457 template <
class ImageType,
class ImageOutType>
465 if (_AxisArg.isSet())
471 std::string _InputImageFile, _OutputImageFile;
472 GetImageFiles(_ImageFiles, _InputImageFile, _OutputImageFile);
474 typedef itk::Image<double,4> Scalar4DImageType;
475 typename Scalar4DImageType::Pointer mask = Scalar4DImageType::New();
476 if (_MaskImageFileArg.isSet())
481 typedef typename ImageType::Pointer ImagePointer;
482 typename ImageType::Pointer image = ImageType::New();
483 typename NDImageType::Pointer imagePermute = NDImageType::New();
484 typename ImageOutType::Pointer outImage = ImageOutType::New();
489 std::vector<ImagePointer> imageVec(_ImageFiles.size()-1);
490 for (
int i = 0; i < _ImageFiles.size()-1; ++i )
492 itk::ReadImage<ImageType>(_ImageFiles[i], imageVec[i]);
500 _realBox[0] = _realBox[0]<0 ? 0 : (_realBox[0]>_size[0]-1 ? _size[0]-1 : _realBox[0]);
501 _realBox[1] = _realBox[1]==-1 ? _size[0]-1 : (_realBox[1]<0 ? 0 : (_realBox[1]>_size[0]-1 ? _size[0]-1 : _realBox[1]) );
502 _realBox[2] = _realBox[2]<0 ? 0 : (_realBox[2]>_size[1]-1 ? _size[1]-1 : _realBox[2]);
503 _realBox[3] = _realBox[3]==-1 ? _size[1]-1 : (_realBox[3]<0 ? 0 : (_realBox[3]>_size[1]-1 ? _size[1]-1 : _realBox[3]) );
504 _realBox[4] = _realBox[4]<0 ? 0 : (_realBox[4]>_size[2]-1 ? _size[2]-1 : _realBox[4]);
505 _realBox[5] = _realBox[5]==-1 ? _size[2]-1 : (_realBox[5]<0 ? 0 : (_realBox[5]>_size[2]-1 ? _size[2]-1 : _realBox[5]) );
508 if (_AddImageFileArg.isSet())
511 BinaryOPImage<ImageType, ImageOutType>(image, outImage, _MaskImageFile, _AddImageFile, std::plus<double>());
513 if (_MinusImageFileArg.isSet())
516 BinaryOPImage<ImageType, ImageOutType>(image, outImage, _MaskImageFile, _MinusImageFile, std::minus<double>());
518 if (_MultiplyImageFileArg.isSet())
521 BinaryOPImage<ImageType, ImageOutType>(image, outImage, _MaskImageFile, _MultiplyImageFile, std::multiplies<double>());
523 if (_DivideImageFileArg.isSet())
526 BinaryOPImage<ImageType, ImageOutType>(image, outImage, _MaskImageFile, _DivideImageFile, std::divides<double>());
528 if (_MaxImageFileArg.isSet())
533 if (_MinImageFileArg.isSet())
538 if (_PowImageFileArg.isSet())
546 if (_FunctorArg.isSet())
561 if (_NormArg.isSet())
582 if (_CropArg.isSet())
585 std::vector<int> cropBox(8,-1);
587 for (
int i = 0; i < _Crop.size(); ++i )
588 cropBox[i] = _Crop[i];
589 cropBox[0] = cropBox[0]<0 ? 0 : (cropBox[0]>_size[0]-1 ? _size[0]-1 : cropBox[0]);
590 cropBox[1] = cropBox[1]==-1 ? _size[0]-1 : (cropBox[1]<0 ? 0 : (cropBox[1]>_size[0]-1 ? _size[0]-1 : cropBox[1]) );
591 cropBox[2] = cropBox[2]<0 ? 0 : (cropBox[2]>_size[1]-1 ? _size[1]-1 : cropBox[2]);
592 cropBox[3] = cropBox[3]==-1 ? _size[1]-1 : (cropBox[3]<0 ? 0 : (cropBox[3]>_size[1]-1 ? _size[1]-1 : cropBox[3]) );
593 cropBox[4] = cropBox[4]<0 ? 0 : (cropBox[4]>_size[2]-1 ? _size[2]-1 : cropBox[4]);
594 cropBox[5] = cropBox[5]==-1 ? _size[2]-1 : (cropBox[5]<0 ? 0 : (cropBox[5]>_size[2]-1 ? _size[2]-1 : cropBox[5]) );
595 cropBox[6] = cropBox[6]<0 ? 0 : (cropBox[6]>dimT-1 ? dimT-1 : cropBox[6]);
596 cropBox[7] = cropBox[7]==-1 ? dimT-1 : (cropBox[7]<0 ? 0 : (cropBox[7]>dimT-1 ? dimT-1 : cropBox[7]) );
601 if (cropBox[6]==0 && cropBox[7]==dimT-1)
604 typename ImageType::Pointer imageTmp = ImageType::New();
605 typename ImageType::IndexType desiredStart;
606 typename ImageType::SizeType desiredSize;
608 for (
int i = 0; i < ImageType::ImageDimension; ++i )
609 desiredStart[i] = cropBox[2*i];
610 for (
int i = 0; i < ImageType::ImageDimension; ++i )
611 desiredSize[i] = cropBox[2*i+1]-cropBox[2*i]+1;
613 typename ImageType::RegionType desiredRegion(desiredStart, desiredSize);
615 typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > FilterType;
616 typename FilterType::Pointer filter = FilterType::New();
617 filter->SetRegionOfInterest(desiredRegion);
618 filter->SetInput(image);
620 imageTmp = filter->GetOutput();
630 typename ImageOutType::Pointer imageTmp = ImageOutType::New();
631 itk::UnaryVectorOPImage<ImageType, ImageOutType>(image, imageTmp, op, mask,
_numberOfThreads);
633 if (cropBox[0]==0 && cropBox[1]==_size[0]-1 && cropBox[2]==0 && cropBox[3]==_size[1]-1 && cropBox[4]==0 && cropBox[5]==_size[2]-1)
641 typename ImageOutType::IndexType desiredStart;
642 typename ImageOutType::SizeType desiredSize;
644 for (
int i = 0; i < ImageOutType::ImageDimension; ++i )
645 desiredStart[i] = cropBox[2*i];
646 for (
int i = 0; i < ImageOutType::ImageDimension; ++i )
647 desiredSize[i] = cropBox[2*i+1]-cropBox[2*i]+1;
650 if (ImageOutType::ImageDimension==4)
653 desiredSize[3] = cropBox[7]-cropBox[6]+1;
656 typename ImageOutType::RegionType desiredRegion(desiredStart, desiredSize);
658 typedef itk::RegionOfInterestImageFilter< ImageOutType, ImageOutType > FilterType;
659 typename FilterType::Pointer filter = FilterType::New();
660 filter->SetRegionOfInterest(desiredRegion);
661 filter->SetInput(imageTmp);
663 outImage = filter->GetOutput();
670 else if (_ImageFiles.size()==2)
673 BinaryOPImage<ImageType, ImageOutType>(image, outImage, _MaskImageFile,
utl::ConvertNumberToString(1.0), std::multiplies<double>());
687 main (
int argc,
char const* argv[])
693 std::string _InputImageFile, _OutputImageFile;
694 GetImageFiles(_ImageFiles, _InputImageFile, _OutputImageFile);
696 if (!_OutputFormatArg.isSet() || (_OutputFormatArg.isSet() && _OutputFormat==
"NONE"))
699 return ImageMath<VectorImageType, VectorImageType>(argc, argv);
701 return ImageMath<NDImageType, NDImageType>(argc, argv);
706 return ImageMath<VectorImageType, VectorImageType>(argc, argv);
708 return ImageMath<VectorImageType, NDImageType>(argc, argv);
710 return ImageMath<NDImageType, VectorImageType>(argc, argv);
712 return ImageMath<NDImageType, NDImageType>(argc, argv);
NDArray<T,1> is a vector class which uses blas mkl.
bool Is3DImage(const std::string &filename)
#define __UnaryScalarFunctor(argNoAxis, opNoAxis, funcName)
helper functions specifically used in dmritool
bool IsNumber(const std::string &input)
#define __SetImage(ImageType, fileName, imageName, imageItName, axis)
void MultiVolumeToVectorImage(const SmartPointer< Image< ScalarType, Dim+1 > > &image1, SmartPointer< VectorImage< ScalarType, Dim > > &image2)
#define __XYZTMultiVectorFunctor_FixedSize(axisNum, argNoAxis, opNoAxis, funcName, inSize)
std::string ConvertNumberToString(const T value, const int precision=6)
#define utlSAGlobalException(expr)
bool SaveImage(const SmartPointer< ImageType > &image, const std::string &filename, const std::string &printInfo="Writing Image:")
#define __XYZTUnaryVectorFunctor(axisNum, argNoAxis, opNoAxis, funcName)
void ConvertImage< VectorImageType, NDImageType >(const itk::SmartPointer< VectorImageType > &image, itk::SmartPointer< NDImageType > &imageOut)
#define _SetOperationWithChecking(op, value, numberOfInputsCond)
void PrintVariableLengthVector(const VariableLengthVector< T >vec, const std::string &str="", const char *separate=" ", std::ostream &os=std::cout)
void SetOperationWithChecking(int &op, int value)
int ImageMath(int argc, char const *argv[])
std::string StringToUpperCase(const std::string &str)
bool IsLogDebug(const int level=utl::LogLevel)
#define __FunctionFromStringOpImage(funcStr)
virtual void SetSpace(const int _arg)
bool ReadImage(const std::string &filename, SmartPointer< ImageType > &image, const std::string &printInfo="Reading Image:")
void CopyImageInformation(const SmartPointer< ImageWithInfoType > &imageFrom, SmartPointer< ImageType > &imageTo)
#define utlGlobalException(cond, expout)
virtual void SetOffset(const int _arg)
int GetNumberFromAxis(std::string axis)
#define utlPrintVar(cond,...)
std::vector< int > GetVectorImage3DVolumeSize(const SmartPointer< ImageType > &image)
void BinaryOPImage(const itk::SmartPointer< ImageType > &image, itk::SmartPointer< ImageOutType > &outImage, std::string _MaskImageFile, std::string _opImageFile, const OpFunctor &func)
void GetImageFiles(const std::vector< std::string > &imageVec, std::string &inImage0, std::string &outImage)
int main(int argc, char const *argv[])
4DImage math. It works for both itk::Image<double,4> and itk::VectorImage<double,3> ...
int GetVectorImageVectorSize(const SmartPointer< ImageType > &image, const int axis=-1)
void PrintVector(const std::vector< T > &vec, const std::string &str="", const char *separate=" ", std::ostream &os=std::cout, bool showStats=true)
#define __XYZTUnaryVectorFunctorWithArguments(axisNum, argNoAxis, opNoAxis, funcName)
#define __SetImageOrScalar(ImageType, fileName, imageName, imageItName, valueName)
#define __XYZTMultiVectorFunctor(axisNum, argNoAxis, opNoAxis, funcName)
void ConvertImage< NDImageType, VectorImageType >(const itk::SmartPointer< NDImageType > &image, itk::SmartPointer< VectorImageType > &imageOut)
itk::Image< ScalarType, 4 > NDImageType
void VectorToMultiVolumeImage(const SmartPointer< VectorImage< ScalarType, Dim > > &image1, SmartPointer< Image< ScalarType, Dim+1 > > &image2)
obtain a part of a vector.
bool IsVectorImage(const std::string &filename)
itk::VectorImage< ScalarType, 3 > VectorImageType
void ConvertImage(const itk::SmartPointer< ImageType > &image, itk::SmartPointer< Image2Type > &imageOut)
bool IsOutsideBox(const IndexType &index, const std::vector< int > &box)
std::vector< int > _realBox
A multi-dimensional iterator templated over image type. It provides the same interfaces for both itk:...
virtual void SetChunkSize(const int _arg)
void SetVector(const PixelVectorType &value, const int offIndex=0) const