Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkImageToSurfaceFilter.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 
17 #include "mitkException.h"
19 #include <vtkDecimatePro.h>
20 #include <vtkImageChangeInformation.h>
21 #include <vtkImageData.h>
22 #include <vtkLinearTransform.h>
23 #include <vtkMath.h>
24 #include <vtkMatrix4x4.h>
25 #include <vtkQuadricDecimation.h>
26 
27 #include <vtkCleanPolyData.h>
28 #include <vtkPolyDataNormals.h>
29 #include <vtkSmartPointer.h>
30 
31 #include "mitkProgressBar.h"
32 
34  : m_Smooth(false),
35  m_Decimate(NoDecimation),
36  m_Threshold(1.0),
37  m_TargetReduction(0.95f),
38  m_SmoothIteration(50),
39  m_SmoothRelaxation(0.1)
40 {
41 }
42 
44 {
45 }
46 
48  vtkImageData *vtkimage,
49  mitk::Surface *surface,
50  const ScalarType threshold)
51 {
52  vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
53  indexCoordinatesImageFilter->SetInputData(vtkimage);
54  indexCoordinatesImageFilter->SetOutputOrigin(0.0, 0.0, 0.0);
55 
56  // MarchingCube -->create Surface
57  vtkSmartPointer<vtkMarchingCubes> skinExtractor = vtkSmartPointer<vtkMarchingCubes>::New();
58  skinExtractor->ComputeScalarsOff();
59  skinExtractor->SetInputConnection(indexCoordinatesImageFilter->GetOutputPort()); // RC++
60  indexCoordinatesImageFilter->Delete();
61  skinExtractor->SetValue(0, threshold);
62 
63  vtkPolyData *polydata;
64  skinExtractor->Update();
65  polydata = skinExtractor->GetOutput();
66  polydata->Register(nullptr); // RC++
67 
68  if (m_Smooth)
69  {
70  vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
71  // read poly1 (poly1 can be the original polygon, or the decimated polygon)
72  smoother->SetInputConnection(skinExtractor->GetOutputPort()); // RC++
73  smoother->SetNumberOfIterations(m_SmoothIteration);
74  smoother->SetRelaxationFactor(m_SmoothRelaxation);
75  smoother->SetFeatureAngle(60);
76  smoother->FeatureEdgeSmoothingOff();
77  smoother->BoundarySmoothingOff();
78  smoother->SetConvergence(0);
79  smoother->Update();
80 
81  polydata->Delete(); // RC--
82  polydata = smoother->GetOutput();
83  polydata->Register(nullptr); // RC++
84  smoother->Delete();
85  }
87 
88  // decimate = to reduce number of polygons
89  if (m_Decimate == DecimatePro)
90  {
91  vtkDecimatePro *decimate = vtkDecimatePro::New();
92  decimate->SplittingOff();
93  decimate->SetErrorIsAbsolute(5);
94  decimate->SetFeatureAngle(30);
95  decimate->PreserveTopologyOn();
96  decimate->BoundaryVertexDeletionOff();
97  decimate->SetDegree(10); // std-value is 25!
98 
99  decimate->SetInputData(polydata); // RC++
100  decimate->SetTargetReduction(m_TargetReduction);
101  decimate->SetMaximumError(0.002);
102  decimate->Update();
103 
104  polydata->Delete(); // RC--
105  polydata = decimate->GetOutput();
106  polydata->Register(nullptr); // RC++
107  decimate->Delete();
108  }
109  else if (m_Decimate == QuadricDecimation)
110  {
111  vtkQuadricDecimation *decimate = vtkQuadricDecimation::New();
112  decimate->SetTargetReduction(m_TargetReduction);
113 
114  decimate->SetInputData(polydata);
115  decimate->Update();
116  polydata->Delete();
117  polydata = decimate->GetOutput();
118  polydata->Register(nullptr);
119  decimate->Delete();
120  }
121 
123 
124  if (polydata->GetNumberOfPoints() > 0)
125  {
126  mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();
127 
128  vtkPoints *points = polydata->GetPoints();
129  vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
130  GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
131  double(*matrix)[4] = vtkmatrix->Element;
132 
133  unsigned int i, j;
134  for (i = 0; i < 3; ++i)
135  for (j = 0; j < 3; ++j)
136  matrix[i][j] /= spacing[j];
137 
138  unsigned int n = points->GetNumberOfPoints();
139  double point[3];
140 
141  for (i = 0; i < n; i++)
142  {
143  points->GetPoint(i, point);
144  mitkVtkLinearTransformPoint(matrix, point, point);
145  points->SetPoint(i, point);
146  }
147  vtkmatrix->Delete();
148  }
150 
151  // determine point_data normals for the poly data points.
152  vtkSmartPointer<vtkPolyDataNormals> normalsGenerator = vtkSmartPointer<vtkPolyDataNormals>::New();
153  normalsGenerator->SetInputData(polydata);
154  normalsGenerator->FlipNormalsOn();
155 
156  vtkSmartPointer<vtkCleanPolyData> cleanPolyDataFilter = vtkSmartPointer<vtkCleanPolyData>::New();
157  cleanPolyDataFilter->SetInputConnection(normalsGenerator->GetOutputPort());
158  cleanPolyDataFilter->PieceInvariantOff();
159  cleanPolyDataFilter->ConvertLinesToPointsOff();
160  cleanPolyDataFilter->ConvertPolysToLinesOff();
161  cleanPolyDataFilter->ConvertStripsToPolysOff();
162  cleanPolyDataFilter->PointMergingOn();
163  cleanPolyDataFilter->Update();
164 
165  surface->SetVtkPolyData(cleanPolyDataFilter->GetOutput(), time);
166  polydata->UnRegister(nullptr);
167 }
168 
170 {
171  mitk::Surface *surface = this->GetOutput();
172  mitk::Image *image = (mitk::Image *)GetInput();
173  if (image == nullptr || !image->IsInitialized())
174  mitkThrow() << "No input image set, please set an valid input image!";
175 
176  mitk::Image::RegionType outputRegion = image->GetRequestedRegion();
177 
178  int tstart = outputRegion.GetIndex(3);
179  int tmax = tstart + outputRegion.GetSize(3); // GetSize()==1 - will aber 0 haben, wenn nicht zeitaufgeloest
180 
181  if ((tmax - tstart) > 0)
182  {
183  ProgressBar::GetInstance()->AddStepsToDo(4 * (tmax - tstart));
184  }
185 
186  int t;
187  for (t = tstart; t < tmax; ++t)
188  {
189  vtkImageData *vtkimagedata = image->GetVtkImageData(t);
190  CreateSurface(t, vtkimagedata, surface, m_Threshold);
192  }
193 }
194 
196 {
197  m_SmoothIteration = smoothIteration;
198 }
199 
201 {
202  m_SmoothRelaxation = smoothRelaxation;
203 }
204 
206 {
207  // Process object is not const-correct so the const_cast is required here
208  this->ProcessObject::SetNthInput(0, const_cast<mitk::Image *>(image));
209 }
210 
212 {
213  if (this->GetNumberOfInputs() < 1)
214  {
215  return nullptr;
216  }
217 
218  return static_cast<const mitk::Image *>(this->ProcessObject::GetInput(0));
219 }
220 
222 {
223  mitk::Image::ConstPointer inputImage = (mitk::Image *)this->GetInput();
224 
225  // mitk::Image *inputImage = (mitk::Image*)this->GetImage();
226  mitk::Surface::Pointer output = this->GetOutput();
227 
228  itkDebugMacro(<< "GenerateOutputInformation()");
229 
230  if (inputImage.IsNull())
231  return;
232 
233  // Set Data
234 }
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:32
virtual const RegionType & GetRequestedRegion() const
double ScalarType
const mitk::Image * GetInput(void)
virtual void SetInput(const mitk::Image *image)
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
Definition: mitkImage.cpp:221
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
virtual void GenerateData() override
void SetSmoothRelaxation(float smoothRelaxation)
virtual void GenerateOutputInformation() override
itk::ImageRegion< RegionDimension > RegionType
#define mitkThrow()
Image class for storing images.
Definition: mitkImage.h:76
void CreateSurface(int time, vtkImageData *vtkimage, mitk::Surface *surface, const ScalarType threshold)
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
void AddStepsToDo(unsigned int steps)
Adds steps to totalSteps.
virtual bool IsInitialized() const
Check whether the data has been initialized, i.e., at least the Geometry and other header data has be...
void SetSmoothIteration(int smoothIteration)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.