ANIMA  4.0
animaNLMeansTemporal.cxx
Go to the documentation of this file.
3 
4 #include <tclap/CmdLine.h>
5 
6 #include <itkImage.h>
7 #include <itkCommand.h>
8 
9 //Update progression of the process
10 void eventCallback (itk::Object* caller, const itk::EventObject& event, void* clientData)
11 {
12  itk::ProcessObject * processObject = (itk::ProcessObject*) caller;
13  std::cout<<"\033[K\rProgression: "<<(int)(processObject->GetProgress() * 100)<<"%"<<std::flush;
14 }
15 
16 int main(int ac, const char** av)
17 {
18 
19  TCLAP::CmdLine cmd("INRIA / IRISA - VisAGeS/Empenn Team", ' ',ANIMA_VERSION);
20 
21  TCLAP::ValueArg<std::string> inputArg("i",
22  "input",
23  "A noisy image",
24  true,
25  "",
26  "A noisy image",
27  cmd);
28 
29  TCLAP::ValueArg<std::string> outputArg("o",
30  "output",
31  "Output denoised image",
32  true,
33  "",
34  "Output denoised image",
35  cmd);
36 
37  TCLAP::ValueArg<unsigned int> weightMethod("W",
38  "weight",
39  "Thr weight method -> 0: Exponential, 1: Rician, default: Exponential(0)",
40  false,
41  0,
42  "The Weighting method",
43  cmd);
44 
45  TCLAP::ValueArg<double> weightThrArg("w",
46  "weightThr",
47  "Weight threshold: patches around have to be similar enough -> default: 0.0",
48  false,
49  0.0,
50  "Weight threshold",
51  cmd);
52 
53  TCLAP::ValueArg<double> betaArg("b",
54  "beta",
55  "Beta parameter for local noise estimation -> default: 1",
56  false,
57  1,
58  "Beta for local noise estimation",
59  cmd);
60 
61  TCLAP::ValueArg<double> meanMinArg("m",
62  "meanMin",
63  "Minimun mean threshold (default: 0.95)",
64  false,
65  0.95,
66  "Minimun mean threshold",
67  cmd);
68 
69  TCLAP::ValueArg<double> varMinArg("v",
70  "varMin",
71  "Minimun variance threshold -> default: 0.5",
72  false,
73  0.5,
74  "Minimun variance threshold",
75  cmd);
76 
77  TCLAP::ValueArg<unsigned int> nbpArg("p",
78  "nbp",
79  "Number of threads to run on -> default : automatically determine",
80  false,
81  itk::MultiThreaderBase::GetGlobalDefaultNumberOfThreads(),
82  "Number of threads",
83  cmd);
84 
85  TCLAP::ValueArg<unsigned int> patchHSArg("S",
86  "patchHalfSize",
87  "Patch half size in each direction -> default: 1",
88  false,
89  1,
90  "patch half size",
91  cmd);
92 
93  TCLAP::ValueArg<unsigned int> patchSSArg("s",
94  "patchStepSize",
95  "Patch step size for searching -> default: 1",
96  false,
97  1,
98  "Patch search step size",
99  cmd);
100 
101  TCLAP::ValueArg<unsigned int> patchNeighArg("n",
102  "patchNeighborhood",
103  "Patch half neighborhood size -> default: 5",
104  false,
105  5,
106  "Patch search neighborhood size",
107  cmd);
108 
109  try
110  {
111  cmd.parse(ac,av);
112  }
113  catch (TCLAP::ArgException& e)
114  {
115  std::cerr << "Error: " << e.error() << "for argument " << e.argId() << std::endl;
116  return EXIT_FAILURE;
117  }
118 
119  // Find out the type of the image in file
120  itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(inputArg.getValue().c_str(),
121  itk::ImageIOFactory::ReadMode);
122 
123  if( !imageIO )
124  {
125  std::cerr << "Itk could not find a suitable IO factory for the input" << std::endl;
126  return EXIT_FAILURE;
127  }
128 
129  // Now that we found the appropriate ImageIO class, ask it to read the meta data from the image file.
130  imageIO->SetFileName(inputArg.getValue());
131  imageIO->ReadImageInformation();
132 
133  itk::CStyleCommand::Pointer callback = itk::CStyleCommand::New();
134  callback->SetCallback(eventCallback);
135 
136  unsigned int const nbDimension = imageIO->GetNumberOfDimensions ();
137  std::cout<<"Image has "<<nbDimension<<" dimension.\n";
138 
139  switch(nbDimension)
140  {
141  case 2:
142  {
143  std::cerr<<"ERROR !\nInput has only two dimension, you should use the animaNLMeans command.";
144  return 0;
145  }
146 
147  case 3:
148  {
149 
150  std::cerr<<"This command is designed for temporal images.\nIf you want to compute a simple volume, you should use the animaNLMeans command.\nContinue? (y/n) ";
151  char ans;
152  do
153  {
154 
155  std::cin>>ans;
156  if (ans == 'n')
157  return 0;
158 
159  else if (ans != 'y')
160  {
161  std::cerr<<"Please press \"n\" or \"y\".\nContinue? (y/n) ";
162  }
163  }
164  while(ans != 'y');
165 
166  std::cout<<"preparing filter..." << std::endl;
167 
168  typedef itk::Image<double, 3> ImageType;
170 
171  FilterType::Pointer filter = FilterType::New();
172  filter->SetInput(anima::readImage <ImageType> (inputArg.getValue()));
173 
174  filter->SetWeightThreshold(weightThrArg.getValue());
175  filter->SetPatchHalfSize(patchHSArg.getValue());
176  filter->SetSearchStepSize(patchSSArg.getValue());
177  filter->SetSearchNeighborhood(patchNeighArg.getValue());
178  filter->SetBetaParameter(betaArg.getValue());
179  filter->SetMeanMinThreshold(meanMinArg.getValue());
180  filter->SetVarMinThreshold(varMinArg.getValue());
181  filter->SetWeightMethod(FilterType::EXP);
182  if (weightMethod.getValue())
183  filter->SetWeightMethod(FilterType::RICIAN);
184 
185  filter->SetNumberOfWorkUnits(nbpArg.getValue());
186 
187  filter->Update();
188 
189  try
190  {
191  anima::writeImage <ImageType> (outputArg.getValue(),filter->GetOutput());
192  }
193  catch( itk::ExceptionObject & err )
194  {
195  std::cerr << "Itk cannot write output, be sure to use a valid extension..." << std::endl;
196  std::cerr << err << std::endl;
197  return EXIT_FAILURE;
198  }
199  break;
200  }
201  case 4:
202  {
203  std::cout<<"preparing filter..." << std::endl;
204 
205  typedef itk::Image<double, 4> ImageType;
207 
208  FilterType::Pointer filter = FilterType::New();
209  filter->SetInput(anima::readImage <ImageType> (inputArg.getValue()));
210 
211  filter->SetWeightThreshold(weightThrArg.getValue());
212  filter->SetPatchHalfSize(patchHSArg.getValue());
213  filter->SetSearchStepSize(patchSSArg.getValue());
214  filter->SetSearchNeighborhood(patchNeighArg.getValue());
215  filter->SetBetaParameter(betaArg.getValue());
216  filter->SetMeanMinThreshold(meanMinArg.getValue());
217  filter->SetVarMinThreshold(varMinArg.getValue());
218  filter->SetWeightMethod(FilterType::EXP);
219  if (weightMethod.getValue())
220  filter->SetWeightMethod(FilterType::RICIAN);
221 
222  filter->SetNumberOfWorkUnits(nbpArg.getValue());
223 
224  filter->AddObserver(itk::ProgressEvent(), callback );
225  filter->Update();
226 
227  try
228  {
229  anima::writeImage <ImageType> (outputArg.getValue(),filter->GetOutput());
230  }
231  catch( itk::ExceptionObject & err )
232  {
233  std::cerr << "Itk cannot write output, be sure to use a valid extension..." << std::endl;
234  std::cerr << err << std::endl;
235  return EXIT_FAILURE;
236  }
237  break;
238  }
239  default:
240  {
241  itk::ExceptionObject excp;
242  excp.SetDescription("The file uses a number of dimension that is not supported in this application");
243  throw excp;
244  }
245  }
246 
247  std::cout << std::endl;
248 
249  return EXIT_SUCCESS;
250 }
251 
int main(int ac, const char **av)
void eventCallback(itk::Object *caller, const itk::EventObject &event, void *clientData)