17 #include <itkAddImageFilter.h> 18 #include <itkBinaryMedianImageFilter.h> 19 #include <itkBinaryThresholdImageFilter.h> 20 #include <itkConnectedThresholdImageFilter.h> 21 #include <itkConstantPadImageFilter.h> 22 #include <itkDiscreteGaussianImageFilter.h> 23 #include <itkImageRegionIteratorWithIndex.h> 24 #include <itkMultiplyImageFilter.h> 25 #include <itkRegionOfInterestImageFilter.h> 33 #include <vtkCleanPolyData.h> 34 #include <vtkPolyDataNormals.h> 35 #include <vtkQuadricDecimation.h> 40 ShowSegmentationAsSmoothedSurface::ShowSegmentationAsSmoothedSurface()
44 ShowSegmentationAsSmoothedSurface::~ShowSegmentationAsSmoothedSurface()
50 Superclass::Initialize(other);
52 bool syncVisibility =
false;
57 SetParameter(
"Sync visibility", syncVisibility);
58 SetParameter(
"Wireframe",
false);
62 SetParameter(
"Smoothing", 1.0);
67 SetParameter(
"Decimation", 0.5);
71 SetParameter(
"Closing", 0.0);
79 GetPointerParameter(
"Input", image);
81 return image.IsNotNull() && GetGroupNode();
83 catch (
const invalid_argument &)
92 GetPointerParameter(
"Input", image);
95 GetParameter(
"Smoothing", smoothing);
98 GetParameter(
"Decimation", decimation);
101 GetParameter(
"Closing", closing);
104 GetParameter(
"TimeNr", timeNr);
106 if (image->GetDimension() == 4)
107 MITK_INFO <<
"CREATING SMOOTHED POLYGON MODEL (t = " << timeNr <<
')';
109 MITK_INFO <<
"CREATING SMOOTHED POLYGON MODEL";
111 MITK_INFO <<
" Smoothing = " << smoothing;
112 MITK_INFO <<
" Decimation = " << decimation;
119 typedef itk::Image<unsigned char, 3> CharImageType;
120 typedef itk::Image<unsigned short, 3> ShortImageType;
123 if (image->GetDimension() == 4)
126 imageTimeSelector->SetInput(image);
127 imageTimeSelector->SetTimeNr(timeNr);
128 imageTimeSelector->UpdateLargestPossibleRegion();
129 image = imageTimeSelector->GetOutput(0);
136 imageToItkFilter->SetInput(image);
138 catch (
const itk::ExceptionObject &e)
146 imageToItkFilter->Update();
148 CharImageType::Pointer itkImage = imageToItkFilter->GetOutput();
155 bool roiFound =
false;
157 CharImageType::IndexType minIndex;
160 CharImageType::IndexType maxIndex;
163 itk::ImageRegionIteratorWithIndex<CharImageType> iter(itkImage, itkImage->GetLargestPossibleRegion());
165 for (iter.GoToBegin(); !iter.IsAtEnd(); ++iter)
167 if (iter.Get() == imageLabel)
172 CharImageType::IndexType currentIndex = iter.GetIndex();
174 for (
unsigned int dim = 0; dim < 3; ++dim)
176 minIndex[dim] =
min(currentIndex[dim], minIndex[dim]);
177 maxIndex[dim] =
max(currentIndex[dim], maxIndex[dim]);
189 MITK_ERROR <<
"Didn't found segmentation labeled with " << imageLabel <<
"!" << endl;
197 typedef itk::RegionOfInterestImageFilter<CharImageType, CharImageType> ROIFilterType;
199 ROIFilterType::Pointer roiFilter = ROIFilterType::New();
200 CharImageType::RegionType region;
201 CharImageType::SizeType size;
203 for (
unsigned int dim = 0; dim < 3; ++dim)
205 size[dim] = maxIndex[dim] - minIndex[dim] + 1;
208 region.SetIndex(minIndex);
209 region.SetSize(size);
211 roiFilter->SetInput(itkImage);
212 roiFilter->SetRegionOfInterest(region);
213 roiFilter->ReleaseDataFlagOn();
214 roiFilter->ReleaseDataBeforeUpdateFlagOn();
216 typedef itk::ConstantPadImageFilter<CharImageType, CharImageType> PadFilterType;
218 PadFilterType::Pointer padFilter = PadFilterType::New();
219 const PadFilterType::SizeValueType pad[3] = {10, 10, 10};
221 padFilter->SetInput(roiFilter->GetOutput());
222 padFilter->SetConstant(0);
223 padFilter->SetPadLowerBound(pad);
224 padFilter->SetPadUpperBound(pad);
225 padFilter->ReleaseDataFlagOn();
226 padFilter->ReleaseDataBeforeUpdateFlagOn();
229 CharImageType::Pointer roiImage = padFilter->GetOutput();
231 roiImage->DisconnectPipeline();
239 TransformType::Pointer transform = TransformType::New();
240 TransformType::OutputVectorType translation;
242 for (
unsigned int dim = 0; dim < 3; ++dim)
243 translation[dim] = (
int)minIndex[dim] - (int)pad[dim];
245 transform->SetIdentity();
246 transform->Translate(translation);
247 geometry->Compose(transform,
true);
255 typedef itk::BinaryMedianImageFilter<CharImageType, CharImageType> MedianFilterType;
257 MedianFilterType::Pointer medianFilter = MedianFilterType::New();
258 CharImageType::SizeType radius = {{0}};
260 medianFilter->SetRadius(radius);
261 medianFilter->SetBackgroundValue(0);
262 medianFilter->SetForegroundValue(1);
263 medianFilter->SetInput(roiImage);
264 medianFilter->ReleaseDataFlagOn();
265 medianFilter->ReleaseDataBeforeUpdateFlagOn();
266 medianFilter->Update();
274 auto surfaceRatio = (
unsigned int)((1.0f - closing) * 100.0f);
278 ClosingFilterType::Pointer closingFilter = ClosingFilterType::New();
280 closingFilter->SetInput(medianFilter->GetOutput());
281 closingFilter->ReleaseDataFlagOn();
282 closingFilter->ReleaseDataBeforeUpdateFlagOn();
283 closingFilter->SetSurfaceRatio(surfaceRatio);
284 closingFilter->Update();
286 ShortImageType::Pointer closedImage = closingFilter->GetOutput();
288 closedImage->DisconnectPipeline();
290 medianFilter =
nullptr;
291 closingFilter =
nullptr;
299 typedef itk::BinaryThresholdImageFilter<ShortImageType, FloatImageType> BinaryThresholdToFloatFilterType;
301 BinaryThresholdToFloatFilterType::Pointer binThresToFloatFilter = BinaryThresholdToFloatFilterType::New();
303 binThresToFloatFilter->SetInput(closedImage);
304 binThresToFloatFilter->SetLowerThreshold(1);
305 binThresToFloatFilter->SetUpperThreshold(1);
306 binThresToFloatFilter->SetInsideValue(100);
307 binThresToFloatFilter->SetOutsideValue(0);
308 binThresToFloatFilter->ReleaseDataFlagOn();
309 binThresToFloatFilter->ReleaseDataBeforeUpdateFlagOn();
311 typedef itk::DiscreteGaussianImageFilter<FloatImageType, FloatImageType> GaussianFilterType;
314 GaussianFilterType::Pointer gaussFilter = GaussianFilterType::New();
316 gaussFilter->SetInput(binThresToFloatFilter->GetOutput());
317 gaussFilter->SetUseImageSpacing(
true);
318 gaussFilter->SetVariance(smoothing);
319 gaussFilter->ReleaseDataFlagOn();
320 gaussFilter->ReleaseDataBeforeUpdateFlagOn();
322 typedef itk::BinaryThresholdImageFilter<FloatImageType, CharImageType> BinaryThresholdFromFloatFilterType;
324 BinaryThresholdFromFloatFilterType::Pointer binThresFromFloatFilter = BinaryThresholdFromFloatFilterType::New();
326 binThresFromFloatFilter->SetInput(gaussFilter->GetOutput());
327 binThresFromFloatFilter->SetLowerThreshold(50);
328 binThresFromFloatFilter->SetUpperThreshold(255);
329 binThresFromFloatFilter->SetInsideValue(1);
330 binThresFromFloatFilter->SetOutsideValue(0);
331 binThresFromFloatFilter->ReleaseDataFlagOn();
332 binThresFromFloatFilter->ReleaseDataBeforeUpdateFlagOn();
333 binThresFromFloatFilter->Update();
335 CharImageType::Pointer blurredImage = binThresFromFloatFilter->GetOutput();
337 blurredImage->DisconnectPipeline();
338 closedImage =
nullptr;
339 binThresToFloatFilter =
nullptr;
340 gaussFilter =
nullptr;
348 typedef itk::ConnectedThresholdImageFilter<CharImageType, CharImageType> ConnectedThresholdFilterType;
350 ConnectedThresholdFilterType::Pointer connectedThresFilter = ConnectedThresholdFilterType::New();
352 CharImageType::IndexType corner;
358 connectedThresFilter->SetInput(blurredImage);
359 connectedThresFilter->SetSeed(corner);
360 connectedThresFilter->SetLower(0);
361 connectedThresFilter->SetUpper(0);
362 connectedThresFilter->SetReplaceValue(2);
363 connectedThresFilter->ReleaseDataFlagOn();
364 connectedThresFilter->ReleaseDataBeforeUpdateFlagOn();
366 typedef itk::BinaryThresholdImageFilter<CharImageType, CharImageType> BinaryThresholdFilterType;
368 BinaryThresholdFilterType::Pointer binThresFilter = BinaryThresholdFilterType::New();
370 binThresFilter->SetInput(connectedThresFilter->GetOutput());
371 binThresFilter->SetLowerThreshold(0);
372 binThresFilter->SetUpperThreshold(0);
373 binThresFilter->SetInsideValue(50);
374 binThresFilter->SetOutsideValue(0);
375 binThresFilter->ReleaseDataFlagOn();
376 binThresFilter->ReleaseDataBeforeUpdateFlagOn();
378 typedef itk::AddImageFilter<CharImageType, CharImageType, CharImageType> AddFilterType;
380 AddFilterType::Pointer addFilter = AddFilterType::New();
382 addFilter->SetInput1(blurredImage);
383 addFilter->SetInput2(binThresFilter->GetOutput());
384 addFilter->ReleaseDataFlagOn();
385 addFilter->ReleaseDataBeforeUpdateFlagOn();
397 filteredImage->SetGeometry(geometry);
401 imageToSurfaceFilter->SetInput(filteredImage);
402 imageToSurfaceFilter->SetThreshold(50);
403 imageToSurfaceFilter->SmoothOn();
406 m_Surface = imageToSurfaceFilter->GetOutput(0);
412 if (decimation > 0.0f && decimation < 1.0f)
414 MITK_INFO <<
"Quadric mesh decimation...";
416 vtkQuadricDecimation *quadricDecimation = vtkQuadricDecimation::New();
417 quadricDecimation->SetInputData(m_Surface->GetVtkPolyData());
418 quadricDecimation->SetTargetReduction(decimation);
419 quadricDecimation->AttributeErrorMetricOn();
420 quadricDecimation->GlobalWarningDisplayOff();
421 quadricDecimation->Update();
423 vtkCleanPolyData *cleaner = vtkCleanPolyData::New();
424 cleaner->SetInputConnection(quadricDecimation->GetOutputPort());
425 cleaner->PieceInvariantOn();
426 cleaner->ConvertLinesToPointsOn();
427 cleaner->ConvertStripsToPolysOn();
428 cleaner->PointMergingOn();
431 m_Surface->SetVtkPolyData(cleaner->GetOutput());
438 vtkPolyDataNormals *computeNormals = vtkPolyDataNormals::New();
439 computeNormals->SetInputData(m_Surface->GetVtkPolyData());
440 computeNormals->SetFeatureAngle(360.0f);
441 computeNormals->AutoOrientNormalsOn();
442 computeNormals->FlipNormalsOff();
443 computeNormals->Update();
445 m_Surface->SetVtkPolyData(computeNormals->GetOutput());
454 bool wireframe =
false;
455 GetParameter(
"Wireframe", wireframe);
459 auto *representation =
462 if (representation !=
nullptr)
470 std::string groupNodeName =
"surface";
471 DataNode *groupNode = GetGroupNode();
473 if (groupNode !=
nullptr)
474 groupNode->
GetName(groupNodeName);
477 node->SetData(m_Surface);
481 if (colorProperty !=
nullptr)
482 node->ReplaceProperty(
"color", colorProperty->
Clone());
486 bool showResult =
true;
487 GetParameter(
"Show result", showResult);
489 bool syncVisibility =
false;
490 GetParameter(
"Sync visibility", syncVisibility);
493 GetPointerParameter(
"Input", image);
495 BaseProperty *organTypeProperty = image->GetProperty(
"organ type");
497 if (organTypeProperty !=
nullptr)
498 m_Surface->SetProperty(
"organ type", organTypeProperty);
502 if (visibleProperty !=
nullptr && syncVisibility)
503 node->ReplaceProperty(
"visible", visibleProperty->
Clone());
507 InsertBelowGroupNode(node);
509 Superclass::ThreadedUpdateSuccessful();
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr, bool fallBackOnDataProperties=true) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
Standard implementation of BaseGeometry.
GeometryTransformHolder::TransformType TransformType
DataCollection - Class to facilitate loading/accessing structured data.
itk::Image< double, 3 > FloatImageType
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
void GetParameter(const char *parameter, T &value) const
Abstract base class for properties.
mitk::Image::Pointer image
void CastToMitkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, itk::SmartPointer< mitk::Image > &mitkoutputimage)
Cast an itk::Image (with a specific type) to an mitk::Image.
bool ReadyToRun() override
virtual void SetRepresentationToWireframe()
void Initialize(const NonBlockingAlgorithm *other=nullptr) override
void ThreadedUpdateSuccessful() override
Class for nodes of the DataTree.
bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="name") const
Convenience access method for accessing the name of an object (instance of StringProperty with proper...
bool ThreadedUpdateFunction() override