ANIMA  4.0
animaImageArithmetic.cxx
Go to the documentation of this file.
1 #include <tclap/CmdLine.h>
2 
4 #include <itkImage.h>
5 #include <itkVectorImage.h>
6 #include <itkImageRegionIterator.h>
7 
8 #include <itkAddImageFilter.h>
9 #include <itkSubtractImageFilter.h>
10 #include <itkDivideImageFilter.h>
11 #include <itkMultiplyImageFilter.h>
12 #include <itkPowImageFilter.h>
13 
14 template <class ImageType>
15 void computeArithmetic (std::string &inStr, std::string &outStr, std::string &multImStr, std::string &divImStr, std::string &addImStr,
16  std::string &subImStr, double multConstant, double divideConstant, double addConstant, double subConstant,
17  double powConstant, unsigned int nThreads)
18 {
19  typedef itk::Image <double, ImageType::ImageDimension> WorkImageType;
20  typedef itk::AddImageFilter <ImageType,ImageType,ImageType> AddFilterType;
21  typedef itk::AddImageFilter <ImageType,WorkImageType,ImageType> AddConstantFilterType;
22  typedef itk::SubtractImageFilter <ImageType,ImageType,ImageType> SubtractFilterType;
23  typedef itk::SubtractImageFilter <ImageType,WorkImageType,ImageType> SubtractConstantFilterType;
24 
25  typedef itk::MultiplyImageFilter <ImageType,WorkImageType,ImageType> MultiplyFilterType;
26  typedef itk::DivideImageFilter <ImageType,WorkImageType,ImageType> DivideFilterType;
27 
28  typename ImageType::Pointer currentImage = anima::readImage <ImageType> (inStr);
29  currentImage->DisconnectPipeline();
30 
31  if (multImStr != "")
32  {
33  typedef itk::ImageFileReader <WorkImageType> MultiplyReaderType;
34  typename MultiplyReaderType::Pointer multImReader = MultiplyReaderType::New();
35  multImReader->SetFileName(multImStr);
36  multImReader->Update();
37 
38  typename MultiplyFilterType::Pointer multFilter = MultiplyFilterType::New();
39  multFilter->SetInput1(currentImage);
40  multFilter->SetInput2(multImReader->GetOutput());
41  multFilter->SetNumberOfWorkUnits(nThreads);
42  multFilter->InPlaceOn();
43 
44  multFilter->Update();
45  currentImage = multFilter->GetOutput();
46  currentImage->DisconnectPipeline();
47  }
48 
49  if (multConstant != 1.0)
50  {
51  typename MultiplyFilterType::Pointer multFilter = MultiplyFilterType::New();
52  multFilter->SetInput1(currentImage);
53  multFilter->SetConstant(multConstant);
54  multFilter->SetNumberOfWorkUnits(nThreads);
55  multFilter->InPlaceOn();
56 
57  multFilter->Update();
58  currentImage = multFilter->GetOutput();
59  currentImage->DisconnectPipeline();
60  }
61 
62  if ((divideConstant != 0.0)&&(divideConstant != 1.0))
63  {
64  typename DivideFilterType::Pointer divFilter = DivideFilterType::New();
65  divFilter->SetInput1(currentImage);
66  divFilter->SetConstant(divideConstant);
67  divFilter->SetNumberOfWorkUnits(nThreads);
68  divFilter->InPlaceOn();
69 
70  divFilter->Update();
71  currentImage = divFilter->GetOutput();
72  currentImage->DisconnectPipeline();
73  }
74 
75  if (divImStr != "")
76  {
77  typedef itk::ImageFileReader <WorkImageType> DivideReaderType;
78  typename DivideReaderType::Pointer divImReader = DivideReaderType::New();
79  divImReader->SetFileName(divImStr);
80  divImReader->Update();
81 
82  typename DivideFilterType::Pointer divFilter = DivideFilterType::New();
83  divFilter->SetInput1(currentImage);
84  divFilter->SetInput2(divImReader->GetOutput());
85  divFilter->SetNumberOfWorkUnits(nThreads);
86  divFilter->InPlaceOn();
87 
88  divFilter->Update();
89  currentImage = divFilter->GetOutput();
90  currentImage->DisconnectPipeline();
91 
92  itk::ImageRegionIterator <WorkImageType> divImItr (divImReader->GetOutput(),divImReader->GetOutput()->GetLargestPossibleRegion());
93  itk::ImageRegionIterator <ImageType> currentImageItr (currentImage,currentImage->GetLargestPossibleRegion());
94 
95  while (!currentImageItr.IsAtEnd())
96  {
97  // Multiplication by 0.0 since current image may be a vector
98  if (itk::Math::AlmostEquals(divImItr.Get(), itk::NumericTraits<typename WorkImageType::PixelType>::ZeroValue()))
99  currentImageItr.Set(currentImageItr.Get() * 0.0);
100 
101  ++currentImageItr;
102  ++divImItr;
103  }
104  }
105 
106  if (addImStr != "")
107  {
108  typename ImageType::Pointer addedImage = anima::readImage <ImageType> (addImStr);
109 
110  typename AddFilterType::Pointer addFilter = AddFilterType::New();
111  addFilter->SetInput1(currentImage);
112  addFilter->SetInput2(addedImage);
113  addFilter->SetNumberOfWorkUnits(nThreads);
114  addFilter->InPlaceOn();
115 
116  addFilter->Update();
117  currentImage = addFilter->GetOutput();
118  currentImage->DisconnectPipeline();
119  }
120 
121  if (subImStr != "")
122  {
123  typename ImageType::Pointer subtractedImage = anima::readImage <ImageType> (subImStr);
124 
125  typename SubtractFilterType::Pointer subFilter = SubtractFilterType::New();
126  subFilter->SetInput1(currentImage);
127  subFilter->SetInput2(subtractedImage);
128  subFilter->SetNumberOfWorkUnits(nThreads);
129  subFilter->InPlaceOn();
130 
131  subFilter->Update();
132  currentImage = subFilter->GetOutput();
133  currentImage->DisconnectPipeline();
134  }
135 
136  if (addConstant != 0.0)
137  {
138  typename AddConstantFilterType::Pointer addFilter = AddConstantFilterType::New();
139  addFilter->SetInput1(currentImage);
140  addFilter->SetConstant(addConstant);
141  addFilter->SetNumberOfWorkUnits(nThreads);
142  addFilter->InPlaceOn();
143 
144  addFilter->Update();
145  currentImage = addFilter->GetOutput();
146  currentImage->DisconnectPipeline();
147  }
148 
149  if (subConstant != 0.0)
150  {
151  typename SubtractConstantFilterType::Pointer subFilter = SubtractConstantFilterType::New();
152  subFilter->SetInput1(currentImage);
153  subFilter->SetConstant(subConstant);
154  subFilter->SetNumberOfWorkUnits(nThreads);
155  subFilter->InPlaceOn();
156 
157  subFilter->Update();
158  currentImage = subFilter->GetOutput();
159  currentImage->DisconnectPipeline();
160  }
161 
162  if (powConstant != 1.0)
163  {
164  typedef itk::Image <typename ImageType::IOPixelType, ImageType::ImageDimension> ScalarImageType;
165  typedef itk::PowImageFilter <ScalarImageType, WorkImageType, ScalarImageType> PowConstantFilterType;
166 
167  ScalarImageType *castImage = dynamic_cast <ScalarImageType *> (currentImage.GetPointer());
168  if (castImage)
169  {
170  typename PowConstantFilterType::Pointer powFilter = PowConstantFilterType::New();
171  powFilter->SetInput1(castImage);
172  powFilter->SetConstant(powConstant);
173  powFilter->SetNumberOfWorkUnits(nThreads);
174  powFilter->InPlaceOn();
175 
176  powFilter->Update();
177 
178  currentImage = dynamic_cast <ImageType *> (powFilter->GetOutput());
179  currentImage->DisconnectPipeline();
180  }
181  }
182 
183  // Finally write the result
184  anima::writeImage <ImageType> (outStr,currentImage);
185 }
186 
187 int main(int argc, char **argv)
188 {
189  std::string descriptionMessage = "Performs very basic mathematical operations on images: performs ( (I * m * M) / (D * d) + A + a - s - S)^P \n";
190  descriptionMessage += "This software has known limitations: you might have to use it several times in a row to perform the operation you want,\n";
191  descriptionMessage += "it requires the divide and multiply images to be scalar, and the add and subtract images to be of the same format as the input (although this is not verified).\n";
192  descriptionMessage += "INRIA / IRISA - VisAGeS/Empenn Team";
193 
194  TCLAP::CmdLine cmd(descriptionMessage, ' ',ANIMA_VERSION);
195 
196  TCLAP::ValueArg<std::string> inArg("i","input","Input image",true,"","input image",cmd);
197  TCLAP::ValueArg<std::string> outArg("o","output","output image",true,"","output image",cmd);
198 
199  TCLAP::ValueArg<std::string> multImArg("m","mult-image","multiply image",false,"","multiply image",cmd);
200  TCLAP::ValueArg<std::string> divImArg("d","div-image","divide image",false,"","divide image",cmd);
201  TCLAP::ValueArg<std::string> addImArg("a","add-image","add image",false,"","add image",cmd);
202  TCLAP::ValueArg<std::string> subtractImArg("s","sub-image","subtract image",false,"","subtract image",cmd);
203 
204  TCLAP::ValueArg<double> multiplyConstantArg("M","multiply-constant","multiply constant value",false,1.0,"multiply constant value",cmd);
205  TCLAP::ValueArg<double> divideConstantArg("D","divide-constant","divide constant value",false,1.0,"divide constant value",cmd);
206  TCLAP::ValueArg<double> addConstantArg("A","add-constant","add constant value",false,0.0,"add constant value",cmd);
207  TCLAP::ValueArg<double> subtractConstantArg("S","sub-constant","Subtract constant value",false,0.0,"subtract constant value",cmd);
208  TCLAP::ValueArg<double> powArg("P","pow-constant","power constant value (only for scalar images)",false,1.0,"power constant value",cmd);
209 
210  TCLAP::ValueArg<unsigned int> nbpArg("T","numberofthreads","Number of threads to run on (default : all cores)",false,itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),"number of threads",cmd);
211 
212  try
213  {
214  cmd.parse(argc,argv);
215  }
216  catch (TCLAP::ArgException& e)
217  {
218  std::cerr << "Error: " << e.error() << "for argument " << e.argId() << std::endl;
219  return EXIT_FAILURE;
220  }
221 
222  typedef itk::Image <double, 3> ImageType;
223  typedef itk::Image <double, 4> Image4DType;
224  typedef itk::VectorImage <double, 3> VectorImageType;
225 
226  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(inArg.getValue().c_str(),
227  itk::ImageIOFactory::ReadMode);
228 
229  if (!imageIO)
230  {
231  std::cerr << "Unable to read input image " << inArg.getValue() << std::endl;
232  return EXIT_FAILURE;
233  }
234 
235  imageIO->SetFileName(inArg.getValue());
236  imageIO->ReadImageInformation();
237 
238  bool vectorImage = (imageIO->GetNumberOfComponents() > 1);
239  bool fourDimensionalImage = (imageIO->GetNumberOfDimensions() == 4);
240 
241  if (vectorImage)
242  computeArithmetic<VectorImageType>(inArg.getValue(),outArg.getValue(),multImArg.getValue(),divImArg.getValue(),addImArg.getValue(),
243  subtractImArg.getValue(),multiplyConstantArg.getValue(),divideConstantArg.getValue(),
244  addConstantArg.getValue(),subtractConstantArg.getValue(),powArg.getValue(),nbpArg.getValue());
245  else if (fourDimensionalImage)
246  computeArithmetic<Image4DType>(inArg.getValue(),outArg.getValue(),multImArg.getValue(),divImArg.getValue(),addImArg.getValue(),
247  subtractImArg.getValue(),multiplyConstantArg.getValue(),divideConstantArg.getValue(),
248  addConstantArg.getValue(),subtractConstantArg.getValue(),powArg.getValue(),nbpArg.getValue());
249  else
250  computeArithmetic<ImageType>(inArg.getValue(),outArg.getValue(),multImArg.getValue(),divImArg.getValue(),addImArg.getValue(),
251  subtractImArg.getValue(),multiplyConstantArg.getValue(),divideConstantArg.getValue(),
252  addConstantArg.getValue(),subtractConstantArg.getValue(),powArg.getValue(),nbpArg.getValue());
253 
254  return EXIT_SUCCESS;
255 }
void computeArithmetic(std::string &inStr, std::string &outStr, std::string &multImStr, std::string &divImStr, std::string &addImStr, std::string &subImStr, double multConstant, double divideConstant, double addConstant, double subConstant, double powConstant, unsigned int nThreads)
int main(int argc, char **argv)