Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
mitkHotspotMaskGenerator.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 
14 #include <mitkImageTimeSelector.h>
15 #include <mitkImageCast.h>
16 #include <mitkPoint.h>
17 #include <itkImageRegionIterator.h>
18 #include "mitkImageAccessByItk.h"
19 #include <itkImageDuplicator.h>
20 #include <itkFFTConvolutionImageFilter.h>
21 #include <mitkITKImageImport.h>
22 
23 namespace mitk
24 {
26  m_HotspotRadiusinMM(6.2035049089940), // radius of a 1cm3 sphere in mm
27  m_HotspotMustBeCompletelyInsideImage(true),
28  m_Label(1)
29  {
30  m_TimeStep = 0;
32  m_InternalMaskUpdateTime = 0;
33  }
34 
36  {
37  if (inputImage != m_inputImage)
38  {
39  m_inputImage = inputImage;
40  m_ConvolutionImageMaxIndex.set_size(inputImage->GetDimension());
41  m_ConvolutionImageMinIndex.set_size(inputImage->GetDimension());
42  this->Modified();
43  }
44  }
45 
47  {
48  if (mask != m_Mask)
49  {
50  m_Mask = mask;
51  this->Modified();
52  }
53  }
54 
56  {
57  }
58 
59  void HotspotMaskGenerator::SetHotspotRadiusInMM(double radiusInMillimeter)
60  {
61  if(radiusInMillimeter != m_HotspotRadiusinMM)
62  {
63  m_HotspotRadiusinMM = radiusInMillimeter;
64  this->Modified();
65  }
66  }
67 
69  {
70  return m_HotspotRadiusinMM;
71  }
72 
74  {
75  return m_HotspotMustBeCompletelyInsideImage;
76  }
77 
79  {
80  if (m_HotspotMustBeCompletelyInsideImage != mustBeCompletelyInImage)
81  {
82  m_HotspotMustBeCompletelyInsideImage = mustBeCompletelyInImage;
83  this->Modified();
84  }
85  }
86 
87 
89  {
90  if (IsUpdateRequired())
91  {
92  if ( m_inputImage.IsNull() )
93  {
94  throw std::runtime_error( "Error: image empty!" );
95  }
96 
97  if ( m_TimeStep >= m_inputImage->GetTimeSteps() )
98  {
99  throw std::runtime_error( "Error: invalid time step!" );
100  }
101 
103  imageTimeSelector->SetInput( m_inputImage );
104  imageTimeSelector->SetTimeNr( m_TimeStep );
105  imageTimeSelector->UpdateLargestPossibleRegion();
106  mitk::Image::Pointer timeSliceImage = imageTimeSelector->GetOutput();
107 
108  m_internalImage = timeSliceImage;
109  m_internalMask2D = nullptr; // is this correct when this variable holds a smart pointer?
110  m_internalMask3D = nullptr;
111 
112  if ( m_Mask != nullptr )
113  {
114  m_Mask->SetTimeStep(m_TimeStep);
115  mitk::Image::Pointer timeSliceMask = m_Mask->GetMask();
116 
117  if ( m_internalImage->GetDimension() == 3 )
118  {
119  CastToItkImage(timeSliceMask, m_internalMask3D);
120  AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 3, m_internalMask3D, m_Label);
121  }
122  else if ( m_internalImage->GetDimension() == 2 )
123  {
124  CastToItkImage(timeSliceMask, m_internalMask2D);
125  AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 2, m_internalMask2D, m_Label);
126  }
127  else
128  {
129  throw std::runtime_error( "Error: invalid image dimension" );
130  }
131  }
132  else
133  {
134 
135  if ( m_internalImage->GetDimension() == 3 )
136  {
137  AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 3, m_internalMask3D, m_Label);
138  }
139  else if ( m_internalImage->GetDimension() == 2 )
140  {
141  AccessFixedDimensionByItk_2(m_internalImage, CalculateHotspotMask, 2, m_internalMask2D, m_Label);
142  }
143  else
144  {
145  throw std::runtime_error( "Error: invalid image dimension" );
146  }
147  }
148  this->Modified();
149  }
150 
151  m_InternalMaskUpdateTime = m_InternalMask->GetMTime();
152  return m_InternalMask;
153  }
154 
155  void HotspotMaskGenerator::SetTimeStep(unsigned int timeStep)
156  {
157  if (m_TimeStep != timeStep)
158  {
159  m_TimeStep = timeStep;
160  }
161  }
162 
163  void HotspotMaskGenerator::SetLabel(unsigned short label)
164  {
165  if (label != m_Label)
166  {
167  m_Label = label;
168  this->Modified();
169  }
170  }
171 
173  {
174  this->GetMask(); // make sure we are up to date
175  return m_ConvolutionImageMinIndex;
176  }
177 
179  {
180  this->GetMask(); // make sure we are up to date
181  return m_ConvolutionImageMaxIndex;
182  }
183 
184  template <typename TPixel, unsigned int VImageDimension >
186  HotspotMaskGenerator::CalculateExtremaWorld( const itk::Image<TPixel, VImageDimension>* inputImage,
187  typename itk::Image<unsigned short, VImageDimension>::Pointer maskImage,
188  double neccessaryDistanceToImageBorderInMM,
189  unsigned int label )
190  {
191  typedef itk::Image< TPixel, VImageDimension > ImageType;
192  typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
193 
194  typedef itk::ImageRegionConstIteratorWithIndex<MaskImageType> MaskImageIteratorType;
195  typedef itk::ImageRegionConstIteratorWithIndex<ImageType> InputImageIndexIteratorType;
196 
197  typename ImageType::SpacingType spacing = inputImage->GetSpacing();
198 
199  ImageExtrema minMax;
200  minMax.Defined = false;
201  minMax.MaxIndex.set_size(VImageDimension);
202  minMax.MaxIndex.set_size(VImageDimension);
203 
204  typename ImageType::RegionType allowedExtremaRegion = inputImage->GetLargestPossibleRegion();
205 
206  bool keepDistanceToImageBorders( neccessaryDistanceToImageBorderInMM > 0 );
207  if (keepDistanceToImageBorders)
208  {
209  itk::IndexValueType distanceInPixels[VImageDimension];
210  for(unsigned short dimension = 0; dimension < VImageDimension; ++dimension)
211  {
212  // To confirm that the whole hotspot is inside the image we have to keep a specific distance to the image-borders, which is as long as
213  // the radius. To get the amount of indices we divide the radius by spacing and add 0.5 because voxels are center based:
214  // For example with a radius of 2.2 and a spacing of 1 two indices are enough because 2.2 / 1 + 0.5 = 2.7 => 2.
215  // But with a radius of 2.7 we need 3 indices because 2.7 / 1 + 0.5 = 3.2 => 3
216  distanceInPixels[dimension] = int( neccessaryDistanceToImageBorderInMM / spacing[dimension] + 0.5);
217  }
218 
219  allowedExtremaRegion.ShrinkByRadius(distanceInPixels);
220  }
221 
222  InputImageIndexIteratorType imageIndexIt(inputImage, allowedExtremaRegion);
223 
224  float maxValue = itk::NumericTraits<float>::min();
225  float minValue = itk::NumericTraits<float>::max();
226 
227  typename ImageType::IndexType maxIndex;
228  typename ImageType::IndexType minIndex;
229 
230  for(unsigned short i = 0; i < VImageDimension; ++i)
231  {
232  maxIndex[i] = 0;
233  minIndex[i] = 0;
234  }
235 
236  if (maskImage != nullptr)
237  {
238  MaskImageIteratorType maskIt(maskImage, maskImage->GetLargestPossibleRegion());
239  typename ImageType::IndexType imageIndex;
240  typename ImageType::PointType worldPosition;
241  typename ImageType::IndexType maskIndex;
242 
243  for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
244  {
245  imageIndex = maskIndex = maskIt.GetIndex();
246 
247  if(maskIt.Get() == label)
248  {
249  if( allowedExtremaRegion.IsInside(imageIndex) )
250  {
251  imageIndexIt.SetIndex( imageIndex );
252  double value = imageIndexIt.Get();
253  minMax.Defined = true;
254 
255  //Calculate minimum, maximum and corresponding index-values
256  if( value > maxValue )
257  {
258  maxIndex = imageIndexIt.GetIndex();
259  maxValue = value;
260  }
261 
262  if(value < minValue )
263  {
264  minIndex = imageIndexIt.GetIndex();
265  minValue = value;
266  }
267  }
268  }
269  }
270  }
271  else
272  {
273  for(imageIndexIt.GoToBegin(); !imageIndexIt.IsAtEnd(); ++imageIndexIt)
274  {
275  double value = imageIndexIt.Get();
276  minMax.Defined = true;
277 
278  //Calculate minimum, maximum and corresponding index-values
279  if( value > maxValue )
280  {
281  maxIndex = imageIndexIt.GetIndex();
282  maxValue = value;
283  }
284 
285  if(value < minValue )
286  {
287  minIndex = imageIndexIt.GetIndex();
288  minValue = value;
289  }
290  }
291  }
292 
293  minMax.MaxIndex.set_size(VImageDimension);
294  minMax.MinIndex.set_size(VImageDimension);
295 
296  for(unsigned int i = 0; i < minMax.MaxIndex.size(); ++i)
297  {
298  minMax.MaxIndex[i] = maxIndex[i];
299  }
300 
301  for(unsigned int i = 0; i < minMax.MinIndex.size(); ++i)
302  {
303  minMax.MinIndex[i] = minIndex[i];
304  }
305 
306  minMax.Max = maxValue;
307  minMax.Min = minValue;
308 
309  return minMax;
310  }
311 
312  template <unsigned int VImageDimension>
313  itk::Size<VImageDimension>
314  HotspotMaskGenerator::CalculateConvolutionKernelSize( double spacing[VImageDimension],
315  double radiusInMM )
316  {
317  typedef itk::Image< float, VImageDimension > KernelImageType;
318  typedef typename KernelImageType::SizeType SizeType;
319  SizeType maskSize;
320 
321  for(unsigned int i = 0; i < VImageDimension; ++i)
322  {
323  maskSize[i] = static_cast<int>( 2 * radiusInMM / spacing[i]);
324 
325  // We always want an uneven size to have a clear center point in the convolution mask
326  if(maskSize[i] % 2 == 0 )
327  {
328  ++maskSize[i];
329  }
330  }
331  return maskSize;
332  }
333 
334  template <unsigned int VImageDimension>
336  HotspotMaskGenerator::GenerateHotspotSearchConvolutionKernel(double mmPerPixel[VImageDimension],
337  double radiusInMM )
338  {
339  std::stringstream ss;
340  for (unsigned int i = 0; i < VImageDimension; ++i)
341  {
342  ss << mmPerPixel[i];
343  if (i < VImageDimension -1)
344  ss << ",";
345  }
346  MITK_DEBUG << "Update convolution kernel for spacing (" << ss.str() << ") and radius " << radiusInMM << "mm";
347 
348 
349  double radiusInMMSquared = radiusInMM * radiusInMM;
350  typedef itk::Image< float, VImageDimension > KernelImageType;
351  typename KernelImageType::Pointer convolutionKernel = KernelImageType::New();
352 
353  // Calculate size and allocate mask image
354  typedef typename KernelImageType::SizeType SizeType;
355  SizeType maskSize = this->CalculateConvolutionKernelSize<VImageDimension>(mmPerPixel, radiusInMM);
356 
357  mitk::Point3D convolutionMaskCenterIndex;
358  convolutionMaskCenterIndex.Fill(0.0);
359  for(unsigned int i = 0; i < VImageDimension; ++i)
360  {
361  convolutionMaskCenterIndex[i] = 0.5 * (double)(maskSize[i]-1);
362  }
363 
364  typedef typename KernelImageType::IndexType IndexType;
365  IndexType maskIndex;
366  maskIndex.Fill(0);
367 
368  typedef typename KernelImageType::RegionType RegionType;
369  RegionType maskRegion;
370  maskRegion.SetSize(maskSize);
371  maskRegion.SetIndex(maskIndex);
372 
373  convolutionKernel->SetRegions(maskRegion);
374  convolutionKernel->SetSpacing(mmPerPixel);
375  convolutionKernel->Allocate();
376 
377  // Fill mask image values by subsampling the image grid
378  typedef itk::ImageRegionIteratorWithIndex<KernelImageType> MaskIteratorType;
379  MaskIteratorType maskIt(convolutionKernel,maskRegion);
380 
381  int numberOfSubVoxelsPerDimension = 2; // per dimension!
382  int numberOfSubVoxels = ::pow( static_cast<float>(numberOfSubVoxelsPerDimension), static_cast<float>(VImageDimension) );
383  double subVoxelSizeInPixels = 1.0 / (double)numberOfSubVoxelsPerDimension;
384  double valueOfOneSubVoxel = 1.0 / (double)numberOfSubVoxels;
385  mitk::Point3D subVoxelIndexPosition;
386  double distanceSquared = 0.0;
387 
388  typedef itk::ContinuousIndex<double, VImageDimension> ContinuousIndexType;
389  for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
390  {
391  ContinuousIndexType indexPoint(maskIt.GetIndex());
392  mitk::Point3D voxelPosition;
393  for (unsigned int dimension = 0; dimension < VImageDimension; ++dimension)
394  {
395  voxelPosition[dimension] = indexPoint[dimension];
396  }
397 
398  double maskValue = 0.0;
399  mitk::Vector3D subVoxelOffset; subVoxelOffset.Fill(0.0);
400  // iterate sub-voxels by iterating all possible offsets
401  for (subVoxelOffset[0] = -0.5 + subVoxelSizeInPixels / 2.0;
402  subVoxelOffset[0] < +0.5;
403  subVoxelOffset[0] += subVoxelSizeInPixels)
404  {
405  for (subVoxelOffset[1] = -0.5 + subVoxelSizeInPixels / 2.0;
406  subVoxelOffset[1] < +0.5;
407  subVoxelOffset[1] += subVoxelSizeInPixels)
408  {
409  for (subVoxelOffset[2] = -0.5 + subVoxelSizeInPixels / 2.0;
410  subVoxelOffset[2] < +0.5;
411  subVoxelOffset[2] += subVoxelSizeInPixels)
412  {
413  subVoxelIndexPosition = voxelPosition + subVoxelOffset; // this COULD be integrated into the for-loops if neccessary (add voxelPosition to initializer and end condition)
414  distanceSquared =
415  (subVoxelIndexPosition[0]-convolutionMaskCenterIndex[0]) * mmPerPixel[0] * (subVoxelIndexPosition[0]-convolutionMaskCenterIndex[0]) * mmPerPixel[0]
416  + (subVoxelIndexPosition[1]-convolutionMaskCenterIndex[1]) * mmPerPixel[1] * (subVoxelIndexPosition[1]-convolutionMaskCenterIndex[1]) * mmPerPixel[1]
417  + (subVoxelIndexPosition[2]-convolutionMaskCenterIndex[2]) * mmPerPixel[2] * (subVoxelIndexPosition[2]-convolutionMaskCenterIndex[2]) * mmPerPixel[2];
418 
419  if (distanceSquared <= radiusInMMSquared)
420  {
421  maskValue += valueOfOneSubVoxel;
422  }
423  }
424  }
425  }
426  maskIt.Set( maskValue );
427  }
428 
429  return convolutionKernel;
430  }
431 
432  template <typename TPixel, unsigned int VImageDimension>
434  HotspotMaskGenerator::GenerateConvolutionImage( const itk::Image<TPixel, VImageDimension>* inputImage )
435  {
436  double mmPerPixel[VImageDimension];
437  for (unsigned int dimension = 0; dimension < VImageDimension; ++dimension)
438  {
439  mmPerPixel[dimension] = inputImage->GetSpacing()[dimension];
440  }
441 
442  // update convolution kernel
443  typedef itk::Image< float, VImageDimension > KernelImageType;
444  typename KernelImageType::Pointer convolutionKernel = this->GenerateHotspotSearchConvolutionKernel<VImageDimension>(mmPerPixel, m_HotspotRadiusinMM);
445 
446  // update convolution image
447  typedef itk::Image< TPixel, VImageDimension > InputImageType;
448  typedef itk::Image< TPixel, VImageDimension > ConvolutionImageType;
449  typedef itk::FFTConvolutionImageFilter<InputImageType,
450  KernelImageType,
451  ConvolutionImageType> ConvolutionFilterType;
452 
453  typename ConvolutionFilterType::Pointer convolutionFilter = ConvolutionFilterType::New();
454  typedef itk::ConstantBoundaryCondition<InputImageType, InputImageType> BoundaryConditionType;
455  BoundaryConditionType boundaryCondition;
456  boundaryCondition.SetConstant(0.0);
457 
458  if (m_HotspotMustBeCompletelyInsideImage)
459  {
460  // overwrite default boundary condition
461  convolutionFilter->SetBoundaryCondition(&boundaryCondition);
462  }
463 
464  convolutionFilter->SetInput(inputImage);
465  convolutionFilter->SetKernelImage(convolutionKernel);
466  convolutionFilter->SetNormalize(true);
467  MITK_DEBUG << "Update Convolution image for hotspot search";
468  convolutionFilter->UpdateLargestPossibleRegion();
469 
470  typename ConvolutionImageType::Pointer convolutionImage = convolutionFilter->GetOutput();
471  convolutionImage->SetSpacing( inputImage->GetSpacing() ); // only workaround because convolution filter seems to ignore spacing of input image
472 
473  return convolutionImage;
474  }
475 
476  template < typename TPixel, unsigned int VImageDimension>
477  void
478  HotspotMaskGenerator::FillHotspotMaskPixels( itk::Image<TPixel, VImageDimension>* maskImage,
479  itk::Point<double, VImageDimension> sphereCenter,
480  double sphereRadiusInMM )
481  {
482  typedef itk::Image< TPixel, VImageDimension > MaskImageType;
483  typedef itk::ImageRegionIteratorWithIndex<MaskImageType> MaskImageIteratorType;
484 
485  MaskImageIteratorType maskIt(maskImage, maskImage->GetLargestPossibleRegion());
486 
487  typename MaskImageType::IndexType maskIndex;
488  typename MaskImageType::PointType worldPosition;
489 
490  // this is not very smart. I would rather use a 0 initialized mask (not the case here -> blame CalculateHotspotMask) and find the region where I need to iterate over, then iterate only over the small region
491  for(maskIt.GoToBegin(); !maskIt.IsAtEnd(); ++maskIt)
492  {
493  maskIndex = maskIt.GetIndex();
494  maskImage->TransformIndexToPhysicalPoint(maskIndex, worldPosition);
495  maskIt.Set( worldPosition.EuclideanDistanceTo(sphereCenter) <= sphereRadiusInMM ? 1 : 0 );
496  }
497  }
498 
499  template <typename TPixel, unsigned int VImageDimension>
500  void
501  HotspotMaskGenerator::CalculateHotspotMask(itk::Image<TPixel, VImageDimension>* inputImage,
502  typename itk::Image<unsigned short, VImageDimension>::Pointer maskImage,
503  unsigned int label)
504  {
505  typedef itk::Image< TPixel, VImageDimension > InputImageType;
506  typedef itk::Image< TPixel, VImageDimension > ConvolutionImageType;
507  typedef itk::Image< unsigned short, VImageDimension > MaskImageType;
508 
509  typename ConvolutionImageType::Pointer convolutionImage = this->GenerateConvolutionImage(inputImage);
510 
511  if (convolutionImage.IsNull())
512  {
513  MITK_ERROR << "Empty convolution image in CalculateHotspotStatistics(). We should never reach this state (logic error).";
514  throw std::logic_error("Empty convolution image in CalculateHotspotStatistics()");
515  }
516 
517  // if mask image is not defined, create an image of the same size as inputImage and fill it with 1's
518  // there is maybe a better way to do this!?
519  if (maskImage == nullptr)
520  {
521  maskImage = MaskImageType::New();
522  typename MaskImageType::RegionType maskRegion = inputImage->GetLargestPossibleRegion();
523  typename MaskImageType::SpacingType maskSpacing = inputImage->GetSpacing();
524  typename MaskImageType::PointType maskOrigin = inputImage->GetOrigin();
525  typename MaskImageType::DirectionType maskDirection = inputImage->GetDirection();
526  maskImage->SetRegions(maskRegion);
527  maskImage->Allocate();
528  maskImage->SetOrigin(maskOrigin);
529  maskImage->SetSpacing(maskSpacing);
530  maskImage->SetDirection(maskDirection);
531 
532  maskImage->FillBuffer(1);
533 
534  label = 1;
535  }
536 
537  // find maximum in convolution image, given the current mask
538  double requiredDistanceToBorder = m_HotspotMustBeCompletelyInsideImage ? m_HotspotRadiusinMM : -1.0;
539  ImageExtrema convolutionImageInformation = CalculateExtremaWorld(convolutionImage.GetPointer(), maskImage, requiredDistanceToBorder, label);
540 
541  bool isHotspotDefined = convolutionImageInformation.Defined;
542 
543  if (!isHotspotDefined)
544  {
545  MITK_ERROR << "No origin of hotspot-sphere was calculated!";
546  m_InternalMask = nullptr;
547  }
548  else
549  {
550  // create a binary mask around the "hotspot" region, fill the shape of a sphere around our hotspot center
551 // typename DuplicatorType::Pointer copyMachine = DuplicatorType::New();
552 // copyMachine->SetInputImage(inputImage);
553 // copyMachine->Update();
554 
555 // typename CastFilterType::Pointer caster = CastFilterType::New();
556 // caster->SetInput( copyMachine->GetOutput() );
557 // caster->Update();
558  typename MaskImageType::Pointer hotspotMaskITK = MaskImageType::New();
559  hotspotMaskITK->SetOrigin(inputImage->GetOrigin());
560  hotspotMaskITK->SetSpacing(inputImage->GetSpacing());
561  hotspotMaskITK->SetLargestPossibleRegion(inputImage->GetLargestPossibleRegion());
562  hotspotMaskITK->SetBufferedRegion(inputImage->GetBufferedRegion());
563  hotspotMaskITK->SetDirection(inputImage->GetDirection());
564  hotspotMaskITK->SetNumberOfComponentsPerPixel(inputImage->GetNumberOfComponentsPerPixel());
565  hotspotMaskITK->Allocate();
566  hotspotMaskITK->FillBuffer(1);
567 
568  typedef typename InputImageType::IndexType IndexType;
569  IndexType maskCenterIndex;
570  for (unsigned int d =0; d< VImageDimension;++d)
571  {
572  maskCenterIndex[d]=convolutionImageInformation.MaxIndex[d];
573  }
574 
575  typename ConvolutionImageType::PointType maskCenter;
576  inputImage->TransformIndexToPhysicalPoint(maskCenterIndex,maskCenter);
577 
578  FillHotspotMaskPixels(hotspotMaskITK.GetPointer(), maskCenter, m_HotspotRadiusinMM);
579 
580  //obtain mitk::Image::Pointer from itk::Image
581  mitk::Image::Pointer hotspotMaskAsMITKImage = mitk::GrabItkImageMemory(hotspotMaskITK);
582 
583  m_InternalMask = hotspotMaskAsMITKImage;
584  m_ConvolutionImageMaxIndex = convolutionImageInformation.MaxIndex;
585  m_ConvolutionImageMinIndex = convolutionImageInformation.MinIndex;
586  }
587  }
588 
589  bool HotspotMaskGenerator::IsUpdateRequired() const
590  {
591  unsigned long thisClassTimeStamp = this->GetMTime();
592  unsigned long internalMaskTimeStamp = m_InternalMask->GetMTime();
593  unsigned long maskGeneratorTimeStamp = m_Mask->GetMTime();
594  unsigned long inputImageTimeStamp = m_inputImage->GetMTime();
595 
596  if (thisClassTimeStamp > m_InternalMaskUpdateTime) // inputs have changed
597  {
598  return true;
599  }
600 
601  if (m_InternalMaskUpdateTime < maskGeneratorTimeStamp || m_InternalMaskUpdateTime < inputImageTimeStamp) // mask image has changed outside of this class
602  {
603  return true;
604  }
605 
606  if (internalMaskTimeStamp > m_InternalMaskUpdateTime) // internal mask has been changed outside of this class
607  {
608  return true;
609  }
610 
611  return false;
612  }
613 }
vnl_vector< int > GetHotspotIndex()
Returns the image index where the hotspot is located.
void SetHotspotRadiusInMM(double radiusInMillimeter)
Set the radius of the hotspot (in MM)
mitk::Image::ConstPointer m_inputImage
itk::Image< unsigned char, 3 > ImageType
#define MITK_ERROR
Definition: mitkLogMacros.h:20
#define MITK_DEBUG
Definition: mitkLogMacros.h:22
DataCollection - Class to facilitate loading/accessing structured data.
void SetLabel(unsigned short label)
If a maskGenerator is set, this detemines which mask value is used.
void SetInputImage(mitk::Image::Pointer inputImage)
Set the input image. Required for this class.
void SetTimeStep(unsigned int timeStep) override
SetTimeStep is used to set the time step for which the mask is to be generated.
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.
void SetMask(MaskGenerator::Pointer mask)
Set a mask (can be nullptr if no mask is desired)
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
itk::Image< unsigned char, 3 > MaskImageType
Definition: CLBrainMask.cpp:32
static T max(T x, T y)
Definition: svm.cpp:56
mitk::Image::Pointer m_InternalMask
vnl_vector< int > GetConvolutionImageMinIndex()
Returns the index where the convolution image is minimal (darkest spot in image)
void SetHotspotMustBeCompletelyInsideImage(bool hotspotCompletelyInsideImage)
Define whether the hotspot must be completely inside the image. Default is true.
static Pointer New()
static T min(T x, T y)
Definition: svm.cpp:53
mitk::Image::Pointer GetMask() override
Computes and returns the hotspot mask. The hotspot mask has the same size as the input image...
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::Image::Pointer mask
const double & GetHotspotRadiusinMM() const
static Pointer New()