Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkLabelSetImageToSurfaceFilter.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 
15 #include <mitkImageAccessByItk.h>
16 #include <mitkImageCast.h>
17 
18 // itk
19 #include <itkAntiAliasBinaryImageFilter.h>
20 #include <itkAutoCropLabelMapFilter.h>
21 #include <itkBinaryThresholdImageFilter.h>
22 #include <itkLabelImageToLabelMapFilter.h>
23 #include <itkLabelMap.h>
24 #include <itkLabelMapToLabelImageFilter.h>
25 #include <itkLabelObject.h>
26 #include <itkNumericTraits.h>
27 #include <itkSmoothingRecursiveGaussianImageFilter.h>
28 
29 // vtk
30 #include <vtkCleanPolyData.h>
31 #include <vtkImageChangeInformation.h>
32 #include <vtkImageData.h>
33 #include <vtkLinearTransform.h>
34 #include <vtkMarchingCubes.h>
35 #include <vtkSmartPointer.h>
36 
38  : m_GenerateAllLabels(false), m_RequestedLabel(1), m_BackgroundLabel(0), m_UseSmoothing(0), m_Sigma(0.1)
39 {
40 }
41 
43 {
44 }
45 
47 {
48  // Process object is not const-correct so the const_cast is required here
49  this->ProcessObject::SetNthInput(0, const_cast<mitk::Image *>(image));
50 }
51 /*
52 void mitk::LabelSetImageToSurfaceFilter::SetObserver(mitk::ProcessObserver::Pointer observer)
53 {
54  m_Observer = observer;
55 }
56 */
58 {
59  if (this->GetNumberOfInputs() < 1)
60  {
61  return nullptr;
62  }
63 
64  return static_cast<const mitk::Image *>(this->ProcessObject::GetInput(0));
65 }
66 
68 {
69  itkDebugMacro(<< "GenerateOutputInformation()");
70 }
71 
73 {
74  Image::ConstPointer inputImage = this->GetInput();
75  if (inputImage.IsNull())
76  return;
77 
78  mitk::Surface *outputSurface = this->GetOutput();
79  if (!outputSurface)
80  return;
81 
82  AccessFixedDimensionByItk_1(inputImage, InternalProcessing, 3, outputSurface);
83 }
84 
85 template <typename TPixel, unsigned int VDimension>
86 void mitk::LabelSetImageToSurfaceFilter::InternalProcessing(const itk::Image<TPixel, VDimension> *input,
87  mitk::Surface * /*surface*/)
88 {
89  typedef itk::Image<TPixel, VDimension> ImageType;
90 
91  typedef itk::BinaryThresholdImageFilter<ImageType, ImageType> BinaryThresholdFilterType;
92  typedef itk::LabelObject<TPixel, VDimension> LabelObjectType;
93  typedef itk::LabelMap<LabelObjectType> LabelMapType;
94  typedef itk::LabelImageToLabelMapFilter<ImageType, LabelMapType> Image2LabelMapType;
95  typedef itk::AutoCropLabelMapFilter<LabelMapType> AutoCropType;
96  typedef itk::LabelMapToLabelImageFilter<LabelMapType, ImageType> LabelMap2ImageType;
97 
98  typedef itk::Image<float, VDimension> RealImageType;
99 
100  typedef itk::AntiAliasBinaryImageFilter<ImageType, RealImageType> AntiAliasFilterType;
101  typedef itk::SmoothingRecursiveGaussianImageFilter<RealImageType, RealImageType> GaussianFilterType;
102 
103  typename BinaryThresholdFilterType::Pointer thresholdFilter = BinaryThresholdFilterType::New();
104  thresholdFilter->SetInput(input);
105  thresholdFilter->SetLowerThreshold(m_RequestedLabel);
106  thresholdFilter->SetUpperThreshold(m_RequestedLabel);
107  thresholdFilter->SetOutsideValue(0);
108  thresholdFilter->SetInsideValue(1);
109  // thresholdFilter->ReleaseDataFlagOn();
110  thresholdFilter->Update();
111 
112  typename Image2LabelMapType::Pointer image2label = Image2LabelMapType::New();
113  image2label->SetInput(thresholdFilter->GetOutput());
114 
115  typename AutoCropType::SizeType border;
116  border[0] = 3;
117  border[1] = 3;
118  border[2] = 3;
119 
120  typename AutoCropType::Pointer autoCropFilter = AutoCropType::New();
121  autoCropFilter->SetInput(image2label->GetOutput());
122  autoCropFilter->SetCropBorder(border);
123  autoCropFilter->InPlaceOn();
124 
125  typename LabelMap2ImageType::Pointer label2image = LabelMap2ImageType::New();
126  label2image->SetInput(autoCropFilter->GetOutput());
127 
128  label2image->Update();
129 
130  typename AntiAliasFilterType::Pointer antiAliasFilter = AntiAliasFilterType::New();
131  antiAliasFilter->SetInput(label2image->GetOutput());
132  antiAliasFilter->SetMaximumRMSError(0.001);
133  antiAliasFilter->SetNumberOfLayers(3);
134  antiAliasFilter->SetUseImageSpacing(false);
135  antiAliasFilter->SetNumberOfIterations(40);
136 
137  antiAliasFilter->Update();
138 
139  typename RealImageType::Pointer result;
140 
141  if (m_UseSmoothing)
142  {
143  typename GaussianFilterType::Pointer gaussianFilter = GaussianFilterType::New();
144  gaussianFilter->SetSigma(m_Sigma);
145  gaussianFilter->SetInput(antiAliasFilter->GetOutput());
146  gaussianFilter->Update();
147  result = gaussianFilter->GetOutput();
148  }
149  else
150  {
151  result = antiAliasFilter->GetOutput();
152  }
153 
154  result->DisconnectPipeline();
155 
156  typename ImageType::RegionType cropRegion;
157  cropRegion = autoCropFilter->GetOutput()->GetLargestPossibleRegion();
158 
159  const typename ImageType::IndexType &cropIndex = cropRegion.GetIndex();
160 
163 
164  mitk::BaseGeometry *newGeometry = m_ResultImage->GetSlicedGeometry();
165  mitk::Point3D origin;
166  vtk2itk(cropIndex, origin);
167  this->GetInput()->GetGeometry()->IndexToWorld(origin, origin);
168  newGeometry->SetOrigin(origin);
169 
170  auto *vtkimage = m_ResultImage->GetVtkImageData(0);
171 
172  vtkSmartPointer<vtkImageChangeInformation> indexCoordinatesImageFilter =
173  vtkSmartPointer<vtkImageChangeInformation>::New();
174  indexCoordinatesImageFilter->SetInputData(vtkimage);
175  indexCoordinatesImageFilter->SetOutputOrigin(0.0, 0.0, 0.0);
176 
177  vtkSmartPointer<vtkMarchingCubes> marching = vtkSmartPointer<vtkMarchingCubes>::New();
178  marching->ComputeScalarsOff();
179  marching->ComputeNormalsOn();
180  marching->ComputeGradientsOn();
181  marching->SetInputConnection(indexCoordinatesImageFilter->GetOutputPort());
182  marching->SetValue(0, 0.0);
183 
184  marching->Update();
185 
186  vtkPolyData *polydata = marching->GetOutput();
187 
188  if ((!polydata) || (!polydata->GetNumberOfPoints()))
189  throw itk::ExceptionObject(__FILE__, __LINE__, "marching cubes has failed.");
190 
191  mitk::Vector3D spacing = newGeometry->GetSpacing();
192 
193  vtkPoints *points = polydata->GetPoints();
194  vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
195  newGeometry->GetVtkTransform()->GetMatrix(vtkmatrix);
196  double(*matrix)[4] = vtkmatrix->Element;
197 
198  for (int i = 0; i < 3; ++i)
199  for (int j = 0; j < 3; ++j)
200  matrix[i][j] /= spacing[j];
201 
202  unsigned int n = points->GetNumberOfPoints();
203  double point[3];
204 
205  for (unsigned int i = 0; i < n; i++)
206  {
207  points->GetPoint(i, point);
208  mitkVtkLinearTransformPoint(matrix, point, point);
209  points->SetPoint(i, point);
210  }
211  vtkmatrix->Delete();
212 
213  vtkSmartPointer<vtkCleanPolyData> cleanPolyDataFilter = vtkSmartPointer<vtkCleanPolyData>::New();
214  cleanPolyDataFilter->SetInputData(polydata);
215  cleanPolyDataFilter->PieceInvariantOff();
216  cleanPolyDataFilter->ConvertLinesToPointsOff();
217  cleanPolyDataFilter->ConvertPolysToLinesOff();
218  cleanPolyDataFilter->ConvertStripsToPolysOff();
219  cleanPolyDataFilter->PointMergingOn();
220  cleanPolyDataFilter->Update();
221 
222  mitk::Surface::Pointer output = this->GetOutput(0);
223  output->SetVtkPolyData(cleanPolyDataFilter->GetOutput(), 0);
224 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
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)...
itk::Image< unsigned char, 3 > ImageType
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
void InternalProcessing(const itk::Image< TPixel, VImageDimension > *input, mitk::Surface *surface)
OutputType * GetOutput()
std::map< LabelType, unsigned long > LabelMapType
void mitkVtkLinearTransformPoint(T1 matrix[4][4], T2 in[3], T3 out[3])
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
void vtk2itk(const Tin &in, Tout &out)
mitk::Image::Pointer image
static Pointer New()
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
Definition: mitkImageCast.h:74
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
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
virtual void SetInput(const mitk::Image *image)
BaseGeometry Describes the geometry of a data object.