Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkBSplineRegistration.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 #include <mitkImageCast.h>
18 
19 #include "itkImageFileWriter.h"
20 #include "itkImageRegionIterator.h"
21 #include "itkWarpImageFilter.h"
22 
23 #include "itkBSplineDeformableTransform.h"
25 //#include "itkLBFGSOptimizer.h"
26 #include "itkImageRegistrationMethod.h"
27 #include "itkMattesMutualInformationImageToImageMetric.h"
28 #include "itkMeanSquaresImageToImageMetric.h"
29 #include "itkResampleImageFilter.h"
30 
32 
33 #include "mitkMetricFactory.h"
34 #include "mitkOptimizerFactory.h"
35 
36 #include <itkHistogramMatchingImageFilter.h>
37 #include <itkRescaleIntensityImageFilter.h>
38 
39 namespace mitk
40 {
42  : m_Iterations(50),
43  m_ResultName("deformedImage.mhd"),
44  m_SaveResult(true),
45  m_SaveDeformationField(false),
46  m_UpdateInputImage(false),
47  m_MatchHistograms(true),
48  m_Metric(0)
49  {
51  }
52 
54  void BSplineRegistration::SetNumberOfIterations(int iterations) { m_Iterations = iterations; }
55  void BSplineRegistration::SetSaveResult(bool saveResult) { m_SaveResult = saveResult; }
56  void BSplineRegistration::SetResultFileName(const char *resultName) { m_ResultName = resultName; }
57  template <typename TPixel, unsigned int VImageDimension>
58  void BSplineRegistration::GenerateData2(const itk::Image<TPixel, VImageDimension> *itkImage1)
59  {
60  std::cout << "start bspline registration" << std::endl;
61 
62  // Typedefs
63  typedef typename itk::Image<TPixel, VImageDimension> InternalImageType;
64 
65  typedef typename itk::Vector<float, VImageDimension> VectorPixelType;
66  typedef typename itk::Image<VectorPixelType, VImageDimension> DeformationFieldType;
67 
68  typedef itk::BSplineDeformableTransform<double, VImageDimension, 3> TransformType;
69 
70  typedef typename TransformType::ParametersType ParametersType;
71 
72  // typedef itk::LBFGSOptimizer OptimizerType;
73  typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
74  // typedef itk::SingleValuedCostFunction MetricType;
75 
76  typedef itk::MattesMutualInformationImageToImageMetric<InternalImageType, InternalImageType> MetricType;
77 
78  typedef itk::MeanSquaresImageToImageMetric<InternalImageType, InternalImageType> MetricTypeMS;
79 
80  typedef itk::LinearInterpolateImageFunction<InternalImageType, double> InterpolatorType;
81 
82  typedef itk::ImageRegistrationMethod<InternalImageType, InternalImageType> RegistrationType;
83 
84  typedef typename itk::WarpImageFilter<InternalImageType, InternalImageType, DeformationFieldType> WarperType;
85 
86  typedef typename TransformType::SpacingType SpacingType;
87 
88  typedef typename TransformType::OriginType OriginType;
89 
90  typedef itk::ResampleImageFilter<InternalImageType, InternalImageType> ResampleFilterType;
91 
92  typedef itk::Image<TPixel, VImageDimension> OutputImageType;
93 
94  // Sample new image with the same image type as the fixed image
95  typedef itk::CastImageFilter<InternalImageType, InternalImageType> CastFilterType;
96 
97  typedef itk::Vector<float, VImageDimension> VectorType;
98  typedef itk::Image<VectorType, VImageDimension> DeformationFieldType;
99 
101 
102  typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
103  typename RegistrationType::Pointer registration = RegistrationType::New();
104  typename InitializerType::Pointer initializer = InitializerType::New();
105  typename TransformType::Pointer transform = TransformType::New();
106 
107  if (m_Metric == 0 || m_Metric == 1)
108  {
109  typename MetricType::Pointer metric = MetricType::New();
110  metric->SetNumberOfHistogramBins(32);
111  metric->SetNumberOfSpatialSamples(90000);
112  registration->SetMetric(metric);
113  }
114  else
115  {
116  typename MetricTypeMS::Pointer metric = MetricTypeMS::New();
117  registration->SetMetric(metric);
118  }
119 
121  optFac->SetOptimizerParameters(m_OptimizerParameters);
122  optFac->SetNumberOfTransformParameters(transform->GetNumberOfParameters());
123  OptimizerType::Pointer optimizer = optFac->GetOptimizer();
124 
125  optimizer->AddObserver(itk::AnyEvent(), m_Observer);
126 
127  // typedef mitk::MetricFactory <TPixel, VImageDimension> MetricFactoryType;
128  // typename MetricFactoryType::Pointer metricFac = MetricFactoryType::New();
129  // metricFac->SetMetricParameters(m_MetricParameters);
131 
132  typename InternalImageType::Pointer fixedImage = InternalImageType::New();
134  typename InternalImageType::ConstPointer movingImage = itkImage1;
135  typename InternalImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion();
136  typename InternalImageType::RegionType movingRegion = movingImage->GetBufferedRegion();
137 
138  if (m_MatchHistograms)
139  {
140  typedef itk::RescaleIntensityImageFilter<InternalImageType, InternalImageType> FilterType;
141  typedef itk::HistogramMatchingImageFilter<InternalImageType, InternalImageType> HEFilterType;
142 
143  typename FilterType::Pointer inputRescaleFilter = FilterType::New();
144  typename FilterType::Pointer referenceRescaleFilter = FilterType::New();
145 
146  referenceRescaleFilter->SetInput(fixedImage);
147  inputRescaleFilter->SetInput(movingImage);
148 
149  TPixel desiredMinimum = 0;
150  TPixel desiredMaximum = 255;
151 
152  referenceRescaleFilter->SetOutputMinimum(desiredMinimum);
153  referenceRescaleFilter->SetOutputMaximum(desiredMaximum);
154  referenceRescaleFilter->UpdateLargestPossibleRegion();
155  inputRescaleFilter->SetOutputMinimum(desiredMinimum);
156  inputRescaleFilter->SetOutputMaximum(desiredMaximum);
157  inputRescaleFilter->UpdateLargestPossibleRegion();
158 
159  // Histogram match the images
160  typename HEFilterType::Pointer intensityEqualizeFilter = HEFilterType::New();
161 
162  intensityEqualizeFilter->SetReferenceImage(inputRescaleFilter->GetOutput());
163  intensityEqualizeFilter->SetInput(referenceRescaleFilter->GetOutput());
164  intensityEqualizeFilter->SetNumberOfHistogramLevels(64);
165  intensityEqualizeFilter->SetNumberOfMatchPoints(12);
166  intensityEqualizeFilter->ThresholdAtMeanIntensityOn();
167  intensityEqualizeFilter->Update();
168 
169  // fixedImage = referenceRescaleFilter->GetOutput();
170  // movingImage = IntensityEqualizeFilter->GetOutput();
171 
172  fixedImage = intensityEqualizeFilter->GetOutput();
173  movingImage = inputRescaleFilter->GetOutput();
174  }
175 
176  //
177  registration->SetOptimizer(optimizer);
178  registration->SetInterpolator(interpolator);
179  registration->SetFixedImage(fixedImage);
180  registration->SetMovingImage(movingImage);
181  registration->SetFixedImageRegion(fixedRegion);
182 
183  initializer->SetTransform(transform);
184  initializer->SetImage(fixedImage);
185  initializer->SetNumberOfGridNodesInsideTheImage(m_NumberOfGridPoints);
186  initializer->InitializeTransform();
187 
188  registration->SetTransform(transform);
189 
190  const unsigned int numberOfParameters = transform->GetNumberOfParameters();
191 
192  typename itk::BSplineDeformableTransform<double, VImageDimension, 3>::ParametersType parameters;
193 
194  parameters.set_size(numberOfParameters);
195  parameters.Fill(0.0);
196  transform->SetParameters(parameters);
197 
198  // We now pass the parameters of the current transform as the initial
199  // parameters to be used when the registration process starts.
200  registration->SetInitialTransformParameters(transform->GetParameters());
201 
202  std::cout << "Intial Parameters = " << std::endl;
203  std::cout << transform->GetParameters() << std::endl;
204 
205  std::cout << std::endl << "Starting Registration" << std::endl;
206 
207  try
208  {
209  double tstart(clock());
210  registration->Update();
211  double time = clock() - tstart;
212  time = time / CLOCKS_PER_SEC;
213  MITK_INFO << "Registration time: " << time;
214  }
215  catch (itk::ExceptionObject &err)
216  {
217  std::cerr << "ExceptionObject caught !" << std::endl;
218  std::cerr << err << std::endl;
219  }
220 
221  typename OptimizerType::ParametersType finalParameters = registration->GetLastTransformParameters();
222 
223  std::cout << "Last Transform Parameters" << std::endl;
224  std::cout << finalParameters << std::endl;
225 
226  transform->SetParameters(finalParameters);
227 
228  /*
229  ResampleFilterType::Pointer resampler = ResampleFilterType::New();
230  resampler->SetTransform( transform );
231  resampler->SetInput( movingImage );
232  resampler->SetSize( fixedImage->GetLargestPossibleRegion().GetSize() );
233  resampler->SetOutputOrigin( fixedImage->GetOrigin() );
234  resampler->SetOutputSpacing( fixedImage->GetSpacing() );
235  resampler->SetOutputDirection( fixedImage->GetDirection() );
236  resampler->SetDefaultPixelValue( 100 );
237  resampler->SetInterpolator( interpolator);
238  resampler->Update();*/
239 
240  // Generate deformation field
242  field->SetRegions(movingRegion);
243  field->SetOrigin(movingImage->GetOrigin());
244  field->SetSpacing(movingImage->GetSpacing());
245  field->SetDirection(movingImage->GetDirection());
246  field->Allocate();
247 
248  typedef itk::ImageRegionIterator<DeformationFieldType> FieldIterator;
249  FieldIterator fi(field, movingRegion);
250  fi.GoToBegin();
251 
252  typename TransformType::InputPointType fixedPoint;
253  typename TransformType::OutputPointType movingPoint;
254  typename DeformationFieldType::IndexType index;
255 
256  VectorType displacement;
257 
258  while (!fi.IsAtEnd())
259  {
260  index = fi.GetIndex();
261  field->TransformIndexToPhysicalPoint(index, fixedPoint);
262  movingPoint = transform->TransformPoint(fixedPoint);
263  displacement = movingPoint - fixedPoint;
264  fi.Set(displacement);
265  ++fi;
266  }
267 
268  // Use the deformation field to warp the moving image
269  typename WarperType::Pointer warper = WarperType::New();
270  warper->SetInput(movingImage);
271  warper->SetInterpolator(interpolator);
272  warper->SetOutputSpacing(movingImage->GetSpacing());
273  warper->SetOutputOrigin(movingImage->GetOrigin());
274  warper->SetOutputDirection(movingImage->GetDirection());
275  warper->SetDisplacementField(field);
276  warper->Update();
277 
278  typename InternalImageType::Pointer result = warper->GetOutput();
279 
280  if (m_UpdateInputImage)
281  {
282  Image::Pointer outputImage = this->GetOutput();
283  mitk::CastToMitkImage(result, outputImage);
284  }
285 
286  // Save the deformationfield resulting from the registration
288  {
289  typedef itk::ImageFileWriter<DeformationFieldType> FieldWriterType;
290  typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
291 
292  fieldWriter->SetInput(field);
293 
294  fieldWriter->SetFileName(m_DeformationFileName);
295  try
296  {
297  fieldWriter->Update();
298  }
299  catch (itk::ExceptionObject &excp)
300  {
301  std::cerr << "Exception thrown " << std::endl;
302  std::cerr << excp << std::endl;
303  // return EXIT_FAILURE;
304  }
305  }
306  }
307 } // end namespace
static Pointer New()
itk::SmartPointer< Self > Pointer
void SetResultFileName(const char *resultName)
Sets the filename for the resulting deformed image.
#define MITK_INFO
Definition: mitkLogMacros.h:22
mitk::OptimizerParameters::Pointer m_OptimizerParameters
DataCollection - Class to facilitate loading/accessing structured data.
BSplineDeformableTransformInitializer is a helper class intended to initialize the grid parameters of...
itk::SmartPointer< const Self > ConstPointer
itk::Vector< float, 3 > VectorType
RigidRegistrationObserver::Pointer m_Observer
virtual ~BSplineRegistration()
Default destructor.
mitk::Image OutputImageType
Some convenient typedefs.
itk::Image< VectorType, 3 > DeformationFieldType
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:78
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
void SetSaveResult(bool saveResult)
Sets whether the result should be saved or not.
BSplineRegistration()
Default constructor.
OutputType * GetOutput()
Get the output data of this image source object.
void SetNumberOfIterations(int iterations)
Sets the number of iterations which will be performed during the registration process.
::map::core::RegistrationBase RegistrationType
void GenerateData2(const itk::Image< TPixel, VImageDimension > *itkImage1)
Template class to perform the demons registration with any kind of image. Called by GenerateData()...
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.