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