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
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.