Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkRegistrationWrapper.cpp
Go to the documentation of this file.
2 
4 #include "mitkImage.h"
7 #include <itkResampleImageFilter.h>
8 #include <itkWindowedSincInterpolateImageFunction.h>
9 #include <itkLinearInterpolateImageFunction.h>
10 #include <itkNearestNeighborExtrapolateImageFunction.h>
11 #include <itkBSplineInterpolateImageFunction.h>
13 #include <mitkProperties.h>
15 #include <itkImageDuplicator.h>
16 
17 #include <vnl/vnl_inverse.h>
18 
20 {
21 
23  {
24 
26 
27  CastToItkImage(img, itkImage);
28 
29  typedef itk::Euler3DTransform< double > RigidTransformType;
31  RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension);
32 
33  for (int i = 0; i<6;++i)
34  parameters[i] = transformation[i];
35 
36  rtransform->SetParameters( parameters );
37 
38  mitk::Point3D origin = img->GetGeometry()->GetOrigin();
39  // overwrite origin only if an offset was supplied
40  if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0)
41  {
42  origin[0]=offset[0];
43  origin[1]=offset[1];
44  origin[2]=offset[2];
45  }
46 
47  mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(origin);
48 
49  itk::Matrix<double,3,3> dir = itkImage->GetDirection();
50  itk::Matrix<double,3,3> transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix()));
51  itk::Matrix<double,3,3> newDirection = transM * dir;
52 
53  itkImage->SetOrigin(newOrigin);
54  itkImage->SetDirection(newDirection);
55 
56  // Perform Resampling if reference image is provided
57  if (resampleReference != NULL)
58  {
59  typedef itk::ResampleImageFilter<ItkImageType, ItkImageType> ResampleFilterType;
60 
62  CastToItkImage(resampleReference,itkReference);
63 
64  typedef itk::Function::WelchWindowFunction<4> WelchWindowFunction;
65  typedef itk::WindowedSincInterpolateImageFunction< ItkImageType, 4,WelchWindowFunction> WindowedSincInterpolatorType;
67 
68 
69  typedef itk::LinearInterpolateImageFunction< ItkImageType> LinearInterpolatorType;
71 
72  typedef itk::NearestNeighborInterpolateImageFunction< ItkImageType, double > NearestNeighborInterpolatorType;
74 
75  typedef itk::BSplineInterpolateImageFunction< ItkImageType, double > BSplineInterpolatorType;
77 
78 
80  resampler->SetInput(itkImage);
81  resampler->SetReferenceImage( itkReference );
82  resampler->UseReferenceImageOn();
83  if (binary)
84  resampler->SetInterpolator(nn_interpolator);
85  else
86  resampler->SetInterpolator(lin_interpolator);
87 
88  resampler->Update();
89 
90  GrabItkImageMemory(resampler->GetOutput(), img);
91  }
92  else
93  {
94  // !! CastToItk behaves very differently depending on the original data type
95  // if the target type is the same as the original, only a pointer to the data is set
96  // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed
97  // GrabItkImageMemory - is not necessary in this case since we worked on the original data
98  // See Bug 17538 - this is why we duplicate the itkImage first and then create a new mitk::Image from it.
100  duplicator->SetInputImage(itkImage);
101  duplicator->Update();
102  GrabItkImageMemory(duplicator->GetOutput(), img);
103  }
104 
105  }
106  else
107  {
108  mitk::Image::Pointer diffImages = dynamic_cast<mitk::Image*>(img.GetPointer());
109 
110 // mitk::DiffusionPropertyHelper::GradientDirectionsContainerType::Pointer gradientDirections =
111 // static_cast<mitk::GradientDirectionsProperty*>( img->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer();
112  typedef itk::Euler3DTransform< double > RigidTransformType;
114  RigidTransformType::ParametersType parameters(RigidTransformType::ParametersDimension);
115 
116  for (int i = 0; i<6;++i)
117  {
118  parameters[i] = transformation[i];
119  }
120 
121  rtransform->SetParameters( parameters );
122 
123  typedef itk::VectorImage<short, 3> ITKDiffusionImageType;
125  mitk::CastToItkImage(diffImages, itkVectorImagePointer);
126 
127  mitk::Point3D b0origin = itkVectorImagePointer->GetOrigin();
128  // overwrite origin only if an offset was supplied
129  if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0)
130  {
131  b0origin[0]=offset[0];
132  b0origin[1]=offset[1];
133  b0origin[2]=offset[2];
134  }
135 
136  mitk::Point3D newOrigin = rtransform->GetInverseTransform()->TransformPoint(b0origin);
137 
138  itk::Matrix<double,3,3> dir = itkVectorImagePointer->GetDirection();
139  itk::Matrix<double,3,3> transM ( vnl_inverse(rtransform->GetMatrix().GetVnlMatrix()));
140  itk::Matrix<double,3,3> newDirection = transM * dir;
141 
142  itkVectorImagePointer->SetOrigin(newOrigin);
143  itkVectorImagePointer->SetDirection(newDirection);
144 
145  // !! CastToItk behaves very differently depending on the original data type
146  // if the target type is the same as the original, only a pointer to the data is set
147  // and an additional GrabItkImageMemory will cause a segfault when the image is destroyed
148  // GrabItkImageMemory - is not necessary in this case since we worked on the original data
149  // See Bug 17538 - this is why we duplicate the itkImage first and then create a new mitk::Image from it.
151  duplicator->SetInputImage(itkVectorImagePointer);
152  duplicator->Update();
153  GrabItkImageMemory(duplicator->GetOutput(), img);
154 
155  img->SetProperty( mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str(), mitk::GradientDirectionsProperty::New( static_cast<mitk::GradientDirectionsProperty*>( diffImages->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer() ) );
156  img->SetProperty( mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str(), mitk::MeasurementFrameProperty::New( static_cast<mitk::MeasurementFrameProperty*>( diffImages->GetProperty(mitk::DiffusionPropertyHelper::MEASUREMENTFRAMEPROPERTYNAME.c_str()).GetPointer() )->GetMeasurementFrame() ) );
157  img->SetProperty( mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str(), mitk::FloatProperty::New( static_cast<mitk::FloatProperty*>(diffImages->GetProperty(mitk::DiffusionPropertyHelper::REFERENCEBVALUEPROPERTYNAME.c_str()).GetPointer() )->GetValue() ) );
158  mitk::DiffusionPropertyHelper propertyHelper( img );
159  propertyHelper.InitializeImage();
160 
162 
163  // For Diff. Images: Need to rotate the gradients (works in-place)
164  correctionFilter->SetImage(img);
165  correctionFilter->CorrectDirections(transM.GetVnlMatrix());
166  }
167 }
168 
169 void mitk::RegistrationWrapper::GetTransformation(mitk::Image::Pointer fixedImage, mitk::Image::Pointer movingImage, RidgidTransformType transformation,double* offset, bool useSameOrigin, mitk::Image* mask)
170 {
171  // Handle the case that fixed/moving image is a DWI image
172  mitk::Image* fixedDwi = dynamic_cast<mitk::Image*> (fixedImage.GetPointer());
173  mitk::Image* movingDwi = dynamic_cast<mitk::Image*> (movingImage.GetPointer());
175  offset[0]=offset[1]=offset[2]=0;
176 
177  typedef itk::VectorImage<short, 3> ITKDiffusionImageType;
178 
179 
180 
182  { // Set b0 extraction as fixed image
184  static_cast<mitk::GradientDirectionsProperty*>( fixedDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer();
186  mitk::CastToItkImage(fixedDwi, itkFixedDwiPointer);
187 
188  b0Extraction->SetInput( itkFixedDwiPointer );
189  b0Extraction->SetDirections(fixedGradientDirections);
190  b0Extraction->Update();
192  tmp->InitializeByItk(b0Extraction->GetOutput());
193  tmp->SetVolume(b0Extraction->GetOutput()->GetBufferPointer());
194  fixedImage = tmp;
195  }
197  { // Set b0 extraction as moving image
199  static_cast<mitk::GradientDirectionsProperty*>( movingDwi->GetProperty(mitk::DiffusionPropertyHelper::GRADIENTCONTAINERPROPERTYNAME.c_str()).GetPointer() )->GetGradientDirectionsContainer();
200 
202  mitk::CastToItkImage(movingDwi, itkMovingDwiPointer);
203 
204  b0Extraction->SetInput( itkMovingDwiPointer );
205  b0Extraction->SetDirections(movingGradientDirections);
206  b0Extraction->Update();
208  tmp->InitializeByItk(b0Extraction->GetOutput());
209  tmp->SetVolume(b0Extraction->GetOutput()->GetBufferPointer());
210  movingImage = tmp;
211  }
212 
213  // align the offsets of the two images. this is done to avoid non-overlapping initialization
214  // Point3D origin = fixedImage->GetGeometry()->GetOrigin();
215 
216 
217  Point3D center = fixedImage->GetGeometry()->GetCenter();
218  Point3D centerMoving = movingImage->GetGeometry()->GetCenter();
219  Point3D originMoving = movingImage->GetGeometry()->GetOrigin();
220 
221 
222  mitk::Image::Pointer tmpImage = movingImage->Clone();
223  if (useSameOrigin)
224  {
225 
226  offset[0] = (originMoving[0]-centerMoving[0])+center[0];
227  offset[1] = (originMoving[1]-centerMoving[1])+center[1];
228  offset[2] = (originMoving[2]-centerMoving[2])+center[2];
229  Point3D translatedOrigin;
230  translatedOrigin[0]= offset[0];
231  translatedOrigin[1]= offset[1];
232  translatedOrigin[2]= offset[2];
233  tmpImage->GetGeometry()->SetOrigin(translatedOrigin);
234  }
235  // Start registration
237  registrationMethod->SetFixedImage( fixedImage );
238 
239  if (mask != NULL)
240  {
241  registrationMethod->SetFixedImageMask(mask);
242  registrationMethod->SetUseFixedImageMask(true);
243  }
244  else
245  {
246  registrationMethod->SetUseFixedImageMask(false);
247  }
248 
249  registrationMethod->SetTransformToRigid();
250  registrationMethod->SetCrossModalityOn();
251  registrationMethod->SetVerboseOn();
252 
253 
254  registrationMethod->SetMovingImage(tmpImage);
255  registrationMethod->Update();
256  registrationMethod->GetParameters(transformation); // first three: euler angles, last three translation
257 }
static const std::string REFERENCEBVALUEPROPERTYNAME
itk::SmartPointer< Self > Pointer
static Pointer New()
Method for creation through the object factory.
Helper class for mitk::Images containing diffusion weighted data.
static void GetTransformation(Image::Pointer fixedImage, Image::Pointer movingImage, RidgidTransformType transformation, double *offset, bool useSameOrigin=true, mitk::Image *mask=NULL)
GetTransformation Registeres the moving to the fixed image and returns the according transformation...
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.
static const std::string MEASUREMENTFRAMEPROPERTYNAME
void InitializeImage()
Make certain the owned image is up to date with all necessary properties.
static Vector3D offset
static void ApplyTransformationToImage(mitk::Image::Pointer img, const RidgidTransformType &transformation, double *offset, mitk::Image *resampleReference=NULL, bool binary=false)
ApplyTransformationToImage Applies transformation from GetTransformation to provided image...
Image class for storing images.
Definition: mitkImage.h:76
static Pointer New()
static Pointer New()
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
mitk::BaseProperty::Pointer GetProperty(const char *propertyKey) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList, and set it to this, respectively;.
static const std::string GRADIENTCONTAINERPROPERTYNAME
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.