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