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