20 #include <qmessagebox.h>
31 #include "itkMaskImageFilter.h"
32 #include "itkNumericTraits.h"
33 #include <itkBinaryThresholdImageFilter.h>
35 #include <itkImageIterator.h>
36 #include <itkMinimumMaximumImageCalculator.h>
39 #include "itkOrImageFilter.h"
51 m_MultiWidget(
nullptr),
53 m_UseVolumeRendering(false),
54 m_UpdateSuggestedThreshold(true),
55 m_SuggestedThValue(0.0)
57 this->setParent(parent);
59 m_Controls.setupUi(
this);
61 m_Controls.m_ThresholdSlider->setDecimals(1);
62 m_Controls.m_ThresholdSlider->setSpinBoxAlignment(Qt::AlignVCenter);
64 m_Controls.m_PreviewSlider->setEnabled(
false);
65 m_Controls.m_PreviewSlider->setSingleStep(0.5);
69 this->CreateConnections();
70 this->SetDataNodeNames(
"labeledRGSegmentation",
"RGResult",
"RGFeedbackSurface",
"maskedSegmentation");
72 connect(
this, SIGNAL(NewToolAssociated(
mitk::Tool *)),
this, SLOT(OnNewToolAssociated(
mitk::Tool *)));
80 m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetAddObserverTag);
81 m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetMoveObserverTag);
83 this->RemoveHelperNodes();
99 m_PointSetAddObserverTag =
100 m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand);
101 m_PointSetMoveObserverTag =
102 m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetMoveEvent(), pointAddedCommand);
110 void QmitkAdaptiveRegionGrowingToolGUI::RemoveHelperNodes()
113 if (imageNode.IsNotNull())
119 if (maskedSegmentationNode.IsNotNull())
139 std::string binaryImage,
141 std::string maskedSegmentation)
143 m_NAMEFORLABLEDSEGMENTATIONIMAGE = labledSegmentation;
144 m_NAMEFORBINARYIMAGE = binaryImage;
145 m_NAMEFORSURFACE = surface;
146 m_NAMEFORMASKEDSEGMENTATION = maskedSegmentation;
167 m_Controls.m_ThresholdSlider->setMaximum(max);
168 m_Controls.m_ThresholdSlider->setMinimum(min);
170 m_Controls.m_ThresholdSlider->setMaximumValue(max);
171 m_Controls.m_ThresholdSlider->setMinimumValue(min);
175 template <
typename TPixel>
193 if (pointSet.IsNull())
195 QMessageBox::critical(NULL,
"QmitkAdaptiveRegionGrowingToolGUI",
"PointSetNode does not contain a pointset");
217 m_CurrentRGDirectionIsUpwards =
true;
218 if (m_SeedpointValue < -500)
220 m_CurrentRGDirectionIsUpwards =
false;
224 m_SeedPointValueMean = 0;
231 runningIndex = currentIndex;
233 for (
int i = runningIndex[0] - 2; i <= runningIndex[0] + 2; i++)
235 for (
int j = runningIndex[1] - 2; j <= runningIndex[1] + 2; j++)
237 for (
int k = runningIndex[2] - 2; k <= runningIndex[2] + 2; k++)
267 unsigned int numberOfValues(0);
268 for (
auto &pixelValue : pixelValues)
272 m_SeedPointValueMean += pixelValue;
276 m_SeedPointValueMean = m_SeedPointValueMean / numberOfValues;
279 if (numberOfValues > 1)
281 for (
auto &pixelValue : pixelValues)
285 var += (pixelValue - m_SeedPointValueMean) * (pixelValue - m_SeedPointValueMean);
288 var /= numberOfValues - 1;
304 windowSize = 0.15 * windowSize;
306 if (m_CurrentRGDirectionIsUpwards)
308 m_LOWERTHRESHOLD = m_SeedPointValueMean - stdDev;
309 m_UPPERTHRESHOLD = m_SeedpointValue + windowSize;
310 if (m_UPPERTHRESHOLD > max)
311 m_UPPERTHRESHOLD =
max;
312 m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD);
313 m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD);
317 m_UPPERTHRESHOLD = m_SeedPointValueMean;
318 if (m_SeedpointValue > m_SeedPointValueMean)
319 m_UPPERTHRESHOLD = m_SeedpointValue;
320 m_LOWERTHRESHOLD = m_SeedpointValue - windowSize;
321 if (m_LOWERTHRESHOLD < min)
322 m_LOWERTHRESHOLD =
min;
323 m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD);
324 m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD);
333 QMessageBox::information(NULL,
"Adaptive Region Growing functionality",
"Please specify the image in Datamanager!");
341 QMessageBox::information(NULL,
"Adaptive Region Growing functionality",
"Please insert a seed point inside the "
342 "image.\n\nFirst press the \"Define Seed "
343 "Point\" button,\nthen click left mouse "
344 "button inside the image.");
350 if (seedPointSet.IsNull())
352 m_Controls.m_pbRunSegmentation->setEnabled(
true);
353 QMessageBox::information(
354 NULL,
"Adaptive Region Growing functionality",
"The seed point is empty! Please choose a new seed point.");
361 if (!(seedPointSet->GetSize(timeStep)))
363 m_Controls.m_pbRunSegmentation->setEnabled(
true);
364 QMessageBox::information(
365 NULL,
"Adaptive Region Growing functionality",
"The seed point is empty! Please choose a new seed point.");
369 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
375 if (orgImage.IsNotNull())
377 if (orgImage->GetDimension() == 4)
380 timeSelector->SetInput(orgImage);
381 timeSelector->SetTimeNr(timeStep);
382 timeSelector->UpdateLargestPossibleRegion();
383 mitk::Image *timedImage = timeSelector->GetOutput();
386 else if (orgImage->GetDimension() == 3)
389 AccessByItk_2(orgImage, StartRegionGrowing, orgImage->GetGeometry(), seedPoint);
394 QApplication::restoreOverrideCursor();
395 QMessageBox::information(
396 NULL,
"Adaptive Region Growing functionality",
"Only images of dimension 3 or 4 can be processed!");
401 node->SetVisibility(
true);
402 QApplication::restoreOverrideCursor();
405 template <
typename TPixel,
unsigned int VImageDimension>
406 void QmitkAdaptiveRegionGrowingToolGUI::StartRegionGrowing(itk::Image<TPixel, VImageDimension> *itkImage,
411 typedef typename InputImageType::IndexType IndexType;
414 typedef itk::MinimumMaximumImageCalculator<InputImageType> MinMaxValueFilterType;
415 typedef itk::BinaryThresholdImageFilter<InputImageType, InputImageType> ThresholdFilterType;
416 typedef itk::MaskImageFilter<InputImageType, InputImageType, InputImageType> MaskImageFilterType;
418 if (!imageGeometry->
IsInside(seedPoint))
420 QApplication::restoreOverrideCursor();
421 QMessageBox::information(NULL,
422 "Segmentation functionality",
423 "The seed point is outside of the image! Please choose a position inside the image!");
430 if (m_SeedpointValue > m_UPPERTHRESHOLD || m_SeedpointValue < m_LOWERTHRESHOLD)
432 QApplication::restoreOverrideCursor();
433 QMessageBox::information(
435 "Segmentation functionality",
436 "The seed point is outside the defined thresholds! Please set a new seed point or adjust the thresholds.");
437 MITK_INFO <<
"Mean: " << m_SeedPointValueMean;
443 regionGrower->SetGrowingDirectionIsUpwards(m_CurrentRGDirectionIsUpwards);
444 regionGrower->SetInput(itkImage);
445 regionGrower->AddSeed(seedIndex);
448 regionGrower->SetLower(m_LOWERTHRESHOLD - 1);
449 regionGrower->SetUpper(m_UPPERTHRESHOLD + 1);
453 regionGrower->Update();
455 catch (itk::ExceptionObject &exc)
457 QMessageBox errorInfo;
458 errorInfo.setWindowTitle(
"Adaptive RG Segmentation Functionality");
459 errorInfo.setIcon(QMessageBox::Critical);
460 errorInfo.setText(
"An error occurred during region growing!");
461 errorInfo.setDetailedText(exc.what());
467 QMessageBox::critical(NULL,
"Adaptive RG Segmentation Functionality",
"An error occurred during region growing!");
473 m_Controls.m_PreviewSlider->setMinimum(m_LOWERTHRESHOLD);
475 mitk::ScalarType max = m_SeedpointValue + resultImage->GetStatistics()->GetScalarValueMax();
476 if (max < m_UPPERTHRESHOLD)
479 m_Controls.m_PreviewSlider->setMaximum(m_UPPERTHRESHOLD);
481 this->m_DetectedLeakagePoint = regionGrower->GetLeakagePoint();
483 if (m_CurrentRGDirectionIsUpwards)
485 m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean - 1);
489 m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean + 1);
491 this->m_SliderInitialized =
true;
495 newNode->SetData(resultImage);
512 mitk::CastToItkImage<InputImageType>(resultImage, inputImageItk);
515 thresholdFilter->SetInput(inputImageItk);
516 thresholdFilter->SetInsideValue(1);
517 thresholdFilter->SetOutsideValue(0);
519 double sliderVal = this->
m_Controls.m_PreviewSlider->value();
520 if (m_CurrentRGDirectionIsUpwards)
522 thresholdFilter->SetLowerThreshold(sliderVal);
528 thresholdFilter->SetUpperThreshold(sliderVal);
530 thresholdFilter->SetInPlace(
false);
533 maskFilter->SetInput(inputImageItk);
534 maskFilter->SetInPlace(
false);
535 maskFilter->SetMaskImage(thresholdFilter->GetOutput());
536 maskFilter->SetOutsideValue(0);
537 maskFilter->UpdateLargestPossibleRegion();
540 mitk::CastToMitkImage<InputImageType>(maskFilter->GetOutput(), mitkMask);
542 maskedNode->SetData(mitkMask);
558 this->InitializeLevelWindow();
560 if (m_UseVolumeRendering)
561 this->EnableVolumeRendering(
true);
563 m_UpdateSuggestedThreshold =
true;
569 void QmitkAdaptiveRegionGrowingToolGUI::InitializeLevelWindow()
575 newNode->GetLevelWindow(tempLevelWindow, NULL,
"levelwindow");
581 if (m_CurrentRGDirectionIsUpwards)
583 upper = m_UPPERTHRESHOLD - m_SeedpointValue;
587 upper = m_SeedpointValue - m_LOWERTHRESHOLD;
594 if (m_CurrentRGDirectionIsUpwards)
596 this->
m_Controls.m_PreviewSlider->setValue(m_SeedpointValue);
597 *level = m_UPPERTHRESHOLD - (m_SeedpointValue) + 0.5;
601 this->
m_Controls.m_PreviewSlider->setValue(m_SeedpointValue);
602 *level = (m_SeedpointValue)-m_LOWERTHRESHOLD + 0.5;
606 newNode->SetLevelWindow(tempLevelWindow, NULL,
"levelwindow");
610 m_SliderInitialized =
true;
613 static int lastSliderPosition = 0;
614 if ((this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1) == lastSliderPosition)
618 lastSliderPosition = this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1;
624 static_cast<mitk::LevelWindowProperty *>(newNode->GetProperty(
"levelwindow")));
627 if (m_UseVolumeRendering)
628 this->UpdateVolumeRenderingThreshold((
int)(*level + 0.5));
633 if (m_SliderInitialized)
637 if (newNode.IsNull())
642 newNode->GetLevelWindow(tempLevelWindow, NULL,
"levelwindow");
648 if (m_CurrentRGDirectionIsUpwards)
650 level = m_UPPERTHRESHOLD - newValue + 0.5;
655 level = newValue - m_LOWERTHRESHOLD + 0.5;
659 newNode->SetLevelWindow(tempLevelWindow, NULL,
"levelwindow");
661 if (m_UseVolumeRendering)
662 this->UpdateVolumeRenderingThreshold((
int)(level - 0.5));
664 newNode->SetVisibility(
true);
674 int newValue = this->
m_Controls.m_PreviewSlider->value() - 1;
676 this->
m_Controls.m_PreviewSlider->setValue(newValue);
685 int newValue = this->
m_Controls.m_PreviewSlider->value() + 1;
687 this->
m_Controls.m_PreviewSlider->setValue(newValue);
696 QMessageBox::critical(NULL,
"Adaptive region growing functionality",
"Please specify the image in Datamanager!");
701 if (orgImage.IsNull())
703 QMessageBox::critical(NULL,
"Adaptive region growing functionality",
"No Image found!");
709 if (labeledSeg.IsNull())
711 QMessageBox::critical(NULL,
"Adaptive region growing functionality",
"No Segmentation Preview found!");
716 if (newNode.IsNull())
720 QString segName = QString::fromStdString(
m_RegionGrow3DTool->GetCurrentSegmentationName());
723 int result = dialog.exec();
741 this->EnableVolumeRendering(
false);
742 newNode->SetVisibility(
false);
743 m_Controls.m_cbVolumeRendering->setChecked(
false);
752 template <
typename TPixel,
unsigned int VImageDimension>
753 void QmitkAdaptiveRegionGrowingToolGUI::ITKThresholding(itk::Image<TPixel, VImageDimension> *itkImage)
761 if (originalSegmentation)
764 typedef itk::Image<mitk::Tool::DefaultSegmentationDataType, VImageDimension> SegmentationType;
768 if (originalSegmentation->GetTimeGeometry()->CountTimeSteps() > 1)
771 timeSelector->SetInput(originalSegmentation);
772 timeSelector->SetTimeNr(timeStep);
773 timeSelector->UpdateLargestPossibleRegion();
774 CastToItkImage(timeSelector->GetOutput(), originalSegmentationInITK);
782 originalSegmentationInITK->FillBuffer(0);
783 itk::ImageRegionIterator<SegmentationType> itOutput(originalSegmentationInITK,
784 originalSegmentationInITK->GetLargestPossibleRegion());
785 itk::ImageRegionIterator<InputImageType> itInput(itkImage, itkImage->GetLargestPossibleRegion());
786 itOutput.GoToBegin();
790 int currentTreshold = 0;
791 if (m_CurrentRGDirectionIsUpwards)
793 currentTreshold = m_UPPERTHRESHOLD -
m_Controls.m_PreviewSlider->value() + 1;
797 currentTreshold =
m_Controls.m_PreviewSlider->value() - m_LOWERTHRESHOLD;
801 while (!itOutput.IsAtEnd() && !itInput.IsAtEnd())
804 if (itInput.Value() != 0 && itInput.Value() >= currentTreshold)
814 originalSegmentation->SetVolume((
void *)(originalSegmentationInITK->GetPixelContainer()->GetBufferPointer()),
817 originalSegmentation->Modified();
832 this->
m_Controls.m_pbRunSegmentation->setEnabled(
false);
836 this->
m_Controls.m_pbRunSegmentation->setEnabled(enable);
844 this->
m_Controls.m_PreviewSlider->setEnabled(
false);
845 this->
m_Controls.m_pbConfirmSegementation->setEnabled(
false);
849 this->
m_Controls.m_PreviewSlider->setEnabled(enable);
850 this->
m_Controls.m_pbConfirmSegementation->setEnabled(enable);
853 this->
m_Controls.m_cbVolumeRendering->setEnabled(enable);
856 void QmitkAdaptiveRegionGrowingToolGUI::EnableVolumeRendering(
bool enable)
868 node->SetBoolProperty(
"volumerendering", enable);
869 node->SetBoolProperty(
"volumerendering.uselod",
true);
873 node->SetBoolProperty(
"volumerendering", enable);
876 double val = this->
m_Controls.m_PreviewSlider->value();
882 void QmitkAdaptiveRegionGrowingToolGUI::UpdateVolumeRenderingThreshold(
int thValue)
886 typedef itk::BinaryThresholdImageFilter<InputImageType, InputImageType> ThresholdFilterType;
887 typedef itk::MaskImageFilter<InputImageType, InputImageType, InputImageType> MaskImageFilterType;
894 MITK_ERROR <<
"Missing data node for labeled segmentation image.";
902 thresholdFilter->SetInput(itkGrownImage);
903 thresholdFilter->SetInPlace(
false);
905 double sliderVal = this->
m_Controls.m_PreviewSlider->value();
907 if (m_CurrentRGDirectionIsUpwards)
909 threshold =
static_cast<PixelType
>(m_UPPERTHRESHOLD - sliderVal + 0.5);
911 thresholdFilter->SetLowerThreshold(threshold);
916 threshold = sliderVal - m_LOWERTHRESHOLD + 0.5;
919 thresholdFilter->SetUpperThreshold(threshold);
921 thresholdFilter->UpdateLargestPossibleRegion();
924 maskFilter->SetInput(itkGrownImage);
925 maskFilter->SetInPlace(
false);
926 maskFilter->SetMaskImage(thresholdFilter->GetOutput());
927 maskFilter->SetOutsideValue(0);
928 maskFilter->UpdateLargestPossibleRegion();
931 mitk::CastToMitkImage<InputImageType>(maskFilter->GetOutput(), mitkMaskedImage);
933 maskNode->
SetData(mitkMaskedImage);
938 m_UseVolumeRendering = on;
940 this->EnableVolumeRendering(on);
945 m_LOWERTHRESHOLD = lowerThreshold;
950 m_UPPERTHRESHOLD = upperThreshold;
957 if (node.IsNotNull())
959 node->SetVisibility(
false);
963 this->EnableVolumeRendering(
false);
964 m_Controls.m_cbVolumeRendering->setChecked(
false);
void Progress(unsigned int steps=1)
Sets the current amount of progress to current progress + steps.
mitk::ScalarType FastSinglePixelAccess(mitk::PixelType, mitk::Image::Pointer im, ImageDataItem *item, itk::Index< 3 > idx, mitk::ScalarType &val, int component=0)
virtual void Add(mitk::DataNode *node, const mitk::DataStorage::SetOfObjects *parents=nullptr)=0
Adds a DataNode containing a data object to its internal storage.
Data management class that handles 'was created by' relations.
itk::SmartPointer< Self > Pointer
Gives locked and index-based read access for a particular image part. The class provides several set-...
static BaseRenderer * GetInstance(vtkRenderWindow *renWin)
void SetSegmentationName(QString name)
static vtkRenderWindow * GetRenderWindowByName(const std::string &name)
bool IsIndexInside(const mitk::Point3D &index) const
Test whether the point p ((continous!)index coordinates in units) is inside the bounding box...
StatisticsHolderPointer GetStatistics() const
Returns a pointer to the ImageStatisticsHolder object that holds all statistics information for the i...
virtual void SetData(mitk::BaseData *baseData)
Set the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
ChannelDescriptor GetChannelDescriptor(int id=0) const
ImageFilter used for processing an image with an adaptive iterator (such as itkAdaptiveThresholdItera...
static ProgressBar * GetInstance()
static method to get the GUI dependent ProgressBar-instance so the methods for steps to do and progre...
Image::Pointer ImportItkImage(const itk::SmartPointer< ItkOutputImageType > &itkimage, const BaseGeometry *geometry=nullptr, bool update=true)
Imports an itk::Image (with a specific type) as an mitk::Image.Instantiates instance of ITKImageImpor...
void SetRangeMinMax(ScalarType min, ScalarType max)
The LevelWindow class Class to store level/window values.
virtual ScalarType GetScalarValueMin(int t=0, unsigned int component=0)
Get the minimum for scalar images. Recomputation performed only when necessary.
PixelType GetPixelType() const
Get the type of channel's elements.
DataType * GetNamedObject(const char *name) const
Convenience method to get the first data object of a given data type with a given name...
mitk::DataStorage::Pointer m_DataStorage
Data structure which stores a set of points. Superclass of mitk::Mesh.
itk::Image< double, 3 > InputImageType
#define mitkPixelTypeMultiplex3(function, ptype, param1, param2, param3)
static RenderingManager * GetInstance()
virtual ScalarType GetScalarValueMax(int t=0, unsigned int component=0)
Get the maximum for scalar images. Recomputation performed only when necessary.
Image class for storing images.
#define mitkPixelTypeMultiplex4(function, ptype, param1, param2, param3, param4)
void SetLevelWindowProperty(LevelWindowProperty::Pointer levelWindowProperty)
Sets an specific LevelWindowProperty, all changes will affect the image belonging to this property...
#define AccessByItk(mitkImage, itkImageTypeFunction)
Access a MITK image by an ITK image.
virtual unsigned int GetTimeStep() const
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
void SetAutoTopMostImage(bool autoTopMost, const DataNode *removedNode=nullptr)
(Re-)Initializes the LevelWindowManager by setting the topmost image. Use the removedNode parameter i...
#define AccessByItk_2(mitkImage, itkImageTypeFunction, arg1, arg2)
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
void SetLevelWindow(ScalarType level, ScalarType window, bool expandRangesIfNecessary=true)
virtual void Remove(const mitk::DataNode *node)=0
Removes node from the DataStorage.
mitk::DataNode * GetNamedNode(const char *name) const
Convenience method to get the first node with a given name.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
BaseGeometry Describes the geometry of a data object.
Class for nodes of the DataTree.
Class for defining the data type of pixels.
const TPixel & GetPixelByWorldCoordinates(mitk::Point3D position)
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.