ITK  5.0.0
Insight Segmentation and Registration Toolkit
LinearAnisotropicDiffusionCommandLine.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 //
19 // Created by Jean-Marie Mirebeau on 01/12/2014.
20 //
21 //
22 
23 #ifndef itkLinearAnisotropicDiffusionCommandLine_h
24 #define itkLinearAnisotropicDiffusionCommandLine_h
25 
26 #include "itkImageFileReader.h"
27 #include "itkImageFileWriter.h"
29 
30 namespace LinearAnisotropicDiffusionCommandLine
31 {
32 
33 void Usage(){
34  std::cerr <<
35  "Input image filename. 2D and 3D images supported. Required.\n" <<
36  "Output tensor field filename. Required.\n" <<
37  "Diffusion time. Required.\n" <<
38  "Output image filename. Required.\n" <<
39  "RatioToMaxStableStep. Range: ]0,1]. Default: 0.7. Optionnal.\n" <<
40  "MaxNumberOfIterations. Range: 1...Infinity. Default: 200. Optionnal.\n"
41  << "\n";
42 }
43 
44 using namespace itk;
45 
46 int Execute(int argc, char * argv[]);
47 
48 template<int VDimension>
49 int Execute(int argc, char * argv[], itk::ImageIOBase::IOComponentType, int nComponents);
50 
51 template<int VDimension, typename ScalarType, typename ComponentType>
52 int Execute(int argc, char * argv[], int nComponents);
53 
54 template<int VDimension, typename ScalarType, typename PixelType, typename ExportPixelType>
55 int Execute(int argc, char * argv[]);
56 
57 
59 {
60  itkNewMacro(ReportProgressToCOutType);
61  void Execute(itk::Object *caller, const itk::EventObject & event) override{
62  Execute( (const itk::Object *)caller, event);
63  }
64 
65  void Execute(const itk::Object * object, const itk::EventObject &) override{
66  std::cout << object->GetNameOfClass() << " has completed: "
67  << int(100*dynamic_cast<const itk::ProcessObject*>(object)->GetProgress())
68  << "%" << std::endl;
69  }
70 };
71 
72 
73 int Execute(int argc, char * argv[])
74 {
75  using std::cerr;
76  using std::endl;
77  using namespace itk;
78 
79  if(argc<4+1) {Usage(); return EXIT_SUCCESS;}
80 
81  const char *imageFileName =argv[0+1];
82  using ReaderType = ImageFileReader<Image<unsigned char,3> >;
83  ReaderType::Pointer reader = ReaderType::New();
84  reader->SetFileName(imageFileName);
85 
86  reader->UpdateOutputInformation();
87 
88  const ImageIOBase * io = reader->GetImageIO();
89  const int ImageDimension = io->GetNumberOfDimensions();
90  const itk::ImageIOBase::IOComponentType componentType = io->GetComponentType();
91  const int nComponents = io->GetNumberOfComponents();
92 
93  {
94  const char *tensorFileName = argv[1+1];
95  ReaderType::Pointer reader2 = ReaderType::New();
96  reader2->SetFileName(tensorFileName);
97  reader2->UpdateOutputInformation();
98  const ImageIOBase * io2 = reader2->GetImageIO();
99  if(io2->GetComponentType() != componentType)
100  std::cerr << "Warning: image and tensors have distinct component types.\n";
101  if(ImageDimension != (int)io2->GetNumberOfDimensions())
102  itkGenericExceptionMacro("Error: image and tensor image have distinct dimension");
103  const int TensorDimension = (ImageDimension*(ImageDimension+1))/2;
104  if(TensorDimension != (int)io2->GetNumberOfComponents())
105  itkGenericExceptionMacro("Error: wrong tensor dimension, should be n*(n+1)/2 where n=ImageDimension.");
107  std::cerr << "Warning: tensor image pixel type not marked as Symmetric Second Rank Tensor.\n";
108  }
109 
110  switch (ImageDimension) {
111  case 2: return Execute<2>(argc,argv,componentType,nComponents);
112 // case 3: return Execute<3>(argc,argv,componentType,nComponents);
113  default: itkGenericExceptionMacro("Sorry, unsupported image dimension.");
114  }
115 }
116 
117 template<int Dimension>
118 int Execute(int argc, char * argv[], itk::ImageIOBase::IOComponentType componentType, int nComponents){
119  switch (componentType) {
120  case itk::ImageIOBase::UCHAR: return Execute<Dimension, float, unsigned char>(argc,argv,nComponents);
121  case itk::ImageIOBase::FLOAT: return Execute<Dimension, float, float>(argc,argv,nComponents);
122  case itk::ImageIOBase::DOUBLE:return Execute<Dimension, double, double>(argc,argv,nComponents);
123  default: itkGenericExceptionMacro("Sorry, unsupported component type");
124  }
125 }
126 
127 template<int Dimension, typename ScalarType, typename ComponentType>
128 int Execute(int argc, char * argv[], int nComponents){
129  switch (nComponents) {
130  case 1: return Execute<Dimension,ScalarType,ScalarType,ComponentType>(argc,argv);
131  case 2: return Execute<Dimension,ScalarType,Vector<ScalarType,2>,Vector<ComponentType,2> >(argc,argv);
132  case 3: return Execute<Dimension,ScalarType,Vector<ScalarType,3>,Vector<ComponentType,3> >(argc,argv);
133  default: itkGenericExceptionMacro("Sorry, unsupported number of components");
134  }
135 }
136 
137 template<int Dimension, typename ScalarType, typename PixelType, typename ExportPixelType>
138 int Execute(int argc, char * argv[]){
139 
140  // Import image
141  using ImageType = Image<PixelType,Dimension>;
142  using ReaderType = ImageFileReader<ImageType>;
143  typename ReaderType::Pointer reader = ReaderType::New();
144  const char *imageFileName =argv[0+1];
145  reader->SetFileName(imageFileName);
146 
147  // Import tensors
149  using TensorImageType = Image<TensorType,Dimension>;
150  using TensorReaderType = ImageFileReader<TensorImageType>;
151  typename TensorReaderType::Pointer tensorReader = TensorReaderType::New();
152  const char * tensorImageFileName = argv[1+1];
153  tensorReader->SetFileName(tensorImageFileName);
154 
155  // Import diffusion time
156  const double diffusionTime = std::stod(argv[2+1]);
157  if(diffusionTime==0) itkGenericExceptionMacro("Error: Unrecognized diffusion time (third argument).\n");
158 
159  // Import output image filename
160  const char *outputFileName = argv[3+1];
161 
162  // Setup diffusion filter
164  typename DiffusionFilterType::Pointer diffusionFilter = DiffusionFilterType::New();
165  diffusionFilter->SetInputImage(reader->GetOutput());
166  diffusionFilter->SetInputTensor(tensorReader->GetOutput());
167  diffusionFilter->SetMaxDiffusionTime(diffusionTime);
168 
169  int argIndex = 4+1;
170  if(argIndex<argc){
171  const double ratioToMaxStableTimeStep = std::stod(argv[argIndex++]);
172  if(ratioToMaxStableTimeStep==0) itkGenericExceptionMacro("Error: Unrecognized RatioToMaxStableTimeStep (fourth argument).\n");
173  diffusionFilter->SetRatioToMaxStableTimeStep(ratioToMaxStableTimeStep);
174  }
175 
176  if(argIndex<argc){
177  const int maxNumberOfTimeSteps = std::stoi(argv[argIndex++]);
178  if(maxNumberOfTimeSteps==0) itkGenericExceptionMacro("Error: Unrecognized maxNumberOfTimeSteps (fifth argument).\n");
179  diffusionFilter->SetMaxNumberOfTimeSteps(maxNumberOfTimeSteps);
180  } else
181  diffusionFilter->SetMaxNumberOfTimeSteps(200);
182 
184  diffusionFilter->AddObserver(ProgressEvent(), reportDiffusionProgress);
185 
186  using ExportImageType = Image<ExportPixelType,Dimension>;
188  typename CasterType::Pointer caster = CasterType::New();
189  caster->SetInput(diffusionFilter->GetOutput());
190 
191  //using ScalarImageType = typename DiffusionFilterType::ScalarImageType;
192  using WriterType = ImageFileWriter<ExportImageType>;
193  typename WriterType::Pointer writer = WriterType::New();
194  writer->SetInput(caster->GetOutput());
195  writer->SetFileName(outputFileName);
196  writer->Update();
197 
198  const ScalarType effectiveDiffusionTime=diffusionFilter->GetEffectiveDiffusionTime();
199  if(effectiveDiffusionTime < 0.99 * diffusionTime){
200  std::cerr <<
201  "Warning: early abort at effective diffusion time: " << effectiveDiffusionTime <<
202  ", you may want to increase the max number of time steps: " << diffusionFilter->GetMaxNumberOfTimeSteps() << "\n";
203  Usage();
204  }
205 
206  return EXIT_SUCCESS;
207 }
208 
209 } // end namespace LinearAnisotropicDiffusionCommandLine
210 
211 #endif
Abstract superclass defines image IO interface.
Represent a symmetric tensor of second rank.
void Execute(itk::Object *caller, const itk::EventObject &event) override
Anisotropic diffusion using lattice basis reduction.
A templated class holding a n-Dimensional vector.
Definition: itkVector.h:62
Abstraction of the Events used to communicating among filters and with GUIs.
SmartPointer< Self > Pointer
Definition: itkCommand.h:52
virtual IOComponentType GetComponentType() const
Writes image data to a single file.
virtual IOPixelType GetPixelType() const
Data source that reads image data from a single file.
virtual const unsigned int & GetNumberOfComponents() const
virtual unsigned int GetNumberOfDimensions() const
Base class for most ITK classes.
Definition: itkObject.h:60
Superclass for callback/observer methods.
Definition: itkCommand.h:44
Templated n-dimensional image class.
Definition: itkImage.h:75
Casts input pixels to output pixel type.
void Execute(const itk::Object *object, const itk::EventObject &) override