Medical Imaging Interaction Toolkit  2018.4.99-dfa0c14e
Medical Imaging Interaction Toolkit
mitkBoundingObjectCutter.txx
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 MITKBOUNDINGOBJECTCUTTER_TXX
14 #define MITKBOUNDINGOBJECTCUTTER_TXX
15 
16 #include "itkImageRegionIteratorWithIndex.h"
17 #include "mitkImageToItk.h"
18 #include "mitkStatusBar.h"
19 
20 namespace mitk
21 {
22  template <typename TPixel, unsigned int VImageDimension, typename TOutputPixel>
23  void CutImageWithOutputTypeSelect(itk::Image<TPixel, VImageDimension> *inputItkImage,
24  mitk::BoundingObjectCutter *cutter,
25  int /* boTimeStep */,
26  TOutputPixel * /* dummy */)
27  {
28  typedef itk::Image<TPixel, VImageDimension> ItkInputImageType;
29  typedef itk::Image<TOutputPixel, VImageDimension> ItkOutputImageType;
30  typedef typename itk::ImageBase<VImageDimension>::RegionType ItkRegionType;
31  typedef itk::ImageRegionIteratorWithIndex<ItkInputImageType> ItkInputImageIteratorType;
32  typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType;
33 
34  if (cutter->m_BoundingObject.IsNull())
35  return;
36 
37  if (inputItkImage == nullptr)
38  {
39  mitk::StatusBar::GetInstance()->DisplayErrorText(
40  "An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
41  std::cout << " image is NULL...returning" << std::endl;
42  return;
43  }
44 
45  // PART 1: convert m_InputRequestedReg ion (type mitk::SlicedData::RegionType)
46  // into ITK-image-region (ItkImageType::RegionType)
47  // unfortunately, we cannot use input->GetRequestedRegion(), because it
48  // has been destroyed by the mitk::CastToItkImage call of PART 1
49  // (which sets the m_RequestedRegion to the LargestPossibleRegion).
50  // Thus, use our own member m_InputRequestedRegion insead.
51 
52  // first convert the index
53  typename ItkRegionType::IndexType::IndexValueType tmpIndex[3];
54  itk2vtk(cutter->m_InputRequestedRegion.GetIndex(), tmpIndex);
55  typename ItkRegionType::IndexType index;
56  index.SetIndex(tmpIndex);
57 
58  // then convert the size
59  typename ItkRegionType::SizeType::SizeValueType tmpSize[3];
60  itk2vtk(cutter->m_InputRequestedRegion.GetSize(), tmpSize);
61  typename ItkRegionType::SizeType size;
62  size.SetSize(tmpSize);
63 
64  // create the ITK-image-region out of index and size
65  ItkRegionType inputRegionOfInterest(index, size);
66 
67  // PART 2: get access to the MITK output image via an ITK image
68  typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk =
69  mitk::ImageToItk<ItkOutputImageType>::New();
70  outputimagetoitk->SetInput(cutter->m_OutputTimeSelector->GetOutput());
71  outputimagetoitk->Update();
72  typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
73 
74  // PART 3: iterate over input and output using ITK iterators
75 
76  // create the iterators
77  ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest);
78  ItkOutputImageIteratorType outputIt(outputItkImage, outputItkImage->GetLargestPossibleRegion());
79 
80  // Cut the boundingbox out of the image by iterating through
81  // all pixels and checking if they are inside using IsInside()
82  cutter->m_OutsidePixelCount = 0;
83  cutter->m_InsidePixelCount = 0;
84  mitk::Point3D p;
85  mitk::BaseGeometry *inputGeometry = cutter->GetInput()->GetGeometry();
86 
87  TOutputPixel outsideValue;
88  if (cutter->m_AutoOutsideValue)
89  {
90  outsideValue = itk::NumericTraits<TOutputPixel>::min();
91  }
92  else
93  {
94  outsideValue = (TOutputPixel)cutter->m_OutsideValue;
95  }
96  // shall we use a fixed value for each inside pixel?
97  if (cutter->GetUseInsideValue())
98  {
99  TOutputPixel insideValue = (TOutputPixel)cutter->m_InsideValue;
100  // yes, use a fixed value for each inside pixel (create a binary mask of the bounding object)
101  for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
102  {
103  vtk2itk(inputIt.GetIndex(), p);
104  inputGeometry->IndexToWorld(p, p);
105  if (cutter->m_BoundingObject->IsInside(p))
106  {
107  outputIt.Set(insideValue);
108  ++cutter->m_InsidePixelCount;
109  }
110  else
111  {
112  outputIt.Set(outsideValue);
113  ++cutter->m_OutsidePixelCount;
114  }
115  }
116  }
117  else
118  {
119  // no, use the pixel value of the original image (normal cutting)
120  for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
121  {
122  vtk2itk(inputIt.GetIndex(), p);
123  inputGeometry->IndexToWorld(p, p);
124  if (cutter->m_BoundingObject->IsInside(p))
125  {
126  outputIt.Set((TOutputPixel)inputIt.Value());
127  ++cutter->m_InsidePixelCount;
128  }
129  else
130  {
131  outputIt.Set(outsideValue);
132  ++cutter->m_OutsidePixelCount;
133  }
134  }
135  }
136  }
137 
138  template <typename TPixel, unsigned int VImageDimension, typename TOutputPixel>
139  void CutImageWithOutputTypeSelect(itk::VectorImage<TPixel, VImageDimension> *inputItkImage,
140  mitk::BoundingObjectCutter *cutter,
141  int /* boTimeStep */,
142  TOutputPixel * /* dummy */)
143  {
144  typedef itk::VectorImage<TPixel, VImageDimension> ItkInputImageType;
145  typedef itk::VectorImage<TOutputPixel, VImageDimension> ItkOutputImageType;
146  typedef typename itk::ImageBase<VImageDimension>::RegionType ItkRegionType;
147  typedef itk::ImageRegionIteratorWithIndex<ItkInputImageType> ItkInputImageIteratorType;
148  typedef itk::ImageRegionIteratorWithIndex<ItkOutputImageType> ItkOutputImageIteratorType;
149 
150  if (cutter->m_BoundingObject.IsNull())
151  return;
152 
153  if (inputItkImage == nullptr)
154  {
155  mitk::StatusBar::GetInstance()->DisplayErrorText(
156  "An internal error occurred. Can't convert Image. Please report to bugs@mitk.org");
157  std::cout << " image is NULL...returning" << std::endl;
158  return;
159  }
160 
161  // PART 1: convert m_InputRequestedReg ion (type mitk::SlicedData::RegionType)
162  // into ITK-image-region (ItkImageType::RegionType)
163  // unfortunately, we cannot use input->GetRequestedRegion(), because it
164  // has been destroyed by the mitk::CastToItkImage call of PART 1
165  // (which sets the m_RequestedRegion to the LargestPossibleRegion).
166  // Thus, use our own member m_InputRequestedRegion insead.
167 
168  // first convert the index
169  typename ItkRegionType::IndexType::IndexValueType tmpIndex[3];
170  itk2vtk(cutter->m_InputRequestedRegion.GetIndex(), tmpIndex);
171  typename ItkRegionType::IndexType index;
172  index.SetIndex(tmpIndex);
173 
174  // then convert the size
175  typename ItkRegionType::SizeType::SizeValueType tmpSize[3];
176  itk2vtk(cutter->m_InputRequestedRegion.GetSize(), tmpSize);
177  typename ItkRegionType::SizeType size;
178  size.SetSize(tmpSize);
179 
180  // create the ITK-image-region out of index and size
181  ItkRegionType inputRegionOfInterest(index, size);
182 
183  // PART 2: get access to the MITK output image via an ITK image
184  typename mitk::ImageToItk<ItkOutputImageType>::Pointer outputimagetoitk =
185  mitk::ImageToItk<ItkOutputImageType>::New();
186  outputimagetoitk->SetInput(cutter->m_OutputTimeSelector->GetOutput());
187  outputimagetoitk->Update();
188  typename ItkOutputImageType::Pointer outputItkImage = outputimagetoitk->GetOutput();
189 
190  // PART 3: iterate over input and output using ITK iterators
191 
192  // create the iterators
193  ItkInputImageIteratorType inputIt(inputItkImage, inputRegionOfInterest);
194  ItkOutputImageIteratorType outputIt(outputItkImage, outputItkImage->GetLargestPossibleRegion());
195 
196  // Cut the boundingbox out of the image by iterating through
197  // all pixels and checking if they are inside using IsInside()
198  cutter->m_OutsidePixelCount = 0;
199  cutter->m_InsidePixelCount = 0;
200  mitk::Point3D p;
201  mitk::BaseGeometry *inputGeometry = cutter->GetInput()->GetGeometry();
202 
203  typename ItkOutputImageType::PixelType outsideValue;
204  outsideValue.SetSize(outputItkImage->GetVectorLength());
205  if (cutter->m_AutoOutsideValue)
206  {
207  outsideValue.Fill(itk::NumericTraits<TOutputPixel>::min());
208  }
209  else
210  {
211  outsideValue.Fill(cutter->m_OutsideValue);
212  }
213  // shall we use a fixed value for each inside pixel?
214  if (cutter->GetUseInsideValue())
215  {
216  typename ItkOutputImageType::PixelType insideValue;
217  insideValue.Fill(cutter->m_InsideValue);
218  // yes, use a fixed value for each inside pixel (create a binary mask of the bounding object)
219  for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
220  {
221  vtk2itk(inputIt.GetIndex(), p);
222  inputGeometry->IndexToWorld(p, p);
223  if (cutter->m_BoundingObject->IsInside(p))
224  {
225  outputIt.Set(insideValue);
226  ++cutter->m_InsidePixelCount;
227  }
228  else
229  {
230  outputIt.Set(outsideValue);
231  ++cutter->m_OutsidePixelCount;
232  }
233  }
234  }
235  else
236  {
237  // no, use the pixel value of the original image (normal cutting)
238  for (inputIt.GoToBegin(), outputIt.GoToBegin(); !inputIt.IsAtEnd(); ++inputIt, ++outputIt)
239  {
240  vtk2itk(inputIt.GetIndex(), p);
241  inputGeometry->IndexToWorld(p, p);
242  if (cutter->m_BoundingObject->IsInside(p))
243  {
244  outputIt.Set(inputIt.Get());
245  ++cutter->m_InsidePixelCount;
246  }
247  else
248  {
249  outputIt.Set(outsideValue);
250  ++cutter->m_OutsidePixelCount;
251  }
252  }
253  }
254  }
255 
256  template <typename TPixel, unsigned int VImageDimension>
257  void CutImage(itk::Image<TPixel, VImageDimension> *inputItkImage, mitk::BoundingObjectCutter *cutter, int boTimeStep)
258  {
259  TPixel *dummy = nullptr;
260  CutImageWithOutputTypeSelect<TPixel, VImageDimension, TPixel>(inputItkImage, cutter, boTimeStep, dummy);
261  }
262 
263  template <typename TPixel, unsigned int VImageDimension>
264  void CutImage(itk::VectorImage<TPixel, VImageDimension> *inputItkImage,
265  mitk::BoundingObjectCutter *cutter,
266  int boTimeStep)
267  {
268  TPixel *dummy = nullptr;
269  CutImageWithOutputTypeSelect<TPixel, VImageDimension, TPixel>(inputItkImage, cutter, boTimeStep, dummy);
270  }
271 
272 } // of namespace mitk
273 
274 #include "mitkImageCast.h"
275 
276 #endif // of MITKBOUNDINGOBJECTCUTTER_TXX