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