Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkAlgorithmHelper.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 "mitkAlgorithmHelper.h"
18 
19 //itk
20 #include <itkImageDuplicator.h>
21 
22 // Mitk
23 #include <mitkImageAccessByItk.h>
25 
26 // MatchPoint
27 #include <mapImageRegistrationAlgorithmInterface.h>
28 #include <mapRegistrationAlgorithmInterface.h>
29 #include <mapPointSetRegistrationAlgorithmInterface.h>
30 #include <mapDummyImageRegistrationAlgorithm.h>
31 #include <mapAlgorithmIdentificationInterface.h>
32 
33 namespace mitk
34 {
35 
36  MITKAlgorithmHelper::MITKAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase* algorithm) :
37  m_AlgorithmBase(algorithm)
38  {
39  m_AllowImageCasting = true;
40  }
41 
45  {
47 
48  unsigned int movingDim = m_AlgorithmBase->getMovingDimensions();
49  unsigned int targetDim = m_AlgorithmBase->getTargetDimensions();
50 
51  if (movingDim != targetDim)
52  {
53  mapDefaultExceptionStaticMacro( <<
54  "Error, algorithm instance has unequal dimensionality and is therefore not supported in the current version of MITKAlgorithmHelper.");
55  }
56 
57  if (movingDim > 3)
58  {
59  mapDefaultExceptionStaticMacro( <<
60  "Error, algorithm instance has a dimensionality larger than 3 and is therefore not supported in the current version of MITKAlgorithmHelper.");
61  }
62 
63  typedef ::map::algorithm::facet::RegistrationAlgorithmInterface<2, 2> RegistrationAlg2D2DInterface;
64  typedef ::map::algorithm::facet::RegistrationAlgorithmInterface<3, 3> RegistrationAlg3D3DInterface;
65 
66  RegistrationAlg2D2DInterface* pRegAlgorithm2D2D = dynamic_cast<RegistrationAlg2D2DInterface*>
67  (m_AlgorithmBase.GetPointer());
68  RegistrationAlg3D3DInterface* pRegAlgorithm3D3D = dynamic_cast<RegistrationAlg3D3DInterface*>
69  (m_AlgorithmBase.GetPointer());
70 
71  if (pRegAlgorithm2D2D)
72  {
73  spResult = pRegAlgorithm2D2D->getRegistration();
74  }
75 
76  if (pRegAlgorithm3D3D)
77  {
78  spResult = pRegAlgorithm3D3D->getRegistration();
79  }
80 
81  return spResult;
82  }
83 
87  {
90  spResult->SetRegistration(spInternalResult);
91  return spResult;
92  };
93 
94 
95  static const mitk::Image* GetDataAsImage(const mitk::BaseData* data)
96  {
97  return dynamic_cast<const mitk::Image*>(data);
98  };
99 
101  {
102  return dynamic_cast<const mitk::PointSet*>(data);
103  };
104 
105  bool
107  CheckData(const mitk::BaseData* moving, const mitk::BaseData* target, CheckError::Type& error) const
108  {
109  if (! m_AlgorithmBase)
110  {
111  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Helper has no algorithm defined.");
112  }
113 
114  if (! moving)
115  {
116  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Moving data pointer is NULL.");
117  }
118 
119  if (! target)
120  {
121  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Target data pointer is NULL.");
122  }
123 
124  bool result = false;
126 
127  unsigned int movingDim = m_AlgorithmBase->getMovingDimensions();
128  unsigned int targetDim = m_AlgorithmBase->getTargetDimensions();
129 
130  if (movingDim != targetDim)
131  {
132  m_Error = CheckError::wrongDimension;
133  }
134  else
135  {
136  //First check if data are point sets or images
137  if (GetDataAsPointSet(target) && GetDataAsPointSet(moving))
138  {
139  typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType;
140  typedef ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface<InternalDefaultPointSetType, InternalDefaultPointSetType>
141  PointSetRegInterface;
142 
143  PointSetRegInterface* pPointSetInterface = dynamic_cast<PointSetRegInterface*>
144  (m_AlgorithmBase.GetPointer());
145 
146  if (!pPointSetInterface)
147  {
148  result = false;
150  }
151  }
152  else if (GetDataAsImage(moving) && GetDataAsImage(target))
153  {
154  if (movingDim == 2)
155  {
156  AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoCheckImages,
157  2);
158  }
159  else if (movingDim == 3)
160  {
161  AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoCheckImages,
162  3);
163  }
164  else
165  {
166  m_Error = CheckError::wrongDimension;
167  }
168 
169  if (m_Error == CheckError::none || (m_AllowImageCasting && m_Error == CheckError::onlyByCasting))
170  {
171  result = true;
172  }
173  }
174 
175  }
176 
177  error = m_Error;
178  return result;
179 
180  };
181 
183  {
184  this->m_AllowImageCasting = allowCasting;
185  };
186 
188  {
189  return this->m_AllowImageCasting;
190  };
191 
192  void MITKAlgorithmHelper::SetData(const mitk::BaseData* moving, const mitk::BaseData* target)
193  {
194  if (! m_AlgorithmBase)
195  {
196  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Helper has no algorithm defined.");
197  }
198 
199  if (! moving)
200  {
201  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Moving data pointer is NULL.");
202  }
203 
204  if (! target)
205  {
206  mapDefaultExceptionStaticMacro( << "Error, cannot check data. Target data pointer is NULL.");
207  }
208 
209  unsigned int movingDim = m_AlgorithmBase->getMovingDimensions();
210  unsigned int targetDim = m_AlgorithmBase->getTargetDimensions();
211 
212  if (movingDim != targetDim)
213  {
214  mapDefaultExceptionStaticMacro( <<
215  "Error, cannot set data. Current version of MITKAlgorithmHelper only supports images/point sets with same dimensionality.");
216  }
217 
218  if (GetDataAsPointSet(target) && GetDataAsPointSet(moving))
219  {
220  typedef ::map::core::continuous::Elements<3>::InternalPointSetType InternalDefaultPointSetType;
221  typedef ::map::algorithm::facet::PointSetRegistrationAlgorithmInterface<InternalDefaultPointSetType, InternalDefaultPointSetType>
222  PointSetRegInterface;
223 
224  PointSetRegInterface* pPointSetInterface = dynamic_cast<PointSetRegInterface*>
225  (m_AlgorithmBase.GetPointer());
226 
227  pPointSetInterface->setMovingPointSet(mitk::PointSetMappingHelper::ConvertPointSetMITKtoMAP(
228  GetDataAsPointSet(moving)->GetPointSet()));
229  pPointSetInterface->setTargetPointSet(mitk::PointSetMappingHelper::ConvertPointSetMITKtoMAP(
230  GetDataAsPointSet(target)->GetPointSet()));
231  }
232  else if (GetDataAsImage(moving) && GetDataAsImage(target))
233  {
234  if (movingDim == 2)
235  {
236  AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoSetImages, 2);
237  }
238  else if (movingDim == 3)
239  {
240  AccessTwoImagesFixedDimensionByItk(GetDataAsImage(moving), GetDataAsImage(target), DoSetImages, 3);
241  }
242  }
243  };
244 
245  template<typename TInImageType, typename TOutImageType>
246  typename TOutImageType::Pointer MITKAlgorithmHelper::CastImage(const TInImageType* input) const
247  {
248  typedef itk::CastImageFilter< TInImageType, TOutImageType > CastFilterType;
249  typename CastFilterType::Pointer spImageCaster = CastFilterType::New();
250 
251  spImageCaster->SetInput(input);
252 
253  typename TOutImageType::Pointer spImage = spImageCaster->GetOutput();
254  spImageCaster->Update();
255 
256  return spImage;
257  }
258 
259  template<typename TPixelType1, unsigned int VImageDimension1,
260  typename TPixelType2, unsigned int VImageDimension2>
261  void MITKAlgorithmHelper::DoSetImages(const itk::Image<TPixelType1, VImageDimension1>* moving,
262  const itk::Image<TPixelType2, VImageDimension2>* target)
263  {
264  typedef itk::Image<TPixelType1, VImageDimension1> MovingImageType;
265  typedef itk::Image<TPixelType2, VImageDimension2> TargetImageType;
266  typedef itk::Image<map::core::discrete::InternalPixelType, VImageDimension1>
267  InternalDefaultMovingImageType;
268  typedef itk::Image<map::core::discrete::InternalPixelType, VImageDimension2>
269  InternalDefaultTargetImageType;
270 
271  typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface<MovingImageType, TargetImageType>
272  ImageRegInterface;
273  typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface<InternalDefaultMovingImageType, InternalDefaultTargetImageType>
274  DefaultImageRegInterface;
275 
276 
277  ImageRegInterface* pImageInterface = dynamic_cast<ImageRegInterface*>(m_AlgorithmBase.GetPointer());
278  DefaultImageRegInterface* pDefaultImageInterface = dynamic_cast<DefaultImageRegInterface*>
279  (m_AlgorithmBase.GetPointer());
280 
281  if (pImageInterface)
282  {
283  //just set directly and you are done
284 
291  typedef itk::ImageDuplicator< MovingImageType > MovingDuplicatorType;
292  typedef itk::ImageDuplicator< TargetImageType > TargetDuplicatorType;
294  mDuplicator->SetInputImage(moving);
295  mDuplicator->Update();
296 
298  tDuplicator->SetInputImage(target);
299  tDuplicator->Update();
300 
301  typename MovingImageType::Pointer clonedMoving = mDuplicator->GetOutput();
302  typename TargetImageType::Pointer clonedTarget = tDuplicator->GetOutput();
303 
304  pImageInterface->setTargetImage(clonedTarget);
305  pImageInterface->setMovingImage(clonedMoving);
306  }
307  else if (pDefaultImageInterface)
308  {
309  //you may convert it to the default image type and use it then
310  if (! m_AllowImageCasting)
311  {
312  mapDefaultExceptionStaticMacro( <<
313  "Error, cannot set images. MITKAlgorithmHelper has to convert them into MatchPoint default images, but is not allowed. Please reconfigure helper.");
314  }
315 
316  typename InternalDefaultTargetImageType::Pointer spCastedTarget =
317  CastImage<TargetImageType, InternalDefaultTargetImageType>(target);
318  typename InternalDefaultMovingImageType::Pointer spCastedMoving =
319  CastImage<MovingImageType, InternalDefaultMovingImageType>(moving);
320  pDefaultImageInterface->setTargetImage(spCastedTarget);
321  pDefaultImageInterface->setMovingImage(spCastedMoving);
322  }
323  else
324  {
325  mapDefaultExceptionStaticMacro( << "Error, algorithm is not able to use the based images.");
326  }
327  }
328 
329  template<typename TPixelType1, unsigned int VImageDimension1,
330  typename TPixelType2, unsigned int VImageDimension2>
331  void MITKAlgorithmHelper::DoCheckImages(const itk::Image<TPixelType1, VImageDimension1>* moving,
332  const itk::Image<TPixelType2, VImageDimension2>* target) const
333  {
334  typedef itk::Image<TPixelType1, VImageDimension1> MovingImageType;
335  typedef itk::Image<TPixelType2, VImageDimension2> TargetImageType;
336  typedef itk::Image<map::core::discrete::InternalPixelType, VImageDimension1>
337  InternalDefaultMovingImageType;
338  typedef itk::Image<map::core::discrete::InternalPixelType, VImageDimension2>
339  InternalDefaultTargetImageType;
340 
341  typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface<MovingImageType, TargetImageType>
342  ImageRegInterface;
343  typedef ::map::algorithm::facet::ImageRegistrationAlgorithmInterface<InternalDefaultMovingImageType, InternalDefaultTargetImageType>
344  DefaultImageRegInterface;
345 
346  ImageRegInterface* pImageInterface = dynamic_cast<ImageRegInterface*>(m_AlgorithmBase.GetPointer());
347  DefaultImageRegInterface* pDefaultImageInterface = dynamic_cast<DefaultImageRegInterface*>
348  (m_AlgorithmBase.GetPointer());
349 
350  if (pImageInterface)
351  {
352  //just set directly and you are done
353  m_Error = CheckError::none;
354  }
355  else if (pDefaultImageInterface)
356  {
357  //you may convert it to the default image type and use it then
358  m_Error = CheckError::onlyByCasting;
359  }
360  else
361  {
363  }
364  }
365 
366 
367  mapGenerateAlgorithmUIDPolicyMacro(DummyRegIDPolicy, "de.dkfz.dipp", "Identity", "1.0.0", "");
368 
370  {
371  typedef map::algorithm::DummyImageRegistrationAlgorithm<map::core::discrete::Elements<3>::InternalImageType, map::core::discrete::Elements<3>::InternalImageType, DummyRegIDPolicy>
372  DummyRegType;
374  mitk::MITKAlgorithmHelper helper(regAlg);
375 
378  dummyImg->Allocate();
379  regAlg->setTargetImage(dummyImg);
380  regAlg->setMovingImage(dummyImg);
381 
383  dummyReg->SetRegistration(regAlg->getRegistration());
384 
385  return dummyReg;
386  }
387 
388 }
void SetAllowImageCasting(bool allowCasting)
map::core::RegistrationBase::Pointer GetRegistration() const
MITKAlgorithmHelper.
itk::SmartPointer< Self > Pointer
Base of all data objects.
Definition: mitkBaseData.h:39
DataCollection - Class to facilitate loading/accessing structured data.
bool CheckData(const mitk::BaseData *moving, const mitk::BaseData *target, CheckError::Type &error) const
MITKMATCHPOINTREGISTRATION_EXPORT::map::core::continuous::Elements< 3 >::InternalPointSetType::Pointer ConvertPointSetMITKtoMAP(const mitk::PointSet::DataType *mitkSet)
Data structure which stores a set of points. Superclass of mitk::Mesh.
Definition: mitkPointSet.h:79
void SetData(const mitk::BaseData *moving, const mitk::BaseData *target)
mitk::MAPRegistrationWrapper::Pointer GetMITKRegistrationWrapper() const
Image class for storing images.
Definition: mitkImage.h:76
static const mitk::Image * GetDataAsImage(const mitk::BaseData *data)
static const mitk::PointSet * GetDataAsPointSet(const mitk::BaseData *data)
#define AccessTwoImagesFixedDimensionByItk(mitkImage1, mitkImage2, itkImageTypeFunction, dimension)
Access two mitk-images with known dimension by itk-images.
mitk::MAPRegistrationWrapper::Pointer GenerateIdentityRegistration3D()
MITKAlgorithmHelper(map::algorithm::RegistrationAlgorithmBase *algorithm=NULL)
mapGenerateAlgorithmUIDPolicyMacro(DummyRegIDPolicy,"de.dkfz.dipp","Identity","1.0.0","")
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.