Medical Imaging Interaction Toolkit  2018.4.99-1bab67a2
Medical Imaging Interaction Toolkit
mitkSurfaceToImageFilter.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 "mitkImageWriteAccessor.h"
15 #include "mitkTimeHelper.h"
16 #include <mitkImageReadAccessor.h>
17 
18 #include <vtkImageData.h>
19 #include <vtkImageStencil.h>
20 #include <vtkPointData.h>
21 #include <vtkPolyData.h>
22 #include <vtkPolyDataNormals.h>
23 #include <vtkPolyDataToImageStencil.h>
24 #include <vtkSmartPointer.h>
25 #include <vtkTransform.h>
26 #include <vtkTransformPolyDataFilter.h>
27 
29  : m_MakeOutputBinary(false), m_UShortBinaryPixelType(false), m_BackgroundValue(-10000), m_Tolerance(0.0)
30 {
31 }
32 
34 {
35 }
36 
38 {
39  mitk::Image *output = this->GetOutput();
40  if ((output->IsInitialized() == false))
41  return;
42 
43  GenerateTimeInInputRegion(output, const_cast<mitk::Image *>(this->GetImage()));
44 }
45 
47 {
48  mitk::Image *inputImage = (mitk::Image *)this->GetImage();
49  mitk::Image::Pointer output = this->GetOutput();
50 
51  itkDebugMacro(<< "GenerateOutputInformation()");
52 
53  if ((inputImage == nullptr) || (inputImage->IsInitialized() == false) || (inputImage->GetTimeGeometry() == nullptr))
54  return;
55 
57  {
59  {
60  output->Initialize(mitk::MakeScalarPixelType<unsigned short>(), *inputImage->GetTimeGeometry());
61  }
62  else
63  {
64  output->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *inputImage->GetTimeGeometry());
65  }
66  }
67  else
68  {
69  output->Initialize(inputImage->GetPixelType(), *inputImage->GetTimeGeometry());
70  }
71 
72  output->SetPropertyList(inputImage->GetPropertyList()->Clone());
73 }
74 
76 {
77  mitk::Image::ConstPointer inputImage = this->GetImage();
78  mitk::Image::Pointer output = this->GetOutput();
79 
80  if (inputImage.IsNull())
81  return;
82 
83  if (output->IsInitialized() == false)
84  return;
85 
86  mitk::Image::RegionType outputRegion = output->GetRequestedRegion();
87 
88  int tstart = outputRegion.GetIndex(3);
89  int tmax = tstart + outputRegion.GetSize(3);
90 
91  if (tmax > 0)
92  {
93  int t;
94  for (t = tstart; t < tmax; ++t)
95  {
96  Stencil3DImage(t);
97  }
98  }
99  else
100  {
101  Stencil3DImage(0);
102  }
103 }
104 
106 {
107  mitk::Image::Pointer output = this->GetOutput();
108  mitk::Image::Pointer binaryImage = mitk::Image::New();
109 
110  unsigned int size = sizeof(unsigned char);
111  if (m_MakeOutputBinary)
112  {
114  {
115  binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned short>(), *this->GetImage()->GetTimeGeometry(), 1, 1);
116  size = sizeof(unsigned short);
117  }
118  else
119  {
120  binaryImage->Initialize(mitk::MakeScalarPixelType<unsigned char>(), *this->GetImage()->GetTimeGeometry(), 1, 1);
121  }
122  }
123  else
124  {
125  binaryImage->Initialize(this->GetImage()->GetPixelType(), *this->GetImage()->GetTimeGeometry(), 1, 1);
126  size = this->GetImage()->GetPixelType().GetSize();
127  }
128 
129  for (unsigned int i = 0; i < binaryImage->GetDimension(); ++i)
130  {
131  size *= binaryImage->GetDimension(i);
132  }
133 
134  mitk::ImageWriteAccessor accessor(binaryImage);
135  memset(accessor.GetData(), 1, size);
136 
137  const mitk::TimeGeometry *surfaceTimeGeometry = GetInput()->GetTimeGeometry();
138  const mitk::TimeGeometry *imageTimeGeometry = GetImage()->GetTimeGeometry();
139 
140  // Convert time step from image time-frame to surface time-frame
141  mitk::TimePointType matchingTimePoint = imageTimeGeometry->TimeStepToTimePoint(time);
142  mitk::TimeStepType surfaceTimeStep = surfaceTimeGeometry->TimePointToTimeStep(matchingTimePoint);
143 
144  vtkPolyData *polydata = ((mitk::Surface *)GetInput())->GetVtkPolyData(surfaceTimeStep);
145  if (polydata)
146  {
147  vtkSmartPointer<vtkTransformPolyDataFilter> move = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
148  move->SetInputData(polydata);
149  move->ReleaseDataFlagOn();
150 
151  vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
152  BaseGeometry *geometry = surfaceTimeGeometry->GetGeometryForTimeStep(surfaceTimeStep);
153  if (!geometry)
154  {
155  geometry = GetInput()->GetGeometry();
156  }
157  transform->PostMultiply();
158  transform->Concatenate(geometry->GetVtkTransform()->GetMatrix());
159  // take image geometry into account. vtk-Image information will be changed to unit spacing and zero origin below.
160  BaseGeometry *imageGeometry = imageTimeGeometry->GetGeometryForTimeStep(time);
161  transform->Concatenate(imageGeometry->GetVtkTransform()->GetLinearInverse());
162  move->SetTransform(transform);
163 
164  vtkSmartPointer<vtkPolyDataNormals> normalsFilter = vtkSmartPointer<vtkPolyDataNormals>::New();
165  normalsFilter->SetFeatureAngle(50);
166  normalsFilter->SetConsistency(1);
167  normalsFilter->SetSplitting(1);
168  normalsFilter->SetFlipNormals(0);
169  normalsFilter->ReleaseDataFlagOn();
170 
171  normalsFilter->SetInputConnection(move->GetOutputPort());
172 
173  vtkSmartPointer<vtkPolyDataToImageStencil> surfaceConverter = vtkSmartPointer<vtkPolyDataToImageStencil>::New();
174  surfaceConverter->SetTolerance(m_Tolerance);
175  surfaceConverter->ReleaseDataFlagOn();
176 
177  surfaceConverter->SetInputConnection(normalsFilter->GetOutputPort());
178 
179  vtkImageData *image = m_MakeOutputBinary ? binaryImage->GetVtkImageData() :
180  const_cast<mitk::Image *>(this->GetImage())->GetVtkImageData(time);
181 
182  // fill the image with foreground voxels:
183  unsigned char inval = 1;
184  vtkIdType count = image->GetNumberOfPoints();
185  for (vtkIdType i = 0; i < count; ++i)
186  {
187  image->GetPointData()->GetScalars()->SetTuple1(i, inval);
188  }
189 
190  // Create stencil and use numerical minimum of pixel type as background value
191  vtkSmartPointer<vtkImageStencil> stencil = vtkSmartPointer<vtkImageStencil>::New();
192  stencil->SetInputData(image);
193  stencil->ReverseStencilOff();
194  stencil->ReleaseDataFlagOn();
195  stencil->SetStencilConnection(surfaceConverter->GetOutputPort());
196 
197  stencil->SetBackgroundValue(m_MakeOutputBinary ? 0 : m_BackgroundValue);
198  stencil->Update();
199 
200  output->SetVolume(stencil->GetOutput()->GetScalarPointer(), time);
201  MITK_INFO << "stencil ref count: " << stencil->GetReferenceCount() << std::endl;
202  }
203  else
204  {
205  memset(accessor.GetData(), 0, size);
206  output->SetVolume(accessor.GetData(), time);
207  }
208 }
209 
211 {
212  if (this->GetNumberOfInputs() < 1)
213  {
214  return nullptr;
215  }
216 
217  return static_cast<const mitk::Surface *>(this->ProcessObject::GetInput(0));
218 }
219 
221 {
222  // Process object is not const-correct so the const_cast is required here
223  this->ProcessObject::SetNthInput(0, const_cast<mitk::Surface *>(input));
224 }
225 
227 {
228  this->ProcessObject::SetNthInput(1, const_cast<mitk::Image *>(source));
229 }
230 
232 {
233  return static_cast<const mitk::Image *>(this->ProcessObject::GetInput(1));
234 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
#define MITK_INFO
Definition: mitkLogMacros.h:18
virtual vtkImageData * GetVtkImageData()
const mitk::Surface * GetInput(void)
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:101
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
const mitk::Image * GetImage(void)
void * GetData()
Gives full data access.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
void SetImage(const mitk::Image *source)
itk::ImageRegion< RegionDimension > RegionType
Image class for storing images.
Definition: mitkImage.h:72
virtual TimePointType TimeStepToTimePoint(TimeStepType timeStep) const =0
Converts a time step to a time point.
mitk::ScalarType TimePointType
std::vcl_size_t TimeStepType
mitk::Image::Pointer image
static Pointer New()
void GenerateTimeInInputRegion(const mitk::TimeGeometry *outputTimeGeometry, const TOutputRegion &outputRegion, const mitk::TimeGeometry *inputTimeGeometry, TInputRegion &inputRegion)
vcl_size_t GetSize() const
Get size of the PixelType in bytes.
mitk::PropertyList::Pointer GetPropertyList() const
Get the data&#39;s property list.
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
OutputType * GetOutput()
Get the output data of this image source object.
ImageWriteAccessor class to get locked write-access for a particular image part.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:138
BaseGeometry Describes the geometry of a data object.
virtual void SetInput(const mitk::Surface *surface)