Medical Imaging Interaction Toolkit  2018.4.99-4c24e3cb
Medical Imaging Interaction Toolkit
mitkMaskUtilities.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 #ifndef MITKMASKUTIL_CPP
14 #define MITKMASKUTIL_CPP
15 
16 #include <mitkMaskUtilities.h>
17 //#include <mitkImageCast.h>
18 #include <mitkImageAccessByItk.h>
19 #include <itkExtractImageFilter.h>
20 #include <itkChangeInformationImageFilter.h>
21 #include <mitkITKImageImport.h>
22 
23 namespace mitk
24 {
25  template <class TPixel, unsigned int VImageDimension>
27  {
28  if (image != m_Image)
29  {
30  m_Image = image;
31  }
32  }
33 
34  template <class TPixel, unsigned int VImageDimension>
36  {
37  if (mask != m_Mask)
38  {
39  m_Mask = mask;
40  }
41  }
42 
43  template <class TPixel, unsigned int VImageDimension>
45  {
46  if (m_Mask==nullptr || m_Image==nullptr)
47  {
48  MITK_ERROR << "Set an image and a mask first";
49  }
50 
51  typedef itk::Image< TPixel, VImageDimension > ImageType;
52  typedef typename ImageType::PointType PointType;
53  typedef typename ImageType::DirectionType DirectionType;
54 
55  bool maskSanity = true;
56 
57 
58  if (m_Mask==nullptr)
59  {
60  MITK_ERROR << "Something went wrong when casting the mitk mask image to an itk mask image. Do the mask and the input image have the same dimension?";
61  // note to self: We could try to convert say a 2d mask to a 3d mask if the image is 3d. (mask and image dimension have to match.)
62  }
63  // check direction
64  DirectionType imageDirection = m_Image->GetDirection();
65  DirectionType maskDirection = m_Mask->GetDirection();
66  for(unsigned int i = 0; i < imageDirection.ColumnDimensions; ++i )
67  {
68  for(unsigned int j = 0; j < imageDirection.ColumnDimensions; ++j )
69  {
70  double differenceDirection = imageDirection[i][j] - maskDirection[i][j];
71  if ( fabs( differenceDirection ) > mitk::eps )
72  {
73  double differenceDirection = imageDirection[i][j] - maskDirection[i][j];
74  if ( fabs( differenceDirection ) > 0.001 /*mitk::eps*/ ) // TODO: temp fix (bug 17121)
75  {
76  maskSanity = false;
77  MITK_INFO << "Mask needs to have same direction as image! (Image direction: " << imageDirection << "; Mask direction: " << maskDirection << ")";
78  }
79  }
80  }
81  }
82 
83  // check spacing
84  PointType imageSpacing = m_Image->GetSpacing();
85  PointType maskSpacing = m_Mask->GetSpacing();
86  for (unsigned int i = 0; i < VImageDimension; i++)
87  {
88  if ( fabs( maskSpacing[i] - imageSpacing[i] ) > mitk::eps )
89  {
90  maskSanity = false;
91  MITK_INFO << "Spacing of mask and image is not equal. Mask: " << maskSpacing << " image: " << imageSpacing;
92  }
93  }
94 
95  // check alignment
96  // Make sure that the voxels of mask and image are correctly "aligned", i.e., voxel boundaries are the same in both images
97  PointType imageOrigin = m_Image->GetOrigin();
98  PointType maskOrigin = m_Mask->GetOrigin();
99 
100  typedef itk::ContinuousIndex<double, VImageDimension> ContinousIndexType;
101  ContinousIndexType maskOriginContinousIndex, imageOriginContinousIndex;
102 
103  m_Image->TransformPhysicalPointToContinuousIndex(maskOrigin, maskOriginContinousIndex);
104  m_Image->TransformPhysicalPointToContinuousIndex(imageOrigin, imageOriginContinousIndex);
105 
106  for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
107  {
108  double misalignment = maskOriginContinousIndex[i] - floor( maskOriginContinousIndex[i] + 0.5 );
109  // misalignment must be a multiple (int) of spacing in that direction
110  if ( fmod(misalignment,imageSpacing[i]) > mitk::eps )
111  {
112  maskSanity = false;
113  MITK_INFO << "Pixels/voxels of mask and image are not sufficiently aligned! (Misalignment: " << fmod(misalignment,imageSpacing[i]) << ")";
114  }
115  }
116 
117  // mask must be completely inside image region
118  // Make sure that mask region is contained within image region
119  if ( m_Mask!=nullptr &&
120  !m_Image->GetLargestPossibleRegion().IsInside( m_Mask->GetLargestPossibleRegion() ) )
121  {
122  maskSanity = false;
123  MITK_INFO << "Mask region needs to be inside of image region! (Image region: "
124  << m_Image->GetLargestPossibleRegion() << "; Mask region: " << m_Mask->GetLargestPossibleRegion() << ")";
125  }
126  return maskSanity;
127  }
128 
129  template <class TPixel, unsigned int VImageDimension>
130  typename itk::Image<TPixel, VImageDimension>::Pointer MaskUtilities<TPixel, VImageDimension>::ExtractMaskImageRegion()
131  {
132  if (m_Mask==nullptr || m_Image==nullptr)
133  {
134  MITK_ERROR << "Set an image and a mask first";
135  }
136 
137  bool maskSanity = CheckMaskSanity();
138 
139  if (!maskSanity)
140  {
141  MITK_ERROR << "Mask and image are not compatible";
142  }
143 
144  typedef itk::Image< TPixel, VImageDimension > ImageType;
145  typedef itk::Image< unsigned short, VImageDimension > MaskType;
146  typedef itk::ExtractImageFilter< ImageType, ImageType > ExtractImageFilterType;
147 
148  typename ImageType::SizeType imageSize = m_Image->GetBufferedRegion().GetSize();
149  typename ImageType::SizeType maskSize = m_Mask->GetBufferedRegion().GetSize();
150 
151  typename itk::Image<TPixel, VImageDimension>::Pointer extractedImg = itk::Image<TPixel, VImageDimension>::New();
152 
153  bool maskSmallerImage = false;
154  for ( unsigned int i = 0; i < ImageType::ImageDimension; ++i )
155  {
156  if ( maskSize[i] < imageSize[i] )
157  {
158  maskSmallerImage = true;
159  }
160  }
161 
162  if ( maskSmallerImage )
163  {
164  typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New();
165  typename MaskType::PointType maskOrigin = m_Mask->GetOrigin();
166  typename ImageType::PointType imageOrigin = m_Image->GetOrigin();
167  typename MaskType::SpacingType maskSpacing = m_Mask->GetSpacing();
168  typename ImageType::RegionType extractionRegion;
169  typename ImageType::IndexType extractionRegionIndex;
170 
171 
172  for (unsigned int i=0; i < maskOrigin.GetPointDimension(); i++)
173  {
174  extractionRegionIndex[i] = (maskOrigin[i] - imageOrigin[i]) / maskSpacing[i];
175  }
176 
177  extractionRegion.SetIndex(extractionRegionIndex);
178  extractionRegion.SetSize(m_Mask->GetLargestPossibleRegion().GetSize());
179 
180  extractImageFilter->SetInput( m_Image );
181  extractImageFilter->SetExtractionRegion( extractionRegion );
182  extractImageFilter->SetCoordinateTolerance( 0.001 );
183  extractImageFilter->SetDirectionTolerance( 0.001 );
184  extractImageFilter->Update();
185  extractedImg = extractImageFilter->GetOutput();
186  extractedImg->SetOrigin(m_Mask->GetOrigin());
187  extractedImg->SetLargestPossibleRegion(m_Mask->GetLargestPossibleRegion());
188  extractedImg->SetBufferedRegion(m_Mask->GetBufferedRegion());
189 
190  }
191  else
192  {
193  extractedImg = m_Image;
194  }
195 
196  return extractedImg;
197  }
198 
199 }
200 
201 #endif
#define MITK_INFO
Definition: mitkLogMacros.h:18
itk::Image< unsigned char, 3 > ImageType
#define MITK_ERROR
Definition: mitkLogMacros.h:20
itk::Image< TPixel, VImageDimension >::Pointer ExtractMaskImageRegion()
Crops the image to the LargestPossibleRegion of the mask.
DataCollection - Class to facilitate loading/accessing structured data.
bool CheckMaskSanity()
Checks whether mask and image are compatible for joint access (as via iterators). Spacing and directi...
void SetImage(ImageType *image)
Set image.
mitk::Image::Pointer image
itk::Image< unsigned short, VImageDimension > MaskType
itk::Image< TPixel, VImageDimension > ImageType
void SetMask(MaskType *mask)
Set mask.
MITKCORE_EXPORT const ScalarType eps
mitk::Image::Pointer mask