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