Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ImageResampler.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 
18 #include "mitkCommandLineParser.h"
19 
20 #include <mitkIOUtil.h>
22 #include <mitkImage.h>
23 #include <mitkImageCast.h>
24 #include <mitkITKImageImport.h>
25 #include <mitkImageTimeSelector.h>
27 #include <mitkProperties.h>
28 
29 // ITK
30 #include <itksys/SystemTools.hxx>
31 #include <itkDirectory.h>
32 #include "itkLinearInterpolateImageFunction.h"
33 #include "itkWindowedSincInterpolateImageFunction.h"
34 #include "itkNearestNeighborInterpolateImageFunction.h"
35 #include "itkIdentityTransform.h"
36 #include "itkResampleImageFilter.h"
38 
39 using namespace std;
40 
41 typedef itk::Image<double, 3> InputImageType;
42 typedef itk::Image<unsigned char, 3> BinaryImageType;
43 
44 
45 static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol = false, bool nn = false)
46 {
47  // Convert to itk Images
48 
49  // Identify Transform
50  typedef itk::IdentityTransform<double, 3> T_Transform;
51  T_Transform::Pointer _pTransform = T_Transform::New();
52  _pTransform->SetIdentity();
53 
54  typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 3> WindowedSincInterpolatorType;
56 
57  typedef itk::LinearInterpolateImageFunction< InputImageType> LinearInterpolateImageFunctionType;
59 
60  typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageFunctionType;
62 
63 
64  if (!nn)
65  {
68  mitk::CastToItkImage(reference,itkReference);
69  mitk::CastToItkImage(moving,itkMoving);
70  typedef itk::ResampleImageFilter<InputImageType, InputImageType> ResampleFilterType;
71 
72 
74  resampler->SetInput(itkMoving);
75  resampler->SetReferenceImage( itkReference );
76  resampler->UseReferenceImageOn();
77  resampler->SetTransform(_pTransform);
78  if ( sincInterpol)
79  resampler->SetInterpolator(sinc_interpolator);
80  else
81  resampler->SetInterpolator(lin_interpolator);
82 
83  resampler->Update();
84 
85  // Convert back to mitk
87  result->InitializeByItk(resampler->GetOutput());
88  GrabItkImageMemory( resampler->GetOutput() , result );
89  return result;
90  }
91 
92 
95  mitk::CastToItkImage(reference,itkReference);
96  mitk::CastToItkImage(moving,itkMoving);
97 
98 
99  typedef itk::ResampleImageFilter<BinaryImageType, BinaryImageType> ResampleFilterType;
100 
101 
103  resampler->SetInput(itkMoving);
104  resampler->SetReferenceImage( itkReference );
105  resampler->UseReferenceImageOn();
106  resampler->SetTransform(_pTransform);
107  resampler->SetInterpolator(nn_interpolator);
108 
109  resampler->Update();
110  // Convert back to mitk
112  result->InitializeByItk(resampler->GetOutput());
113  GrabItkImageMemory( resampler->GetOutput() , result );
114  return result;
115 
116 }
117 
118 
119 static std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems)
120 {
121  std::stringstream ss(s);
122  std::string item;
123  while (std::getline(ss, item, delim))
124  {
125  elems.push_back(item);
126  }
127  return elems;
128 }
129 
130 static std::vector<std::string> split(const std::string &s, char delim)
131 {
132  std::vector < std::string > elems;
133  return split(s, delim, elems);
134 }
135 
136 
137 static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt = true, bool useNN = false)
138 {
139  if (!useNN)
140  {
142  CastToItkImage(input,itkImage);
143 
148  // Identity transform.
149  // We don't want any transform on our image except rescaling which is not
150  // specified by a transform but by the input/output spacing as we will see
151  // later.
152  // So no transform will be specified.
153  typedef itk::IdentityTransform<double, 3> T_Transform;
154 
155  // The resampler type itself.
156  typedef itk::ResampleImageFilter<InputImageType, InputImageType> T_ResampleFilter;
157 
158  // Prepare the resampler.
159  // Instantiate the transform and specify it should be the id transform.
160  T_Transform::Pointer _pTransform = T_Transform::New();
161  _pTransform->SetIdentity();
162 
163  // Instantiate the resampler. Wire in the transform and the interpolator.
165 
166  // Specify the input.
167  _pResizeFilter->SetInput(itkImage);
168 
169  _pResizeFilter->SetTransform(_pTransform);
170 
171  // Set the output origin.
172  _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin());
173 
174  // Compute the size of the output.
175  // The size (# of pixels) in the output is recomputed using
176  // the ratio of the input and output sizes.
177  InputImageType::SpacingType inputSpacing = itkImage->GetSpacing();
178  InputImageType::SpacingType outputSpacing;
179  const InputImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion();
180 
181  InputImageType::SizeType outputSize;
182  typedef InputImageType::SizeType::SizeValueType SizeValueType;
183 
184  // Set the output spacing.
185  outputSpacing[0] = spacing[0];
186  outputSpacing[1] = spacing[1];
187  outputSpacing[2] = spacing[2];
188 
189  outputSize[0] = static_cast<SizeValueType>(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5);
190  outputSize[1] = static_cast<SizeValueType>(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5);
191  outputSize[2] = static_cast<SizeValueType>(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5);
192 
193  _pResizeFilter->SetOutputSpacing(outputSpacing);
194  _pResizeFilter->SetSize(outputSize);
195 
196  typedef itk::LinearInterpolateImageFunction< InputImageType > LinearInterpolatorType;
198 
199 
200  typedef itk::WindowedSincInterpolateImageFunction< InputImageType, 4> WindowedSincInterpolatorType;
202 
203  if (useLinInt)
204  _pResizeFilter->SetInterpolator(lin_interpolator);
205  else
206  _pResizeFilter->SetInterpolator(sinc_interpolator);
207 
208  _pResizeFilter->Update();
209 
211  image->InitializeByItk(_pResizeFilter->GetOutput());
212  mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image);
213  return image;
214  }
215 
217  CastToItkImage(input,itkImage);
218 
223  // Identity transform.
224  // We don't want any transform on our image except rescaling which is not
225  // specified by a transform but by the input/output spacing as we will see
226  // later.
227  // So no transform will be specified.
228  typedef itk::IdentityTransform<double, 3> T_Transform;
229 
230  // The resampler type itself.
231  typedef itk::ResampleImageFilter<BinaryImageType, BinaryImageType> T_ResampleFilter;
232 
233  // Prepare the resampler.
234  // Instantiate the transform and specify it should be the id transform.
235  T_Transform::Pointer _pTransform = T_Transform::New();
236  _pTransform->SetIdentity();
237 
238  // Instantiate the resampler. Wire in the transform and the interpolator.
240 
241  // Specify the input.
242  _pResizeFilter->SetInput(itkImage);
243 
244  _pResizeFilter->SetTransform(_pTransform);
245 
246  // Set the output origin.
247  _pResizeFilter->SetOutputOrigin(itkImage->GetOrigin());
248 
249  // Compute the size of the output.
250  // The size (# of pixels) in the output is recomputed using
251  // the ratio of the input and output sizes.
252  BinaryImageType::SpacingType inputSpacing = itkImage->GetSpacing();
253  BinaryImageType::SpacingType outputSpacing;
254  const BinaryImageType::RegionType& inputSize = itkImage->GetLargestPossibleRegion();
255 
256  BinaryImageType::SizeType outputSize;
257  typedef BinaryImageType::SizeType::SizeValueType SizeValueType;
258 
259  // Set the output spacing.
260  outputSpacing[0] = spacing[0];
261  outputSpacing[1] = spacing[1];
262  outputSpacing[2] = spacing[2];
263 
264  outputSize[0] = static_cast<SizeValueType>(inputSize.GetSize()[0] * inputSpacing[0] / outputSpacing[0] + .5);
265  outputSize[1] = static_cast<SizeValueType>(inputSize.GetSize()[1] * inputSpacing[1] / outputSpacing[1] + .5);
266  outputSize[2] = static_cast<SizeValueType>(inputSize.GetSize()[2] * inputSpacing[2] / outputSpacing[2] + .5);
267 
268  _pResizeFilter->SetOutputSpacing(outputSpacing);
269  _pResizeFilter->SetSize(outputSize);
270 
271  typedef itk::NearestNeighborInterpolateImageFunction< BinaryImageType> NearestNeighborInterpolateImageType;
273  _pResizeFilter->SetInterpolator(nn_interpolator);
274 
275  _pResizeFilter->Update();
276 
278  image->InitializeByItk(_pResizeFilter->GetOutput());
279  mitk::GrabItkImageMemory( _pResizeFilter->GetOutput(), image);
280  return image;
281 
282 }
283 
285 static void SaveImage(std::string fileName, mitk::Image* image, std::string fileType )
286 {
287  std::cout << "----Save to " << fileName;
288 
289  mitk::IOUtil::Save(image, fileName);
290 }
291 
292 mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float* spacing, bool useLinInt = true)
293 {
294 
295  itk::Vector<double, 3> spacingVector;
296  spacingVector[0] = spacing[0];
297  spacingVector[1] = spacing[1];
298  spacingVector[2] = spacing[2];
299 
300  typedef itk::ResampleDwiImageFilter<short> ResampleFilterType;
301 
303  mitk::CastToItkImage(input, itkVectorImagePointer);
304 
306  resampler->SetInput( itkVectorImagePointer );
307  resampler->SetInterpolation(ResampleFilterType::Interpolate_Linear);
308  resampler->SetNewSpacing(spacingVector);
309  resampler->Update();
310 
311  mitk::Image::Pointer output = mitk::GrabItkImageMemory( resampler->GetOutput() );
314  mitk::DiffusionPropertyHelper propertyHelper( output );
315  propertyHelper.InitializeImage();
316 
317  return output;
318 }
319 
320 int main( int argc, char* argv[] )
321 {
322  mitkCommandLineParser parser;
323  parser.setArgumentPrefix("--","-");
324 
325  parser.setTitle("Image Resampler");
326  parser.setCategory("Preprocessing Tools");
327  parser.setContributor("MBI");
328  parser.setDescription("Resample an image to eigther a specific spacing or to a reference image.");
329 
330  // Add command line argument names
331  parser.addArgument("help", "h",mitkCommandLineParser::Bool, "Show this help text");
332  parser.addArgument("input", "i", mitkCommandLineParser::InputImage, "Input:", "Input file",us::Any(),false);
333  parser.addArgument("output", "o", mitkCommandLineParser::OutputFile, "Output:", "Output file",us::Any(),false);
334  parser.addArgument("spacing", "s", mitkCommandLineParser::String, "Spacing:", "Resample provide x,y,z spacing in mm (e.g. -r 1,1,3), is not applied to tensor data",us::Any());
335  parser.addArgument("reference", "r", mitkCommandLineParser::InputImage, "Reference:", "Resample using supplied reference image. Also cuts image to same dimensions",us::Any());
336  parser.addArgument("win-sinc", "w", mitkCommandLineParser::Bool, "Windowed-sinc interpolation:", "Use windowed-sinc interpolation (3) instead of linear interpolation ",us::Any());
337  parser.addArgument("nearest-neigh", "n", mitkCommandLineParser::Bool, "Nearest Neighbor:", "Use Nearest Neighbor interpolation instead of linear interpolation ",us::Any());
338 
339 
340  map<string, us::Any> parsedArgs = parser.parseArguments(argc, argv);
341 
342  // Handle special arguments
343  bool useSpacing = false;
344  bool useLinearInterpol = true;
345  bool useNN= false;
346  {
347  if (parsedArgs.size() == 0)
348  {
349  return EXIT_FAILURE;
350  }
351 
352  if (parsedArgs.count("sinc-int"))
353  useLinearInterpol = false;
354 
355  if (parsedArgs.count("nearest-neigh"))
356  useNN = true;
357 
358  // Show a help message
359  if ( parsedArgs.count("help") || parsedArgs.count("h"))
360  {
361  std::cout << parser.helpText();
362  return EXIT_SUCCESS;
363  }
364  }
365 
366  std::string outputFile = us::any_cast<string>(parsedArgs["output"]);
367  std::string inputFile = us::any_cast<string>(parsedArgs["input"]);
368 
369  std::vector<std::string> spacings;
370  float spacing[3];
371  if (parsedArgs.count("spacing"))
372  {
373 
374  std::string arg = us::any_cast<string>(parsedArgs["spacing"]);
375  if (arg != "")
376  {
377  spacings = split(arg ,',');
378  spacing[0] = atoi(spacings.at(0).c_str());
379  spacing[1] = atoi(spacings.at(1).c_str());
380  spacing[2] = atoi(spacings.at(2).c_str());
381  useSpacing = true;
382  }
383  }
384 
385  std::string refImageFile = "";
386  if (parsedArgs.count("reference"))
387  {
388  refImageFile = us::any_cast<string>(parsedArgs["reference"]);
389  }
390 
391  if (refImageFile =="" && useSpacing == false)
392  {
393  MITK_ERROR << "No information how to resample is supplied. Use eigther --spacing or --reference !";
394  return EXIT_FAILURE;
395  }
396 
397 
398  mitk::Image::Pointer refImage;
399  if (!useSpacing)
400  refImage = mitk::IOUtil::LoadImage(refImageFile);
401 
402  mitk::Image::Pointer inputDWI = mitk::IOUtil::LoadImage(inputFile);
404  {
405  mitk::Image::Pointer outputImage;
406 
407  if (useSpacing)
408  outputImage = ResampleDWIbySpacing(inputDWI, spacing);
409  else
410  {
411  MITK_WARN << "Not supported yet, to resample a DWI please set a new spacing.";
412  return EXIT_FAILURE;
413  }
414 
415  mitk::IOUtil::Save(outputImage, outputFile.c_str());
416 
417  return EXIT_SUCCESS;
418  }
419  mitk::Image::Pointer inputImage = mitk::IOUtil::LoadImage(inputFile);
420 
421 
422  mitk::Image::Pointer resultImage;
423 
424  if (useSpacing)
425  resultImage = ResampleBySpacing(inputImage,spacing,useLinearInterpol,useNN);
426  else
427  resultImage = TransformToReference(refImage,inputImage,useLinearInterpol,useNN);
428 
429 
430  mitk::IOUtil::SaveImage(resultImage, outputFile);
431 
432  return EXIT_SUCCESS;
433 }
mitk::Image::Pointer ResampleDWIbySpacing(mitk::Image::Pointer input, float *spacing, bool useLinInt=true)
static void Save(const mitk::BaseData *data, const std::string &path)
Save a mitk::BaseData instance.
Definition: mitkIOUtil.cpp:824
static const std::string REFERENCEBVALUEPROPERTYNAME
int main(int argc, char *argv[])
itk::SmartPointer< Self > Pointer
#define MITK_ERROR
Definition: mitkLogMacros.h:24
void setContributor(std::string contributor)
STL namespace.
Helper class for mitk::Images containing diffusion weighted data.
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
static mitk::Image::Pointer TransformToReference(mitk::Image *reference, mitk::Image *moving, bool sincInterpol=false, bool nn=false)
std::map< std::string, us::Any > parseArguments(const StringContainerType &arguments, bool *ok=nullptr)
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
void InitializeImage()
Make certain the owned image is up to date with all necessary properties.
static bool SaveImage(mitk::Image::Pointer image, const std::string &path)
SaveImage Convenience method to save an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:870
#define MITK_WARN
Definition: mitkLogMacros.h:23
itk::Image< double, 3 > InputImageType
void addArgument(const std::string &longarg, const std::string &shortarg, Type type, const std::string &argLabel, const std::string &argHelp=std::string(), const us::Any &defaultValue=us::Any(), bool optional=true, bool ignoreRest=false, bool deprecated=false)
Image class for storing images.
Definition: mitkImage.h:76
Definition: usAny.h:163
itk::Image< unsigned char, 3 > BinaryImageType
void setCategory(std::string category)
static Pointer New()
void setArgumentPrefix(const std::string &longPrefix, const std::string &shortPrefix)
static Pointer New()
Resample DWI channel by channel.
static mitk::Image::Pointer ResampleBySpacing(mitk::Image *input, float *spacing, bool useLinInt=true, bool useNN=false)
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
std::string helpText() const
static void SaveImage(std::string fileName, mitk::Image *image, std::string fileType)
Save images according to file type.
GradientDirectionsContainerType::Pointer GetGradientContainer() const
static const std::string GRADIENTCONTAINERPROPERTYNAME
void setTitle(std::string title)
void setDescription(std::string description)
static std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
static mitk::Image::Pointer LoadImage(const std::string &path)
LoadImage Convenience method to load an arbitrary mitkImage.
Definition: mitkIOUtil.cpp:597
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.