Medical Imaging Interaction Toolkit  2018.4.99-3e3f1a6e
Medical Imaging Interaction Toolkit
mitkBoundingObjectCutter.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 "mitkBoundingObject.h"
16 #include "mitkGeometry3D.h"
17 #include "mitkImageAccessByItk.h"
18 #include "mitkTimeHelper.h"
19 
20 #include <cmath>
21 
22 namespace mitk
23 {
25  {
26  m_BoundingObject = const_cast<mitk::BoundingObject *>(boundingObject);
27  // Process object is not const-correct so the const_cast is required here
28  this->ProcessObject::SetNthInput(1, const_cast<mitk::BoundingObject *>(boundingObject));
29  }
30 
33  : m_BoundingObject(nullptr),
34  m_InsideValue(1),
35  m_OutsideValue(0),
36  m_AutoOutsideValue(false),
37  m_UseInsideValue(false),
41  {
42  this->SetNumberOfIndexedInputs(2);
43  this->SetNumberOfRequiredInputs(2);
46  }
47 
51  {
52  mitk::Image *output = this->GetOutput();
53  if ((output->IsInitialized() == false) || (m_BoundingObject.IsNull()) ||
54  (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
55  return;
56  // we have already calculated the spatial part of the
57  // input-requested-region in m_InputRequestedRegion in
58  // GenerateOutputInformation (which is called before
59  // GenerateInputRequestedRegion).
60  GenerateTimeInInputRegion(output, this->GetInput());
61  GenerateTimeInInputRegion(output, m_BoundingObject.GetPointer());
62  }
63 
65  {
66  mitk::Image::Pointer output = this->GetOutput();
67  if ((output->IsInitialized()) && (output->GetPipelineMTime() <= m_TimeOfHeaderInitialization.GetMTime()))
68  return;
69 
70  mitk::Image::Pointer input = this->GetInput();
71 
72  if (input.IsNull())
73  {
74  mitkThrow() << "Input is not a mitk::Image";
75  }
76  itkDebugMacro(<< "GenerateOutputInformation()");
77  unsigned int dimension = input->GetDimension();
78 
79  if (dimension < 3)
80  {
81  mitkThrow() << "ImageCropper cannot handle 1D or 2D Objects.";
82  }
83 
84  if ((m_BoundingObject.IsNull()) || (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
85  return;
86 
87  mitk::BaseGeometry *boGeometry = m_BoundingObject->GetGeometry();
88  mitk::BaseGeometry *inputImageGeometry = input->GetSlicedGeometry();
89  // calculate bounding box of bounding-object relative to the geometry
90  // of the input image. The result is in pixel coordinates of the input
91  // image (because the m_IndexToWorldTransform includes the spacing).
92  mitk::BoundingBox::Pointer boBoxRelativeToImage =
93  boGeometry->CalculateBoundingBoxRelativeToTransform(inputImageGeometry->GetIndexToWorldTransform());
94 
95  // PART I: initialize input requested region. We do this already here (and not
96  // later when GenerateInputRequestedRegion() is called), because we
97  // also need the information to setup the output.
98 
99  // pre-initialize input-requested-region to largest-possible-region
100  // and correct time-region; spatial part will be cropped by
101  // bounding-box of bounding-object below
102  m_InputRequestedRegion = input->GetLargestPossibleRegion();
103 
104  // build region out of bounding-box of bounding-object
105  mitk::SlicedData::IndexType index = m_InputRequestedRegion.GetIndex(); // init times and channels
106  mitk::BoundingBox::PointType min = boBoxRelativeToImage->GetMinimum();
107  index[0] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[0]));
108  index[1] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[1]));
109  index[2] = (mitk::SlicedData::IndexType::IndexValueType)(std::ceil(min[2]));
110 
111  mitk::SlicedData::SizeType size = m_InputRequestedRegion.GetSize(); // init times and channels
112  mitk::BoundingBox::PointType max = boBoxRelativeToImage->GetMaximum();
113  size[0] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[0]) - index[0]);
114  size[1] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[1]) - index[1]);
115  size[2] = (mitk::SlicedData::SizeType::SizeValueType)(std::ceil(max[2]) - index[2]);
116 
117  mitk::SlicedData::RegionType boRegion(index, size);
118 
119  if (m_UseWholeInputRegion == false)
120  {
121  // crop input-requested-region with region of bounding-object
122  if (m_InputRequestedRegion.Crop(boRegion) == false)
123  {
124  // crop not possible => do nothing: set time size to 0.
125  size.Fill(0);
126  m_InputRequestedRegion.SetSize(size);
127  boRegion.SetSize(size);
128  m_BoundingObject->SetRequestedRegion(&boRegion);
129  mitkThrow() << "No overlap of the image and the cropping object.";
130  }
131  }
132 
133  // set input-requested-region, because we access it later in
134  // GenerateInputRequestedRegion (there we just set the time)
135  input->SetRequestedRegion(&m_InputRequestedRegion);
136 
137  // PART II: initialize output image
138 
139  auto dimensions = new unsigned int[dimension];
140  itk2vtk(m_InputRequestedRegion.GetSize(), dimensions);
141  if (dimension > 3)
142  memcpy(dimensions + 3, input->GetDimensions() + 3, (dimension - 3) * sizeof(unsigned int));
143  output->Initialize(mitk::PixelType(GetOutputPixelType()), dimension, dimensions);
144  delete[] dimensions;
145 
146  // now we have everything to initialize the transform of the output
147  mitk::SlicedGeometry3D *slicedGeometry = output->GetSlicedGeometry();
148 
149  // set the transform: use the transform of the input;
150  // the origin will be replaced afterwards
151  AffineTransform3D::Pointer indexToWorldTransform = AffineTransform3D::New();
152  indexToWorldTransform->SetParameters(input->GetSlicedGeometry()->GetIndexToWorldTransform()->GetParameters());
153  slicedGeometry->SetIndexToWorldTransform(indexToWorldTransform);
154 
155  // Position the output Image to match the corresponding region of the input image
156  const mitk::SlicedData::IndexType &start = m_InputRequestedRegion.GetIndex();
157  mitk::Point3D origin;
158  vtk2itk(start, origin);
159  inputImageGeometry->IndexToWorld(origin, origin);
160  slicedGeometry->SetOrigin(origin);
161 
162  m_TimeOfHeaderInitialization.Modified();
163  }
164 
165  void BoundingObjectCutter::ComputeData(mitk::Image *input3D, int boTimeStep)
166  {
167  if (input3D != nullptr && input3D->GetPixelType().GetNumberOfComponents() == 1)
168  {
169  AccessFixedDimensionByItk_2(input3D, CutImage, 3, this, boTimeStep);
170  }
171  else
172  {
173  AccessVectorFixedDimensionByItk_n(input3D, CutImage, 3, (this, boTimeStep));
174  }
175  }
176 
178  {
179  mitk::Image::ConstPointer input = this->GetInput();
180  mitk::Image::Pointer output = this->GetOutput();
181 
182  if (input.IsNull())
183  return;
184 
185  if ((output->IsInitialized() == false) || (m_BoundingObject.IsNull()) ||
186  (m_BoundingObject->GetTimeGeometry()->CountTimeSteps() == 0))
187  return;
188 
189  m_InputTimeSelector->SetInput(input);
190  m_OutputTimeSelector->SetInput(this->GetOutput());
191 
192  mitk::Surface::RegionType outputRegion = output->GetRequestedRegion();
193  const mitk::TimeGeometry *outputTimeGeometry = output->GetTimeGeometry();
194  const mitk::TimeGeometry *inputTimeGeometry = input->GetTimeGeometry();
195  const mitk::TimeGeometry *boundingObjectTimeGeometry = m_BoundingObject->GetTimeGeometry();
196  TimePointType timeInMS;
197 
198  int timestep = 0;
199  int tstart = outputRegion.GetIndex(3);
200  int tmax = tstart + outputRegion.GetSize(3);
201 
202  int t;
203  for (t = tstart; t < tmax; ++t)
204  {
205  timeInMS = outputTimeGeometry->TimeStepToTimePoint(t);
206  timestep = inputTimeGeometry->TimePointToTimeStep(timeInMS);
207 
208  m_InputTimeSelector->SetTimeNr(timestep);
209  m_InputTimeSelector->UpdateLargestPossibleRegion();
210  m_OutputTimeSelector->SetTimeNr(t);
211  m_OutputTimeSelector->UpdateLargestPossibleRegion();
212 
213  timestep = boundingObjectTimeGeometry->TimePointToTimeStep(timeInMS);
214 
215  ComputeData(m_InputTimeSelector->GetOutput(), timestep);
216  }
217 
218  m_InputTimeSelector->SetInput(nullptr);
219  m_OutputTimeSelector->SetInput(nullptr);
220 
221  m_TimeOfHeaderInitialization.Modified();
222  }
223 
224 } // of namespace mitk
mitk::BoundingObject::Pointer m_BoundingObject
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
void SetBoundingObject(const mitk::BoundingObject *boundingObject)
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
DataCollection - Class to facilitate loading/accessing structured data.
virtual const PixelType GetOutputPixelType()
friend void CutImage(itk::Image< TPixel, VImageDimension > *itkImage, mitk::BoundingObjectCutter *cutter, int boTimeStep)
itk::Size< RegionDimension > SizeType
superclass of all bounding objects (cylinder, cuboid,...)
virtual void ComputeData(mitk::Image *input3D, int boTimeStep)
#define AccessFixedDimensionByItk_2(mitkImage, itkImageTypeFunction, dimension, arg1, arg2)
itk::ImageRegion< RegionDimension > RegionType
virtual TimeStepType TimePointToTimeStep(TimePointType timePoint) const =0
Converts a time point to the corresponding time step.
#define mitkThrow()
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
Image class for storing images.
Definition: mitkImage.h:72
virtual TimePointType TimeStepToTimePoint(TimeStepType timeStep) const =0
Converts a time step to a time point.
const mitk::BoundingObject * GetBoundingObject() const
void vtk2itk(const Tin &in, Tout &out)
mitk::ScalarType TimePointType
mitk::SlicedData::RegionType m_InputRequestedRegion
mitk::ImageTimeSelector::Pointer m_InputTimeSelector
static T max(T x, T y)
Definition: svm.cpp:56
Describes the geometry of a data object consisting of slices.
void GenerateTimeInInputRegion(const mitk::TimeGeometry *outputTimeGeometry, const TOutputRegion &outputRegion, const mitk::TimeGeometry *inputTimeGeometry, TInputRegion &inputRegion)
static T min(T x, T y)
Definition: svm.cpp:53
void itk2vtk(const Tin &in, Tout &out)
InputImageType * GetInput(void)
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
mitk::BoundingBox::Pointer CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D *transform) const
Calculates a bounding-box around the geometry relative to a coordinate system defined by a transform...
OutputType * GetOutput()
Get the output data of this image source object.
mitk::ImageTimeSelector::Pointer m_OutputTimeSelector
itk::ImageRegion< 5 > RegionType
Definition: mitkSurface.h:31
BaseGeometry Describes the geometry of a data object.
static Pointer New()
Class for defining the data type of pixels.
Definition: mitkPixelType.h:51
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
#define AccessVectorFixedDimensionByItk_n(mitkImage, itkImageTypeFunction, dimension, va_tuple)
Access a vector mitk-image with known dimension by a ITK vector image with one or more parameters...