19 #include <vtkDecimatePro.h>
20 #include <vtkImageChangeInformation.h>
21 #include <vtkImageGaussianSmooth.h>
22 #include <vtkImageMarchingCubes.h>
23 #include <vtkImageThreshold.h>
24 #include <vtkLinearTransform.h>
25 #include <vtkMatrix4x4.h>
26 #include <vtkPolyData.h>
27 #include <vtkSmoothPolyDataFilter.h>
29 #include <itkImageRegionIterator.h>
30 #include <itkNumericTraits.h>
35 : m_GaussianStandardDeviation(1.5), m_GenerateAllLabels(true), m_Label(1), m_BackgroundLabel(0)
45 Superclass::GenerateOutputInformation();
49 m_AvailableLabels = this->GetAvailableLabels();
50 m_IdxToLabels.clear();
57 if (!m_GenerateAllLabels)
60 LabelMapType::iterator it;
61 it = m_AvailableLabels.find(m_Label);
62 if (it != m_AvailableLabels.end())
63 tmp[m_Label] = it->second;
67 it = m_AvailableLabels.find(m_BackgroundLabel);
68 if (it != m_AvailableLabels.end())
69 tmp[m_BackgroundLabel] = it->second;
71 tmp[m_BackgroundLabel] = 0;
73 m_AvailableLabels = tmp;
83 unsigned int numberOfOutputs = 0;
84 if (m_AvailableLabels.find(m_BackgroundLabel) == m_AvailableLabels.end())
85 numberOfOutputs = m_AvailableLabels.size();
87 numberOfOutputs = m_AvailableLabels.size() - 1;
88 if (numberOfOutputs == 0)
90 itkWarningMacro(
"Number of outputs == 0");
98 unsigned int numberOfTimeSteps = image->
GetTimeGeometry()->CountTimeSteps();
104 this->SetNumberOfIndexedOutputs(numberOfOutputs);
105 this->SetNumberOfRequiredOutputs(numberOfOutputs);
106 for (
unsigned int i = 0; i < numberOfOutputs; ++i)
108 if (!this->GetOutput(i))
111 assert(output.IsNotNull());
112 output->Expand(numberOfTimeSteps);
113 this->SetNthOutput(i, output.GetPointer());
121 if (image ==
nullptr)
123 itkWarningMacro(
"Image is NULL");
129 m_IdxToLabels.clear();
131 if (this->GetNumberOfOutputs() == 0)
137 unsigned int currentOutputIndex = 0;
138 for (
auto it = m_AvailableLabels.begin(); it != m_AvailableLabels.end(); ++it)
140 if (it->first == m_BackgroundLabel)
142 if ((it->second == 0) && m_GenerateAllLabels)
145 assert(currentOutputIndex < this->GetNumberOfOutputs());
147 assert(surface.IsNotNull());
149 int tstart = outputRegion.GetIndex(3);
150 int tmax = tstart + outputRegion.GetSize(3);
152 for (t = tstart; t < tmax; ++t)
155 CreateSurface(t, vtkimagedata, surface.GetPointer(), it->first);
157 m_IdxToLabels[currentOutputIndex] = it->first;
158 currentOutputIndex++;
163 vtkImageData *vtkimage,
168 indexCoordinatesImageFilter->SetInputData(vtkimage);
169 indexCoordinatesImageFilter->SetOutputOrigin(0.0, 0.0, 0.0);
172 threshold->SetInputConnection(indexCoordinatesImageFilter->GetOutputPort());
174 threshold->SetInValue(100);
175 threshold->SetOutValue(0);
176 threshold->ThresholdBetween(label, label);
177 threshold->SetOutputScalarTypeToUnsignedChar();
178 threshold->ReleaseDataFlagOn();
181 gaussian->SetInputConnection(threshold->GetOutputPort());
183 gaussian->SetDimensionality(3);
184 gaussian->SetRadiusFactor(0.49);
185 gaussian->SetStandardDeviation(GetGaussianStandardDeviation());
186 gaussian->ReleaseDataFlagOn();
187 gaussian->UpdateInformation();
192 skinExtractor->ReleaseDataFlagOn();
193 skinExtractor->SetInputConnection(gaussian->GetOutputPort());
194 indexCoordinatesImageFilter->Delete();
195 skinExtractor->SetValue(0, 50);
197 vtkPolyData *polydata;
198 skinExtractor->Update();
199 polydata = skinExtractor->GetOutput();
200 polydata->Register(
nullptr);
201 skinExtractor->Delete();
207 smoother->SetInputData(polydata);
208 smoother->SetNumberOfIterations(m_SmoothIteration);
209 smoother->SetRelaxationFactor(m_SmoothRelaxation);
210 smoother->SetFeatureAngle(60);
211 smoother->FeatureEdgeSmoothingOff();
212 smoother->BoundarySmoothingOff();
213 smoother->SetConvergence(0);
217 polydata = smoother->GetOutput();
218 polydata->Register(
nullptr);
223 if (m_Decimate == DecimatePro)
226 decimate->SplittingOff();
227 decimate->SetErrorIsAbsolute(5);
228 decimate->SetFeatureAngle(30);
229 decimate->PreserveTopologyOn();
230 decimate->BoundaryVertexDeletionOff();
231 decimate->SetDegree(10);
233 decimate->SetInputData(polydata);
234 decimate->SetTargetReduction(m_TargetReduction);
235 decimate->SetMaximumError(0.002);
239 polydata = decimate->GetOutput();
240 polydata->Register(
nullptr);
244 if (polydata->GetNumberOfPoints() > 0)
246 mitk::Vector3D spacing = GetInput()->GetGeometry(time)->GetSpacing();
248 vtkPoints *points = polydata->GetPoints();
250 GetInput()->GetGeometry(time)->GetVtkTransform()->GetMatrix(vtkmatrix);
251 double(*matrix)[4] = vtkmatrix->Element;
254 for (i = 0; i < 3; ++i)
255 for (j = 0; j < 3; ++j)
256 matrix[i][j] /= spacing[j];
258 unsigned int n = points->GetNumberOfPoints();
261 for (i = 0; i < n; i++)
263 points->GetPoint(i, point);
264 mitkVtkLinearTransformPoint(matrix, point, point);
265 points->SetPoint(i, point);
271 polydata->UnRegister(
nullptr);
277 template <
typename TPixel,
unsigned int VImageDimension>
281 typedef itk::Image<TPixel, VImageDimension>
ImageType;
282 typedef itk::ImageRegionIterator<ImageType> ImageRegionIteratorType;
283 availableLabels.clear();
284 ImageRegionIteratorType it(image, image->GetLargestPossibleRegion());
286 mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
287 while (!it.IsAtEnd())
290 if (labelIt == availableLabels.end())
296 labelIt->second += 1;
303 #define InstantiateAccessFunction_GetAvailableLabelsInternal(pixelType, dim) \
306 GetAvailableLabelsInternal(itk::Image<pixelType, dim> *, mitk::LabeledImageToSurfaceFilter::LabelMapType &);
315 return availableLabels;
320 itkWarningMacro(
"This function should never be called!");
325 const unsigned int &idx)
327 auto it = m_IdxToLabels.find(idx);
328 if (it != m_IdxToLabels.end())
334 itkWarningMacro(
"Unknown index encountered: " << idx <<
". There are " << this->GetNumberOfOutputs()
335 <<
" outputs available.");
342 return GetVolumeForLabel(GetLabelForNthOutput(i));
354 auto it = m_AvailableLabels.find(label);
355 if (it != m_AvailableLabels.end())
357 return static_cast<float>(it->second) * (spacing[0] * spacing[1] * spacing[2] / 1000.0f);
361 itkWarningMacro(
"Unknown label encountered: " << label);
virtual void CreateSurface(int time, vtkImageData *vtkimage, mitk::Surface *surface, LabelType label)
Class for storing surfaces (vtkPolyData).
mitk::ScalarType GetVolumeForNthOutput(const unsigned int &i)
virtual ~LabeledImageToSurfaceFilter()
virtual const RegionType & GetRequestedRegion() const
virtual void GenerateData() override
InstantiateAccessFunctionForFixedDimension(GetAvailableLabelsInternal, 3)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
LabelType GetLabelForNthOutput(const unsigned int &i)
LabeledImageToSurfaceFilter()
virtual void GenerateOutputInformation() override
map::core::discrete::Elements< 3 >::InternalImageType ImageType
itk::ImageRegion< RegionDimension > RegionType
Image class for storing images.
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
void GetAvailableLabelsInternal(itk::Image< TPixel, VImageDimension > *image, mitk::LabeledImageToSurfaceFilter::LabelMapType &availableLabels)
mitk::ScalarType GetVolumeForLabel(const LabelType &label)
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
std::map< LabelType, unsigned long > LabelMapType
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
virtual LabelMapType GetAvailableLabels()
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.