15 #include <vtkDecimatePro.h> 16 #include <vtkImageChangeInformation.h> 17 #include <vtkImageGaussianSmooth.h> 18 #include <vtkImageMarchingCubes.h> 19 #include <vtkImageThreshold.h> 20 #include <vtkLinearTransform.h> 21 #include <vtkMatrix4x4.h> 22 #include <vtkPolyData.h> 23 #include <vtkSmoothPolyDataFilter.h> 25 #include <itkImageRegionIterator.h> 26 #include <itkNumericTraits.h> 31 : m_GaussianStandardDeviation(1.5), m_GenerateAllLabels(true), m_Label(1), m_BackgroundLabel(0)
41 Superclass::GenerateOutputInformation();
56 LabelMapType::iterator it;
79 unsigned int numberOfOutputs = 0;
84 if (numberOfOutputs == 0)
86 itkWarningMacro(
"Number of outputs == 0");
100 this->SetNumberOfIndexedOutputs(numberOfOutputs);
101 this->SetNumberOfRequiredOutputs(numberOfOutputs);
102 for (
unsigned int i = 0; i < numberOfOutputs; ++i)
107 assert(output.IsNotNull());
108 output->Expand(numberOfTimeSteps);
109 this->SetNthOutput(i, output.GetPointer());
117 if (image ==
nullptr)
119 itkWarningMacro(
"Image is nullptr");
127 if (this->GetNumberOfOutputs() == 0)
133 unsigned int currentOutputIndex = 0;
141 assert(currentOutputIndex < this->GetNumberOfOutputs());
143 assert(surface.IsNotNull());
145 int tstart = outputRegion.GetIndex(3);
146 int tmax = tstart + outputRegion.GetSize(3);
148 for (t = tstart; t < tmax; ++t)
151 CreateSurface(t, vtkimagedata, surface.GetPointer(), it->first);
154 currentOutputIndex++;
159 vtkImageData *vtkimage,
163 vtkImageChangeInformation *indexCoordinatesImageFilter = vtkImageChangeInformation::New();
164 indexCoordinatesImageFilter->SetInputData(vtkimage);
165 indexCoordinatesImageFilter->SetOutputOrigin(0.0, 0.0, 0.0);
167 vtkImageThreshold *threshold = vtkImageThreshold::New();
168 threshold->SetInputConnection(indexCoordinatesImageFilter->GetOutputPort());
170 threshold->SetInValue(100);
171 threshold->SetOutValue(0);
172 threshold->ThresholdBetween(label, label);
173 threshold->SetOutputScalarTypeToUnsignedChar();
174 threshold->ReleaseDataFlagOn();
176 vtkImageGaussianSmooth *gaussian = vtkImageGaussianSmooth::New();
177 gaussian->SetInputConnection(threshold->GetOutputPort());
179 gaussian->SetDimensionality(3);
180 gaussian->SetRadiusFactor(0.49);
182 gaussian->ReleaseDataFlagOn();
183 gaussian->UpdateInformation();
187 vtkMarchingCubes *skinExtractor = vtkMarchingCubes::New();
188 skinExtractor->ReleaseDataFlagOn();
189 skinExtractor->SetInputConnection(gaussian->GetOutputPort());
190 indexCoordinatesImageFilter->Delete();
191 skinExtractor->SetValue(0, 50);
193 vtkPolyData *polydata;
194 skinExtractor->Update();
195 polydata = skinExtractor->GetOutput();
196 polydata->Register(
nullptr);
197 skinExtractor->Delete();
201 vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
203 smoother->SetInputData(polydata);
206 smoother->SetFeatureAngle(60);
207 smoother->FeatureEdgeSmoothingOff();
208 smoother->BoundarySmoothingOff();
209 smoother->SetConvergence(0);
213 polydata = smoother->GetOutput();
214 polydata->Register(
nullptr);
221 vtkDecimatePro *decimate = vtkDecimatePro::New();
222 decimate->SplittingOff();
223 decimate->SetErrorIsAbsolute(5);
224 decimate->SetFeatureAngle(30);
225 decimate->PreserveTopologyOn();
226 decimate->BoundaryVertexDeletionOff();
227 decimate->SetDegree(10);
229 decimate->SetInputData(polydata);
231 decimate->SetMaximumError(0.002);
235 polydata = decimate->GetOutput();
236 polydata->Register(
nullptr);
240 if (polydata->GetNumberOfPoints() > 0)
244 vtkPoints *points = polydata->GetPoints();
245 vtkMatrix4x4 *vtkmatrix = vtkMatrix4x4::New();
247 double(*matrix)[4] = vtkmatrix->Element;
250 for (i = 0; i < 3; ++i)
251 for (j = 0; j < 3; ++j)
252 matrix[i][j] /= spacing[j];
254 unsigned int n = points->GetNumberOfPoints();
257 for (i = 0; i < n; i++)
259 points->GetPoint(i, point);
261 points->SetPoint(i, point);
267 polydata->UnRegister(
nullptr);
273 template <
typename TPixel,
unsigned int VImageDimension>
277 typedef itk::Image<TPixel, VImageDimension>
ImageType;
278 typedef itk::ImageRegionIterator<ImageType> ImageRegionIteratorType;
279 availableLabels.clear();
280 ImageRegionIteratorType it(image, image->GetLargestPossibleRegion());
282 mitk::LabeledImageToSurfaceFilter::LabelMapType::iterator labelIt;
283 while (!it.IsAtEnd())
286 if (labelIt == availableLabels.end())
292 labelIt->second += 1;
299 #define InstantiateAccessFunction_GetAvailableLabelsInternal(pixelType, dim) \ 302 GetAvailableLabelsInternal(itk::Image<pixelType, dim> *, mitk::LabeledImageToSurfaceFilter::LabelMapType &); 311 return availableLabels;
316 itkWarningMacro(
"This function should never be called!");
321 const unsigned int &idx)
330 itkWarningMacro(
"Unknown index encountered: " << idx <<
". There are " << this->GetNumberOfOutputs()
331 <<
" outputs available.");
353 return static_cast<float>(it->second) * (spacing[0] * spacing[1] * spacing[2] / 1000.0f);
357 itkWarningMacro(
"Unknown label encountered: " << label);
virtual void CreateSurface(int time, vtkImageData *vtkimage, mitk::Surface *surface, LabelType label)
Class for storing surfaces (vtkPolyData).
~LabeledImageToSurfaceFilter() override
mitk::ScalarType GetVolumeForNthOutput(const unsigned int &i)
virtual TimeStepType CountTimeSteps() const =0
Returns the number of time steps.
itk::Image< unsigned char, 3 > ImageType
void GenerateData() override
InstantiateAccessFunctionForFixedDimension(GetAvailableLabelsInternal, 3)
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
const mitk::Image * GetInput(void)
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
LabelType GetLabelForNthOutput(const unsigned int &i)
LabeledImageToSurfaceFilter()
void GenerateOutputInformation() override
void mitkVtkLinearTransformPoint(T1 matrix[4][4], T2 in[3], T3 out[3])
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
IdxToLabelMapType m_IdxToLabels
LabelType m_BackgroundLabel
itk::ImageRegion< RegionDimension > RegionType
Image class for storing images.
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 const RegionType & GetRequestedRegion() const
virtual void SetVtkPolyData(vtkPolyData *polydata, unsigned int t=0)
mitk::Image::Pointer image
void GetAvailableLabelsInternal(itk::Image< TPixel, VImageDimension > *image, mitk::LabeledImageToSurfaceFilter::LabelMapType &availableLabels)
mitk::ScalarType GetVolumeForLabel(const LabelType &label)
#define AccessFixedDimensionByItk_1(mitkImage, itkImageTypeFunction, dimension, arg1)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
LabelMapType m_AvailableLabels
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
DecimationType m_Decimate
virtual double GetGaussianStandardDeviation()
std::map< LabelType, unsigned long > LabelMapType
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
virtual LabelMapType GetAvailableLabels()