diff --git a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp deleted file mode 100644 index 579561cfd0..0000000000 --- a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkAdaptiveRegionGrowingTool.h" -#include "mitkImage.h" -#include "mitkProperties.h" -#include "mitkToolManager.h" -// us -#include -#include -#include -#include - -namespace mitk -{ - MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, AdaptiveRegionGrowingTool, "AdaptiveRegionGrowingTool"); -} - -mitk::AdaptiveRegionGrowingTool::AdaptiveRegionGrowingTool() -{ - m_PointSetNode = mitk::DataNode::New(); - m_PointSetNode->GetPropertyList()->SetProperty("name", mitk::StringProperty::New("3D_Regiongrowing_Seedpoint")); - m_PointSetNode->GetPropertyList()->SetProperty("helper object", mitk::BoolProperty::New(true)); - m_PointSet = mitk::PointSet::New(); - m_PointSetNode->SetData(m_PointSet); -} - -mitk::AdaptiveRegionGrowingTool::~AdaptiveRegionGrowingTool() -{ -} - -bool mitk::AdaptiveRegionGrowingTool::CanHandle(const BaseData* referenceData, const BaseData* /*workingData*/) const -{ - if (referenceData == nullptr) - return false; - - auto *image = dynamic_cast(referenceData); - - if (image == nullptr) - return false; - - if (image->GetDimension() < 3) - return false; - - if (image->GetTimeSteps() > 1) //release quickfix for T28275 - return false; - - return true; -} - -const char **mitk::AdaptiveRegionGrowingTool::GetXPM() const -{ - return nullptr; -} - -const char *mitk::AdaptiveRegionGrowingTool::GetName() const -{ - return "Region Growing 3D"; -} - -us::ModuleResource mitk::AdaptiveRegionGrowingTool::GetIconResource() const -{ - us::Module *module = us::GetModuleContext()->GetModule(); - us::ModuleResource resource = module->GetResource("RegionGrowing_48x48.png"); - return resource; -} - -void mitk::AdaptiveRegionGrowingTool::Activated() -{ - Superclass::Activated(); - - if (!GetDataStorage()->Exists(m_PointSetNode)) - GetDataStorage()->Add(m_PointSetNode, GetWorkingData()); - m_SeedPointInteractor = mitk::SinglePointDataInteractor::New(); - m_SeedPointInteractor->LoadStateMachine("PointSet.xml"); - m_SeedPointInteractor->SetEventConfig("PointSetConfig.xml"); - m_SeedPointInteractor->SetDataNode(m_PointSetNode); -} - -void mitk::AdaptiveRegionGrowingTool::Deactivated() -{ - m_PointSet->Clear(); - GetDataStorage()->Remove(m_PointSetNode); - - Superclass::Deactivated(); -} - -void mitk::AdaptiveRegionGrowingTool::ConfirmSegmentation() -{ - this->GetToolManager()->ActivateTool(-1); -} - -mitk::DataNode *mitk::AdaptiveRegionGrowingTool::GetReferenceData() -{ - return this->GetToolManager()->GetReferenceData(0); -} - -mitk::DataStorage *mitk::AdaptiveRegionGrowingTool::GetDataStorage() -{ - return this->GetToolManager()->GetDataStorage(); -} - -mitk::DataNode *mitk::AdaptiveRegionGrowingTool::GetWorkingData() -{ - return this->GetToolManager()->GetWorkingData(0); -} - -mitk::DataNode::Pointer mitk::AdaptiveRegionGrowingTool::GetPointSetNode() -{ - return m_PointSetNode; -} diff --git a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h b/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h deleted file mode 100644 index 7924978442..0000000000 --- a/Modules/Segmentation/Interactions/mitkAdaptiveRegionGrowingTool.h +++ /dev/null @@ -1,128 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef mitkAdaptiveRegionGrowingTool_h_Included -#define mitkAdaptiveRegionGrowingTool_h_Included - -#include "mitkAutoSegmentationTool.h" -#include "mitkCommon.h" -#include "mitkDataStorage.h" -#include "mitkPointSet.h" -#include "mitkSinglePointDataInteractor.h" -#include - -namespace us -{ - class ModuleResource; -} - -namespace mitk -{ - /** - \brief Dummy Tool for AdaptiveRegionGrowingToolGUI to get Tool functionality for AdaptiveRegionGrowing. - The actual logic is implemented in QmitkAdaptiveRegionGrowingToolGUI. - - \ingroup ToolManagerEtAl - \sa mitk::Tool - \sa QmitkInteractiveSegmentation - - */ - class MITKSEGMENTATION_EXPORT AdaptiveRegionGrowingTool : public AutoSegmentationTool - { - public: - /** - * @brief mitkClassMacro - */ - mitkClassMacro(AdaptiveRegionGrowingTool, AutoSegmentationTool); - itkFactorylessNewMacro(Self); - itkCloneMacro(Self); - - bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override; - - /** - * @brief Get XPM - * @return nullptr - */ - const char **GetXPM() const override; - - /** - * @brief Get name - * @return name of the Tool - */ - const char *GetName() const override; - - /** - * @brief Get icon resource - * @return the resource Object of the Icon - */ - us::ModuleResource GetIconResource() const override; - - /** - * @brief Adds interactor for the seedpoint and creates a seedpoint if neccessary. - * - * - */ - void Activated() override; - - /** - * @brief Removes all set points and interactors. - * - * - */ - void Deactivated() override; - - /** - * @brief get pointset node - * @return the point set node - */ - virtual DataNode::Pointer GetPointSetNode(); - - /** - * @brief get reference data - * @return the current reference data. - */ - mitk::DataNode *GetReferenceData(); - - /** - * @brief Get working data - * @return a list of all working data. - */ - mitk::DataNode *GetWorkingData(); - - /** - * @brief Get datastorage - * @return the current data storage. - */ - mitk::DataStorage *GetDataStorage(); - - void ConfirmSegmentation(); - - protected: - /** - * @brief constructor - */ - AdaptiveRegionGrowingTool(); // purposely hidden - - /** - * @brief destructor - */ - ~AdaptiveRegionGrowingTool() override; - - private: - PointSet::Pointer m_PointSet; - SinglePointDataInteractor::Pointer m_SeedPointInteractor; - DataNode::Pointer m_PointSetNode; - }; - -} // namespace - -#endif diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp deleted file mode 100644 index ef35be95dc..0000000000 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkAutoSegmentationTool.h" -#include "mitkImage.h" -#include "mitkToolManager.h" -#include -#include - -mitk::AutoSegmentationTool::AutoSegmentationTool() : Tool("dummy"), m_OverwriteExistingSegmentation(false) -{ -} - -mitk::AutoSegmentationTool::AutoSegmentationTool(const char* interactorType, const us::Module* interactorModule) : Tool(interactorType, interactorModule), m_OverwriteExistingSegmentation(false) -{ -} - -mitk::AutoSegmentationTool::~AutoSegmentationTool() -{ -} - -void mitk::AutoSegmentationTool::Activated() -{ - Superclass::Activated(); - - m_NoneOverwriteTargetSegmentationNode = nullptr; -} - -void mitk::AutoSegmentationTool::Deactivated() -{ - m_NoneOverwriteTargetSegmentationNode = nullptr; - - Superclass::Deactivated(); -} - -const char *mitk::AutoSegmentationTool::GetGroup() const -{ - return "autoSegmentation"; -} - -mitk::Image::ConstPointer mitk::AutoSegmentationTool::GetImageByTimeStep(const mitk::Image* image, unsigned int timestep) -{ - return SelectImageByTimeStep(image, timestep); -} - -mitk::Image::Pointer mitk::AutoSegmentationTool::GetImageByTimeStep(mitk::Image* image, unsigned int timestep) -{ - return SelectImageByTimeStep(image, timestep); -} - -mitk::Image::ConstPointer mitk::AutoSegmentationTool::GetImageByTimePoint(const mitk::Image* image, TimePointType timePoint) -{ - return SelectImageByTimeStep(image, timePoint); -} - -void mitk::AutoSegmentationTool::SetOverwriteExistingSegmentation(bool overwrite) -{ - if (m_OverwriteExistingSegmentation != overwrite) - { - m_OverwriteExistingSegmentation = overwrite; - m_NoneOverwriteTargetSegmentationNode = nullptr; - } -} - -std::string mitk::AutoSegmentationTool::GetCurrentSegmentationName() -{ - if (this->GetToolManager()->GetWorkingData(0)) - return this->GetToolManager()->GetWorkingData(0)->GetName(); - else - return ""; -} - -mitk::DataNode *mitk::AutoSegmentationTool::GetTargetSegmentationNode() const -{ - mitk::DataNode::Pointer segmentationNode = this->GetToolManager()->GetWorkingData(0); - if (!m_OverwriteExistingSegmentation) - { - if (m_NoneOverwriteTargetSegmentationNode.IsNull()) - { - mitk::DataNode::Pointer refNode = this->GetToolManager()->GetReferenceData(0); - if (refNode.IsNull()) - { - // TODO create and use segmentation exceptions instead!! - MITK_ERROR << "No valid reference data!"; - return nullptr; - } - std::string nodename = refNode->GetName() + "_" + this->GetName(); - - const auto labelSetImage = dynamic_cast(segmentationNode->GetData()); - if (nullptr == labelSetImage) - { - //TODO: this part of the if statement is old legacy code and should be removed. - //Keept because I didn't want to break/rework to many things before - //the release 2022.04. Should be removed when the seg tool classes are streamlined and the - //multi data structure is the only one used in seg APIs and code. - - mitk::Color color; - color.SetRed(1); - color.SetBlue(0); - color.SetGreen(0); - //create a new segmentation node based on the current segmentation as template - m_NoneOverwriteTargetSegmentationNode = CreateEmptySegmentationNode(dynamic_cast(segmentationNode->GetData()), nodename, color); - } - else - { - auto clonedSegmentation = labelSetImage->Clone(); - m_NoneOverwriteTargetSegmentationNode = LabelSetImageHelper::CreateEmptySegmentationNode(nodename); - m_NoneOverwriteTargetSegmentationNode->SetData(clonedSegmentation); - } - } - segmentationNode = m_NoneOverwriteTargetSegmentationNode; - } - return segmentationNode; -} - -void mitk::AutoSegmentationTool::EnsureTargetSegmentationNodeInDataStorage() const -{ - auto targetNode = this->GetTargetSegmentationNode(); - if (!this->GetToolManager()->GetDataStorage()->Exists(targetNode)) - { - this->GetToolManager()->GetDataStorage()->Add(targetNode, this->GetToolManager()->GetReferenceData(0)); - } -} diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h deleted file mode 100644 index 8665208340..0000000000 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.h +++ /dev/null @@ -1,86 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef mitkAutoSegmentationTool_h_Included -#define mitkAutoSegmentationTool_h_Included - -#include "mitkCommon.h" -#include "mitkTool.h" -#include - -namespace mitk -{ - class Image; - - /** - \brief Superclass for tool that create a new segmentation without user interaction in render windows - - This class is undocumented. Ask the creator ($Author$) to supply useful comments. - */ - class MITKSEGMENTATION_EXPORT AutoSegmentationTool : public Tool - { - public: - mitkClassMacro(AutoSegmentationTool, Tool); - - void Activated() override; - void Deactivated() override; - - /** This function controls wether a confirmed segmentation should replace the old - * segmentation/working node (true) or if it should be stored as new and additional - * node (false). - */ - void SetOverwriteExistingSegmentation(bool overwrite); - - /** - * @brief Gets the name of the currently selected segmentation node - * @return the name of the segmentation node or an empty string if - * none is selected - */ - std::string GetCurrentSegmentationName(); - - /** - * @brief Depending on the selected mode either returns the currently selected segmentation node - * or (if overwrite mode is false) creates a new one from the selected reference data. - * @remark Please keep in mind that new created nodes are not automatically added to the data storage. - * Derived tools can call EnsureTargetSegmentationNodeInDataStorage to ensure it as soon as it is clear - * that the target segmentation node will be/is confirmed. - * @return a mitk::DataNode which contains a segmentation image - */ - virtual DataNode *GetTargetSegmentationNode() const; - - protected: - AutoSegmentationTool(); // purposely hidden - AutoSegmentationTool(const char* interactorType, const us::Module* interactorModule = nullptr); // purposely hidden - ~AutoSegmentationTool() override; - - const char *GetGroup() const override; - - /** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/ - static Image::ConstPointer GetImageByTimeStep(const Image* image, unsigned int timestep); - /** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/ - static Image::Pointer GetImageByTimeStep(Image* image, unsigned int timestep); - /** Helper that extracts the image for the passed time point, if the image has multiple time steps.*/ - static Image::ConstPointer GetImageByTimePoint(const Image* image, TimePointType timePoint); - - void EnsureTargetSegmentationNodeInDataStorage() const; - - bool m_OverwriteExistingSegmentation; - - private: - /**Contains the node returned by GetTargetSementationNode if m_OverwriteExistingSegmentation == false. Then - * GetTargetSegmentation generates a new target segmentation node.*/ - mutable DataNode::Pointer m_NoneOverwriteTargetSegmentationNode; - }; - -} // namespace - -#endif diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp index 2d9d777380..7c93d02c0c 100644 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp +++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp @@ -1,596 +1,633 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkAutoSegmentationWithPreviewTool.h" #include "mitkToolManager.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkLabelSetImage.h" #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkPadImageFilter.h" #include "mitkNodePredicateGeometry.h" #include "mitkSegTool2D.h" -mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews): m_LazyDynamicPreviews(lazyDynamicPreviews) +mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews): Tool("dummy"), m_LazyDynamicPreviews(lazyDynamicPreviews) { m_ProgressCommand = ToolCommand::New(); } -mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule) : AutoSegmentationTool(interactorType, interactorModule), m_LazyDynamicPreviews(lazyDynamicPreviews) +mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule) : Tool(interactorType, interactorModule), m_LazyDynamicPreviews(lazyDynamicPreviews) { m_ProgressCommand = ToolCommand::New(); } mitk::AutoSegmentationWithPreviewTool::~AutoSegmentationWithPreviewTool() { } void mitk::AutoSegmentationWithPreviewTool::SetMergeStyle(MultiLabelSegmentation::MergeStyle mergeStyle) { m_MergeStyle = mergeStyle; } void mitk::AutoSegmentationWithPreviewTool::SetOverwriteStyle(MultiLabelSegmentation::OverwriteStyle overwriteStyle) { m_OverwriteStyle = overwriteStyle; } bool mitk::AutoSegmentationWithPreviewTool::CanHandle(const BaseData* referenceData, const BaseData* workingData) const { if (!Superclass::CanHandle(referenceData, workingData)) return false; if (workingData == nullptr) return true; auto* labelSet = dynamic_cast(workingData); if (labelSet != nullptr) return true; auto* image = dynamic_cast(workingData); if (image == nullptr) return false; //if it is a normal image and not a label set image is used as working data //it must have the same pixel type as a label set. return MakeScalarPixelType< DefaultSegmentationDataType >() == image->GetPixelType(); } void mitk::AutoSegmentationWithPreviewTool::Activated() { Superclass::Activated(); this->GetToolManager()->RoiDataChanged += MessageDelegate(this, &AutoSegmentationWithPreviewTool::OnRoiDataChanged); this->GetToolManager()->SelectedTimePointChanged += MessageDelegate(this, &AutoSegmentationWithPreviewTool::OnTimePointChanged); m_ReferenceDataNode = this->GetToolManager()->GetReferenceData(0); m_SegmentationInputNode = m_ReferenceDataNode; m_LastTimePointOfUpdate = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); if (m_PreviewSegmentationNode.IsNull()) { m_PreviewSegmentationNode = DataNode::New(); m_PreviewSegmentationNode->SetProperty("color", ColorProperty::New(0.0, 1.0, 0.0)); m_PreviewSegmentationNode->SetProperty("name", StringProperty::New(std::string(this->GetName())+" preview")); m_PreviewSegmentationNode->SetProperty("opacity", FloatProperty::New(0.3)); m_PreviewSegmentationNode->SetProperty("binary", BoolProperty::New(true)); m_PreviewSegmentationNode->SetProperty("helper object", BoolProperty::New(true)); } if (m_SegmentationInputNode.IsNotNull()) { this->ResetPreviewNode(); this->InitiateToolByInput(); } else { this->GetToolManager()->ActivateTool(-1); } } void mitk::AutoSegmentationWithPreviewTool::Deactivated() { this->GetToolManager()->RoiDataChanged -= MessageDelegate(this, &AutoSegmentationWithPreviewTool::OnRoiDataChanged); this->GetToolManager()->SelectedTimePointChanged -= MessageDelegate(this, &AutoSegmentationWithPreviewTool::OnTimePointChanged); m_SegmentationInputNode = nullptr; m_ReferenceDataNode = nullptr; m_WorkingPlaneGeometry = nullptr; try { if (DataStorage *storage = this->GetToolManager()->GetDataStorage()) { storage->Remove(m_PreviewSegmentationNode); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch (...) { // don't care } if (m_PreviewSegmentationNode.IsNotNull()) { m_PreviewSegmentationNode->SetData(nullptr); } Superclass::Deactivated(); } void mitk::AutoSegmentationWithPreviewTool::ConfirmSegmentation() { bool labelChanged = this->EnsureUpToDateUserDefinedActiveLabel(); if ((m_LazyDynamicPreviews && m_CreateAllTimeSteps) || labelChanged) { // The tool should create all time steps but is currently in lazy mode, // thus ensure that a preview for all time steps is available. this->UpdatePreview(true); } CreateResultSegmentationFromPreview(); RenderingManager::GetInstance()->RequestUpdateAll(); if (!m_KeepActiveAfterAccept) { this->GetToolManager()->ActivateTool(-1); } } void mitk::AutoSegmentationWithPreviewTool::InitiateToolByInput() { //default implementation does nothing. //implement in derived classes to change behavior } mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetPreviewSegmentation() { if (m_PreviewSegmentationNode.IsNull()) { return nullptr; } return dynamic_cast(m_PreviewSegmentationNode->GetData()); } mitk::DataNode* mitk::AutoSegmentationWithPreviewTool::GetPreviewSegmentationNode() { return m_PreviewSegmentationNode; } const mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetSegmentationInput() const { if (m_SegmentationInputNode.IsNull()) { return nullptr; } return dynamic_cast(m_SegmentationInputNode->GetData()); } const mitk::Image* mitk::AutoSegmentationWithPreviewTool::GetReferenceData() const { if (m_ReferenceDataNode.IsNull()) { return nullptr; } return dynamic_cast(m_ReferenceDataNode->GetData()); } template void ClearBufferProcessing(ImageType* itkImage) { itkImage->FillBuffer(0); } void mitk::AutoSegmentationWithPreviewTool::ResetPreviewContentAtTimeStep(unsigned int timeStep) { auto previewImage = GetImageByTimeStep(this->GetPreviewSegmentation(), timeStep); if (nullptr != previewImage) { AccessByItk(previewImage, ClearBufferProcessing); } } void mitk::AutoSegmentationWithPreviewTool::ResetPreviewContent() { auto previewImage = this->GetPreviewSegmentation(); if (nullptr != previewImage) { auto castedPreviewImage = dynamic_cast(previewImage); if (nullptr == castedPreviewImage) mitkThrow() << "Application is on wrong state / invalid tool implementation. Preview image should always be of type LabelSetImage now."; castedPreviewImage->ClearBuffer(); } } void mitk::AutoSegmentationWithPreviewTool::ResetPreviewNode() { if (m_IsUpdating) { mitkThrow() << "Used tool is implemented incorrectly. ResetPreviewNode is called while preview update is ongoing. Check implementation!"; } itk::RGBPixel previewColor; previewColor[0] = 0.0f; previewColor[1] = 1.0f; previewColor[2] = 0.0f; const auto image = this->GetSegmentationInput(); if (nullptr != image) { LabelSetImage::ConstPointer workingImage = dynamic_cast(this->GetToolManager()->GetWorkingData(0)->GetData()); if (workingImage.IsNotNull()) { auto newPreviewImage = workingImage->Clone(); if (this->GetResetsToEmptyPreview()) { newPreviewImage->ClearBuffer(); } if (newPreviewImage.IsNull()) { MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image"; return; } m_PreviewSegmentationNode->SetData(newPreviewImage); // Let's paint the feedback node green... auto* activeLayer = newPreviewImage->GetActiveLabelSet(); auto* activeLabel = activeLayer->GetActiveLabel(); activeLabel->SetColor(previewColor); activeLayer->UpdateLookupTable(activeLabel->GetValue()); activeLabel->SetVisible(true); } else { Image::ConstPointer workingImageBin = dynamic_cast(this->GetToolManager()->GetWorkingData(0)->GetData()); if (workingImageBin.IsNotNull()) { Image::Pointer newPreviewImage; if (this->GetResetsToEmptyPreview()) { newPreviewImage = Image::New(); newPreviewImage->Initialize(workingImageBin); } else { auto newPreviewImage = workingImageBin->Clone(); } if (newPreviewImage.IsNull()) { MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image"; return; } m_PreviewSegmentationNode->SetData(newPreviewImage); } else { mitkThrow() << "Tool is an invalid state. Cannot setup preview node. Working data is an unsupported class and should have not been accepted by CanHandle()."; } } m_PreviewSegmentationNode->SetColor(previewColor); m_PreviewSegmentationNode->SetOpacity(0.5); int layer(50); m_ReferenceDataNode->GetIntProperty("layer", layer); m_PreviewSegmentationNode->SetIntProperty("layer", layer + 1); if (DataStorage *ds = this->GetToolManager()->GetDataStorage()) { if (!ds->Exists(m_PreviewSegmentationNode)) ds->Add(m_PreviewSegmentationNode, m_ReferenceDataNode); } } } void mitk::AutoSegmentationWithPreviewTool::TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep) { try { Image::ConstPointer sourceImageAtTimeStep = this->GetImageByTimeStep(sourceImage, timeStep); if (sourceImageAtTimeStep->GetPixelType() != destinationImage->GetPixelType()) { mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same pixel type. " << "Source pixel type: " << sourceImage->GetPixelType().GetTypeAsString() << "; destination pixel type: " << destinationImage->GetPixelType().GetTypeAsString(); } if (!Equal(*(sourceImage->GetGeometry(timeStep)), *(destinationImage->GetGeometry(timeStep)), NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_COORDINATE_PRECISION, NODE_PREDICATE_GEOMETRY_DEFAULT_CHECK_DIRECTION_PRECISION, false)) { mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same geometry."; } if (nullptr != this->GetWorkingPlaneGeometry()) { auto sourceSlice = SegTool2D::GetAffectedImageSliceAs2DImage(this->GetWorkingPlaneGeometry(), sourceImage, timeStep); SegTool2D::WriteBackSegmentationResult(this->GetTargetSegmentationNode(), m_WorkingPlaneGeometry, sourceSlice, timeStep); } else { //take care of the full segmentation volume auto sourceLSImage = dynamic_cast(sourceImage); auto destLSImage = dynamic_cast(destinationImage); TransferLabelContent(sourceLSImage, destLSImage, { {this->GetUserDefinedActiveLabel(),this->GetUserDefinedActiveLabel()} }, m_MergeStyle, m_OverwriteStyle, timeStep); } } catch (...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); throw; } } void mitk::AutoSegmentationWithPreviewTool::CreateResultSegmentationFromPreview() { const auto segInput = this->GetSegmentationInput(); auto previewImage = this->GetPreviewSegmentation(); if (nullptr != segInput && nullptr != previewImage) { DataNode::Pointer resultSegmentationNode = GetTargetSegmentationNode(); if (resultSegmentationNode.IsNotNull()) { const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); auto resultSegmentation = dynamic_cast(resultSegmentationNode->GetData()); // REMARK: the following code in this scope assumes that previewImage and resultSegmentation // are clones of the working image (segmentation provided to the tool). Therefore they have // the same time geometry. if (previewImage->GetTimeSteps() != resultSegmentation->GetTimeSteps()) { mitkThrow() << "Cannot perform threshold. Internal tool state is invalid." << " Preview segmentation and segmentation result image have different time geometries."; } if (m_CreateAllTimeSteps) { for (unsigned int timeStep = 0; timeStep < previewImage->GetTimeSteps(); ++timeStep) { this->TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep); } } else { const auto timeStep = resultSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint); this->TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep); } // since we are maybe working on a smaller image, pad it to the size of the original image if (m_ReferenceDataNode.GetPointer() != m_SegmentationInputNode.GetPointer()) { PadImageFilter::Pointer padFilter = PadImageFilter::New(); padFilter->SetInput(0, resultSegmentation); padFilter->SetInput(1, dynamic_cast(m_ReferenceDataNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); resultSegmentationNode->SetData(padFilter->GetOutput()); } - if (m_OverwriteExistingSegmentation) - { //if we overwrite the segmentation (and not just store it as a new result - //in the data storage) we update also the tool manager state. - this->GetToolManager()->SetWorkingData(resultSegmentationNode); - this->GetToolManager()->GetWorkingData(0)->Modified(); - } this->EnsureTargetSegmentationNodeInDataStorage(); } } } void mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged() { DataNode::ConstPointer node = this->GetToolManager()->GetRoiData(0); if (node.IsNotNull()) { MaskAndCutRoiImageFilter::Pointer roiFilter = MaskAndCutRoiImageFilter::New(); Image::Pointer image = dynamic_cast(m_SegmentationInputNode->GetData()); if (image.IsNull()) return; roiFilter->SetInput(image); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); DataNode::Pointer tmpNode = DataNode::New(); tmpNode->SetData(roiFilter->GetOutput()); m_SegmentationInputNode = tmpNode; } else m_SegmentationInputNode = m_ReferenceDataNode; this->ResetPreviewNode(); this->InitiateToolByInput(); this->UpdatePreview(); } void mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged() { if (m_IsTimePointChangeAware && m_PreviewSegmentationNode.IsNotNull() && m_SegmentationInputNode.IsNotNull()) { const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); const bool isStaticSegOnDynamicImage = m_PreviewSegmentationNode->GetData()->GetTimeSteps() == 1 && m_SegmentationInputNode->GetData()->GetTimeSteps() > 1; if (timePoint!=m_LastTimePointOfUpdate && (isStaticSegOnDynamicImage || m_LazyDynamicPreviews)) { //we only need to update either because we are lazzy //or because we have a static segmentation with a dynamic image this->UpdatePreview(); } } } bool mitk::AutoSegmentationWithPreviewTool::EnsureUpToDateUserDefinedActiveLabel() { bool labelChanged = true; const auto workingImage = dynamic_cast(this->GetToolManager()->GetWorkingData(0)->GetData()); if (const auto& labelSetImage = dynamic_cast(workingImage)) { // this is a fix for T28131 / T28986, which should be refactored if T28524 is being worked on auto newLabel = labelSetImage->GetActiveLabel(labelSetImage->GetActiveLayer())->GetValue(); labelChanged = newLabel != m_UserDefinedActiveLabel; m_UserDefinedActiveLabel = newLabel; } else { m_UserDefinedActiveLabel = 1; labelChanged = false; } return labelChanged; } void mitk::AutoSegmentationWithPreviewTool::UpdatePreview(bool ignoreLazyPreviewSetting) { const auto inputImage = this->GetSegmentationInput(); auto previewImage = this->GetPreviewSegmentation(); int progress_steps = 200; const auto workingImage = dynamic_cast(this->GetToolManager()->GetWorkingData(0)->GetData()); this->EnsureUpToDateUserDefinedActiveLabel(); this->CurrentlyBusy.Send(true); m_IsUpdating = true; this->UpdatePrepare(); const auto timePoint = RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); try { if (nullptr != inputImage && nullptr != previewImage) { m_ProgressCommand->AddStepsToDo(progress_steps); if (previewImage->GetTimeSteps() > 1 && (ignoreLazyPreviewSetting || !m_LazyDynamicPreviews)) { for (unsigned int timeStep = 0; timeStep < previewImage->GetTimeSteps(); ++timeStep) { Image::ConstPointer feedBackImage; Image::ConstPointer currentSegImage; auto previewTimePoint = previewImage->GetTimeGeometry()->TimeStepToTimePoint(timeStep); auto inputTimeStep = inputImage->GetTimeGeometry()->TimePointToTimeStep(previewTimePoint); if (nullptr != this->GetWorkingPlaneGeometry()) { //only extract a specific slice defined by the working plane as feedback image. feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImage(this->GetWorkingPlaneGeometry(), inputImage, inputTimeStep); currentSegImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), workingImage, previewTimePoint); } else { //work on the whole feedback image feedBackImage = this->GetImageByTimeStep(inputImage, inputTimeStep); currentSegImage = this->GetImageByTimePoint(workingImage, previewTimePoint); } this->DoUpdatePreview(feedBackImage, currentSegImage, previewImage, timeStep); } } else { Image::ConstPointer feedBackImage; Image::ConstPointer currentSegImage; if (nullptr != this->GetWorkingPlaneGeometry()) { feedBackImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), inputImage, timePoint); currentSegImage = SegTool2D::GetAffectedImageSliceAs2DImageByTimePoint(this->GetWorkingPlaneGeometry(), workingImage, timePoint); } else { feedBackImage = this->GetImageByTimePoint(inputImage, timePoint); currentSegImage = this->GetImageByTimePoint(workingImage, timePoint); } auto timeStep = previewImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); this->DoUpdatePreview(feedBackImage, currentSegImage, previewImage, timeStep); } RenderingManager::GetInstance()->RequestUpdateAll(); } } catch (itk::ExceptionObject & excep) { MITK_ERROR << "Exception caught: " << excep.GetDescription(); m_ProgressCommand->SetProgress(progress_steps); std::string msg = excep.GetDescription(); ErrorMessage.Send(msg); } catch (...) { m_ProgressCommand->SetProgress(progress_steps); m_IsUpdating = false; CurrentlyBusy.Send(false); throw; } this->UpdateCleanUp(); m_LastTimePointOfUpdate = timePoint; m_ProgressCommand->SetProgress(progress_steps); m_IsUpdating = false; CurrentlyBusy.Send(false); } bool mitk::AutoSegmentationWithPreviewTool::IsUpdating() const { return m_IsUpdating; } void mitk::AutoSegmentationWithPreviewTool::UpdatePrepare() { // default implementation does nothing //reimplement in derived classes for special behavior } void mitk::AutoSegmentationWithPreviewTool::UpdateCleanUp() { // default implementation does nothing //reimplement in derived classes for special behavior } mitk::TimePointType mitk::AutoSegmentationWithPreviewTool::GetLastTimePointOfUpdate() const { return m_LastTimePointOfUpdate; } + +const char* mitk::AutoSegmentationWithPreviewTool::GetGroup() const +{ + return "autoSegmentation"; +} + +mitk::Image::ConstPointer mitk::AutoSegmentationWithPreviewTool::GetImageByTimeStep(const mitk::Image* image, unsigned int timestep) +{ + return SelectImageByTimeStep(image, timestep); +} + +mitk::Image::Pointer mitk::AutoSegmentationWithPreviewTool::GetImageByTimeStep(mitk::Image* image, unsigned int timestep) +{ + return SelectImageByTimeStep(image, timestep); +} + +mitk::Image::ConstPointer mitk::AutoSegmentationWithPreviewTool::GetImageByTimePoint(const mitk::Image* image, TimePointType timePoint) +{ + return SelectImageByTimeStep(image, timePoint); +} + +void mitk::AutoSegmentationWithPreviewTool::EnsureTargetSegmentationNodeInDataStorage() const +{ + auto targetNode = this->GetTargetSegmentationNode(); + if (!this->GetToolManager()->GetDataStorage()->Exists(targetNode)) + { + this->GetToolManager()->GetDataStorage()->Add(targetNode, this->GetToolManager()->GetReferenceData(0)); + } +} + +std::string mitk::AutoSegmentationWithPreviewTool::GetCurrentSegmentationName() +{ + if (this->GetToolManager()->GetWorkingData(0)) + return this->GetToolManager()->GetWorkingData(0)->GetName(); + else + return ""; +} + + +mitk::DataNode* mitk::AutoSegmentationWithPreviewTool::GetTargetSegmentationNode() const +{ + return this->GetToolManager()->GetWorkingData(0); +} diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h index 09ec1d6634..1174b9de4f 100644 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h +++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.h @@ -1,225 +1,249 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef mitkAutoSegmentationWithPreviewTool_h_Included #define mitkAutoSegmentationWithPreviewTool_h_Included -#include "mitkAutoSegmentationTool.h" +#include "mitkTool.h" #include "mitkCommon.h" #include "mitkDataNode.h" #include "mitkToolCommand.h" #include namespace mitk { /** \brief Base class for any auto segmentation tool that provides a preview of the new segmentation. This tool class implements a lot basic logic to handle auto segmentation tools with preview, Time point and ROI support. Derived classes will ask to update the segmentation preview if needed (e.g. because the ROI or the current time point has changed) or because derived tools indicated the need to update themselves. This class also takes care to properly transfer a confirmed preview into the segementation result. \ingroup ToolManagerEtAl \sa mitk::Tool \sa QmitkInteractiveSegmentation */ - class MITKSEGMENTATION_EXPORT AutoSegmentationWithPreviewTool : public AutoSegmentationTool + class MITKSEGMENTATION_EXPORT AutoSegmentationWithPreviewTool : public Tool { public: - mitkClassMacro(AutoSegmentationWithPreviewTool, AutoSegmentationTool); + mitkClassMacro(AutoSegmentationWithPreviewTool, Tool); void Activated() override; void Deactivated() override; void ConfirmSegmentation(); itkSetMacro(CreateAllTimeSteps, bool); itkGetMacro(CreateAllTimeSteps, bool); itkBooleanMacro(CreateAllTimeSteps); itkSetMacro(KeepActiveAfterAccept, bool); itkGetMacro(KeepActiveAfterAccept, bool); itkBooleanMacro(KeepActiveAfterAccept); itkSetMacro(IsTimePointChangeAware, bool); itkGetMacro(IsTimePointChangeAware, bool); itkBooleanMacro(IsTimePointChangeAware); itkSetMacro(ResetsToEmptyPreview, bool); itkGetMacro(ResetsToEmptyPreview, bool); itkBooleanMacro(ResetsToEmptyPreview); /*itk macro was not used on purpose, to aviod the change of mtime.*/ void SetMergeStyle(MultiLabelSegmentation::MergeStyle mergeStyle); itkGetMacro(MergeStyle, MultiLabelSegmentation::MergeStyle); /*itk macro was not used on purpose, to aviod the change of mtime.*/ void SetOverwriteStyle(MultiLabelSegmentation::OverwriteStyle overwriteStyle); itkGetMacro(OverwriteStyle, MultiLabelSegmentation::OverwriteStyle); bool CanHandle(const BaseData* referenceData, const BaseData* workingData) const override; /** Triggers the actualization of the preview * @param ignoreLazyPreviewSetting If set true UpdatePreview will always * generate the preview for all time steps. If set to false, UpdatePreview * will regard the setting specified by the constructor. * To define the update generation for time steps implement DoUpdatePreview. * To alter what should be done directly before or after the update of the preview, * reimplement UpdatePrepare() or UpdateCleanUp().*/ void UpdatePreview(bool ignoreLazyPreviewSetting = false); /** Indicate if currently UpdatePreview is triggered (true) or not (false).*/ bool IsUpdating() const; + /** + * @brief Gets the name of the currently selected segmentation node + * @return the name of the segmentation node or an empty string if + * none is selected + */ + std::string GetCurrentSegmentationName(); + + /** + * @brief Returns the currently selected segmentation node + * @return a mitk::DataNode which contains a segmentation image + */ + virtual DataNode* GetTargetSegmentationNode() const; + protected: ToolCommand::Pointer m_ProgressCommand; + AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews = false); // purposely hidden + AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule = nullptr); // purposely hidden + + ~AutoSegmentationWithPreviewTool() override; + + const char* GetGroup() const override; + + /** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/ + static Image::ConstPointer GetImageByTimeStep(const Image* image, unsigned int timestep); + /** Helper that extracts the image for the passed timestep, if the image has multiple time steps.*/ + static Image::Pointer GetImageByTimeStep(Image* image, unsigned int timestep); + /** Helper that extracts the image for the passed time point, if the image has multiple time steps.*/ + static Image::ConstPointer GetImageByTimePoint(const Image* image, TimePointType timePoint); + + void EnsureTargetSegmentationNodeInDataStorage() const; + /** Member is always called if GetSegmentationInput() has changed * (e.g. because a new ROI was defined, or on activation) to give derived * classes the posibility to initiate their state accordingly. * Reimplement this function to implement special behavior. */ virtual void InitiateToolByInput(); /** This member function offers derived classes the possibility to alter what should happen directly before the update of the preview is performed. It is called by UpdatePreview. Default implementation does nothing.*/ virtual void UpdatePrepare(); /** This member function offers derived classes the possibility to alter what should happen directly after the update of the preview is performed. It is called by UpdatePreview. Default implementation does nothing.*/ virtual void UpdateCleanUp(); /** This function does the real work. Here the preview for a given * input image should be computed and stored in the also passed * preview image at the passed time step. * It also provides the current/old segmentation at the time point, * which can be used, if the preview depends on the the segmenation so far. */ virtual void DoUpdatePreview(const Image* inputAtTimeStep, const Image* oldSegAtTimeStep, Image* previewImage, TimeStepType timeStep) = 0; - AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews = false); // purposely hidden - AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews, const char* interactorType, const us::Module* interactorModule = nullptr); // purposely hidden - - ~AutoSegmentationWithPreviewTool() override; - /** Returns the image that contains the preview of the current segmentation. * Returns null if the node is not set or does not contain an image.*/ Image* GetPreviewSegmentation(); DataNode* GetPreviewSegmentationNode(); /** Returns the input that should be used for any segmentation/preview or tool update. * It is either the data of ReferenceDataNode itself or a part of it defined by a ROI mask * provided by the tool manager. Derived classes should regard this as the relevant * input data for any processing. * Returns null if the node is not set or does not contain an image.*/ const Image* GetSegmentationInput() const; /** Returns the image that is provided by the ReferenceDataNode. * Returns null if the node is not set or does not contain an image.*/ const Image* GetReferenceData() const; /** Resets the preview node so it is empty and ready to be filled by the tool @remark Calling this function will generate a new preview image, and the old might be invalidated. Therefore this function should not be used within the scope of UpdatePreview (m_IsUpdating == true).*/ void ResetPreviewNode(); /** Resets the complete content of the preview image. The instance of the preview image and its settings * stay the same.*/ void ResetPreviewContent(); /** Resets only the image content of the specified timeStep of the preview image. If the preview image or the specified time step does not exist, nothing happens.*/ void ResetPreviewContentAtTimeStep(unsigned int timeStep); TimePointType GetLastTimePointOfUpdate() const; itkGetConstMacro(UserDefinedActiveLabel, Label::PixelType); itkSetObjectMacro(WorkingPlaneGeometry, PlaneGeometry); itkGetConstObjectMacro(WorkingPlaneGeometry, PlaneGeometry); private: void TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep); void CreateResultSegmentationFromPreview(); void OnRoiDataChanged(); void OnTimePointChanged(); /**Internal helper that ensures that the stored active label is up to date. This is a fix for T28131 / T28986. It should be refactored if T28524 is being worked on. On the long run, the active label will be communicated/set by the user/toolmanager as a state of the tool and the tool should react accordingly (like it does for other external state changes). @return indicates if the label has changed (true) or not. */ bool EnsureUpToDateUserDefinedActiveLabel(); /** Node that containes the preview data generated and managed by this class or derived ones.*/ DataNode::Pointer m_PreviewSegmentationNode; /** The reference data recieved from ToolManager::GetReferenceData when tool was activated.*/ DataNode::Pointer m_ReferenceDataNode; /** Node that containes the data that should be used as input for any auto segmentation. It might * be the same like m_ReferenceDataNode (if no ROI is set) or a sub region (if ROI is set).*/ DataNode::Pointer m_SegmentationInputNode; /** Indicates if Accepting the threshold should transfer/create the segmentations of all time steps (true) or only of the currently selected timepoint (false).*/ bool m_CreateAllTimeSteps = false; /** Indicates if the tool should kept active after accepting the segmentation or not.*/ bool m_KeepActiveAfterAccept = false; /** Relevant if the working data / preview image has multiple time steps (dynamic segmentations). * This flag has to be set by derived classes accordingly to there way to generate dynamic previews. * If LazyDynamicPreview is true, the tool generates only the preview for the current time step. * Therefore it always has to update the preview if current time point has changed and it has to (re)compute * all timeframes if ConfirmSegmentation() is called.*/ bool m_LazyDynamicPreviews = false; bool m_IsTimePointChangeAware = true; /** Controls if ResetPreviewNode generates an empty content (true) or clones the current segmentation (false).*/ bool m_ResetsToEmptyPreview = false; TimePointType m_LastTimePointOfUpdate = 0.; bool m_IsUpdating = false; Label::PixelType m_UserDefinedActiveLabel = 1; /** This variable indicates if for the tool a working plane geometry is defined. * If a working plane is defined the tool will only work an the slice of the input * and the segmentation. Thus only the relevant input slice will be passed to * DoUpdatePreview(...) and only the relevant slice of the preview will be transfered when * ConfirmSegmentation() is called.*/ PlaneGeometry::Pointer m_WorkingPlaneGeometry; /** This variable controles how the label pixel content of the preview should be transfered into the segmentation- For more details of the behavior see documentation of MultiLabelSegmentation::MergeStyle. */ MultiLabelSegmentation::MergeStyle m_MergeStyle = MultiLabelSegmentation::MergeStyle::Replace; /** This variable controles how the label pixel content of the preview should be transfered into the segmentation- For more details of the behavior see documentation of MultiLabelSegmentation::OverwriteStyle. */ MultiLabelSegmentation::OverwriteStyle m_OverwriteStyle = MultiLabelSegmentation::OverwriteStyle::RegardLocks; }; } // namespace #endif diff --git a/Modules/Segmentation/files.cmake b/Modules/Segmentation/files.cmake index e8f1ecffb7..fd1107c5e9 100644 --- a/Modules/Segmentation/files.cmake +++ b/Modules/Segmentation/files.cmake @@ -1,110 +1,108 @@ set(CPP_FILES Algorithms/mitkCalculateSegmentationVolume.cpp Algorithms/mitkContourModelSetToImageFilter.cpp Algorithms/mitkContourSetToPointSetFilter.cpp Algorithms/mitkContourUtils.cpp Algorithms/mitkCorrectorAlgorithm.cpp Algorithms/mitkDiffImageApplier.cpp Algorithms/mitkDiffSliceOperation.cpp Algorithms/mitkDiffSliceOperationApplier.cpp Algorithms/mitkFeatureBasedEdgeDetectionFilter.cpp Algorithms/mitkImageLiveWireContourModelFilter.cpp Algorithms/mitkImageToContourFilter.cpp #Algorithms/mitkImageToContourModelFilter.cpp Algorithms/mitkImageToLiveWireContourFilter.cpp Algorithms/mitkManualSegmentationToSurfaceFilter.cpp Algorithms/mitkOtsuSegmentationFilter.cpp Algorithms/mitkSegmentationObjectFactory.cpp Algorithms/mitkShapeBasedInterpolationAlgorithm.cpp Algorithms/mitkShowSegmentationAsSmoothedSurface.cpp Algorithms/mitkShowSegmentationAsSurface.cpp Algorithms/mitkVtkImageOverwrite.cpp Controllers/mitkSegmentationInterpolationController.cpp Controllers/mitkToolManager.cpp Controllers/mitkSegmentationModuleActivator.cpp Controllers/mitkToolManagerProvider.cpp DataManagement/mitkContour.cpp DataManagement/mitkContourSet.cpp DataManagement/mitkExtrudedContour.cpp - Interactions/mitkAdaptiveRegionGrowingTool.cpp Interactions/mitkAddContourTool.cpp Interactions/mitkAutoCropTool.cpp - Interactions/mitkAutoSegmentationTool.cpp Interactions/mitkAutoSegmentationWithPreviewTool.cpp Interactions/mitkAutoMLSegmentationWithPreviewTool.cpp Interactions/mitkBinaryThresholdBaseTool.cpp Interactions/mitkBinaryThresholdTool.cpp Interactions/mitkBinaryThresholdULTool.cpp Interactions/mitkCalculateGrayValueStatisticsTool.cpp Interactions/mitkCalculateVolumetryTool.cpp Interactions/mitkContourModelInteractor.cpp Interactions/mitkContourModelLiveWireInteractor.cpp Interactions/mitkLiveWireTool2D.cpp Interactions/mitkContourTool.cpp Interactions/mitkCreateSurfaceTool.cpp Interactions/mitkDrawPaintbrushTool.cpp Interactions/mitkErasePaintbrushTool.cpp Interactions/mitkEraseRegionTool.cpp Interactions/mitkFeedbackContourTool.cpp Interactions/mitkFillRegionTool.cpp Interactions/mitkOtsuTool3D.cpp Interactions/mitkPaintbrushTool.cpp Interactions/mitkPixelManipulationTool.cpp Interactions/mitkRegionGrowingTool.cpp Interactions/mitkSegmentationsProcessingTool.cpp Interactions/mitkSetRegionTool.cpp Interactions/mitkSegTool2D.cpp Interactions/mitkSubtractContourTool.cpp Interactions/mitkTool.cpp Interactions/mitkToolCommand.cpp Interactions/mitkPickingTool.cpp Interactions/mitknnUnetTool.cpp Interactions/mitkSegmentationInteractor.cpp #SO Interactions/mitkProcessExecutor.cpp Rendering/mitkContourMapper2D.cpp Rendering/mitkContourSetMapper2D.cpp Rendering/mitkContourSetVtkMapper3D.cpp Rendering/mitkContourVtkMapper3D.cpp SegmentationUtilities/BooleanOperations/mitkBooleanOperation.cpp SegmentationUtilities/MorphologicalOperations/mitkMorphologicalOperations.cpp #Added from ML Controllers/mitkSliceBasedInterpolationController.cpp Algorithms/mitkSurfaceStampImageFilter.cpp ) set(RESOURCE_FILES Add_48x48.png Add_Cursor_32x32.png AI_48x48.png AI_Cursor_32x32.png Erase_48x48.png Erase_Cursor_32x32.png Fill_48x48.png Fill_Cursor_32x32.png LiveWire_48x48.png LiveWire_Cursor_32x32.png Otsu_48x48.png Paint_48x48.png Paint_Cursor_32x32.png Pick_48x48.png RegionGrowing_48x48.png RegionGrowing_Cursor_32x32.png Subtract_48x48.png Subtract_Cursor_32x32.png Threshold_48x48.png TwoThresholds_48x48.png Wipe_48x48.png Wipe_Cursor_32x32.png Interactions/dummy.xml Interactions/LiveWireTool.xml Interactions/PickingTool.xml Interactions/PressMoveRelease.xml Interactions/PressMoveReleaseAndPointSetting.xml Interactions/PressMoveReleaseWithCTRLInversion.xml Interactions/PressMoveReleaseWithCTRLInversionAllMouseMoves.xml Interactions/SegmentationToolsConfig.xml Interactions/ContourModelModificationConfig.xml Interactions/ContourModelModificationInteractor.xml ) diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp deleted file mode 100644 index 2b6853bb74..0000000000 --- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp +++ /dev/null @@ -1,1006 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -#include "QmitkAdaptiveRegionGrowingToolGUI.h" - -#include - -#include "mitkITKImageImport.h" -#include "mitkImageAccessByItk.h" -#include "mitkImageTimeSelector.h" -#include "mitkNodePredicateDataType.h" -#include "mitkProperties.h" -#include "mitkTransferFunctionProperty.h" - -#include "mitkImageStatisticsHolder.h" - -#include "itkMaskImageFilter.h" -#include "itkNumericTraits.h" -#include -#include -#include -#include - -#include "QmitkConfirmSegmentationDialog.h" -#include "itkOrImageFilter.h" -#include "mitkImageCast.h" - -#include "mitkImagePixelReadAccessor.h" -#include "mitkPixelTypeMultiplex.h" - -#include "mitkImageCast.h" - -MITK_TOOL_GUI_MACRO(, QmitkAdaptiveRegionGrowingToolGUI, "") - -QmitkAdaptiveRegionGrowingToolGUI::QmitkAdaptiveRegionGrowingToolGUI(QWidget *parent) - : QmitkToolGUI(), - m_DataStorage(nullptr), - m_UseVolumeRendering(false), - m_UpdateSuggestedThreshold(true), - m_SuggestedThValue(0.0) -{ - this->setParent(parent); - - m_Controls.setupUi(this); - - m_Controls.m_ThresholdSlider->setDecimals(1); - m_Controls.m_ThresholdSlider->setSpinBoxAlignment(Qt::AlignVCenter); - - m_Controls.m_PreviewSlider->setEnabled(false); - m_Controls.m_PreviewSlider->setSingleStep(0.5); - // Not yet available - // m_Controls.m_PreviewSlider->InvertedAppearance(true); - - //3D preview doesn't work: T24430. Postponed until reimplementation of segmentation - m_Controls.m_cbVolumeRendering->setVisible(false); - - this->CreateConnections(); - this->SetDataNodeNames("labeledRGSegmentation", "RGResult", "RGFeedbackSurface", "maskedSegmentation"); - - connect(this, SIGNAL(NewToolAssociated(mitk::Tool *)), this, SLOT(OnNewToolAssociated(mitk::Tool *))); -} - -QmitkAdaptiveRegionGrowingToolGUI::~QmitkAdaptiveRegionGrowingToolGUI() -{ - // Removing the observer of the PointSet node - if (m_RegionGrow3DTool->GetPointSetNode().IsNotNull()) - { - m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetAddObserverTag); - m_RegionGrow3DTool->GetPointSetNode()->GetData()->RemoveObserver(m_PointSetMoveObserverTag); - } - this->RemoveHelperNodes(); -} - -void QmitkAdaptiveRegionGrowingToolGUI::OnNewToolAssociated(mitk::Tool *tool) -{ - m_RegionGrow3DTool = dynamic_cast(tool); - if (m_RegionGrow3DTool.IsNotNull()) - { - SetInputImageNode(this->m_RegionGrow3DTool->GetReferenceData()); - this->m_DataStorage = this->m_RegionGrow3DTool->GetDataStorage(); - this->EnableControls(true); - - // Watch for point added or modified - itk::SimpleMemberCommand::Pointer pointAddedCommand = - itk::SimpleMemberCommand::New(); - pointAddedCommand->SetCallbackFunction(this, &QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded); - m_PointSetAddObserverTag = - m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetAddEvent(), pointAddedCommand); - m_PointSetMoveObserverTag = - m_RegionGrow3DTool->GetPointSetNode()->GetData()->AddObserver(mitk::PointSetMoveEvent(), pointAddedCommand); - } - else - { - this->EnableControls(false); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::RemoveHelperNodes() -{ - mitk::DataNode::Pointer imageNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - if (imageNode.IsNotNull()) - { - m_DataStorage->Remove(imageNode); - } - - mitk::DataNode::Pointer maskedSegmentationNode = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); - if (maskedSegmentationNode.IsNotNull()) - { - m_DataStorage->Remove(maskedSegmentationNode); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::CreateConnections() -{ - // Connecting GUI components - connect((QObject *)(m_Controls.m_pbRunSegmentation), SIGNAL(clicked()), this, SLOT(RunSegmentation())); - connect(m_Controls.m_PreviewSlider, SIGNAL(valueChanged(double)), this, SLOT(ChangeLevelWindow(double))); - connect((QObject *)(m_Controls.m_pbConfirmSegementation), SIGNAL(clicked()), this, SLOT(ConfirmSegmentation())); - connect( - m_Controls.m_ThresholdSlider, SIGNAL(maximumValueChanged(double)), this, SLOT(SetUpperThresholdValue(double))); - connect( - m_Controls.m_ThresholdSlider, SIGNAL(minimumValueChanged(double)), this, SLOT(SetLowerThresholdValue(double))); -} - -void QmitkAdaptiveRegionGrowingToolGUI::SetDataNodeNames(std::string labledSegmentation, - std::string binaryImage, - std::string surface, - std::string maskedSegmentation) -{ - m_NAMEFORLABLEDSEGMENTATIONIMAGE = labledSegmentation; - m_NAMEFORBINARYIMAGE = binaryImage; - m_NAMEFORSURFACE = surface; - m_NAMEFORMASKEDSEGMENTATION = maskedSegmentation; -} - -void QmitkAdaptiveRegionGrowingToolGUI::SetDataStorage(mitk::DataStorage *dataStorage) -{ - m_DataStorage = dataStorage; -} - -void QmitkAdaptiveRegionGrowingToolGUI::SetInputImageNode(mitk::DataNode *node) -{ - m_InputImageNode = node; - mitk::Image *inputImage = dynamic_cast(m_InputImageNode->GetData()); - if (inputImage) - { - mitk::ScalarType max = inputImage->GetStatistics()->GetScalarValueMax(); - mitk::ScalarType min = inputImage->GetStatistics()->GetScalarValueMin(); - m_Controls.m_ThresholdSlider->setMaximum(max); - m_Controls.m_ThresholdSlider->setMinimum(min); - // Just for initialization - m_Controls.m_ThresholdSlider->setMaximumValue(max); - m_Controls.m_ThresholdSlider->setMinimumValue(min); - } -} - -template -static void AccessPixel(mitk::PixelType /*ptype*/, mitk::Image* im, mitk::Point3D p, int& val) -{ - mitk::ImagePixelReadAccessor access(im); - val = access.GetPixelByWorldCoordinates(p); -} - -/**Overloaded const verison*/ -template -static void AccessPixel(mitk::PixelType /*ptype*/, const mitk::Image* im, mitk::Point3D p, int& val) -{ - mitk::ImagePixelReadAccessor access(im); - val = access.GetPixelByWorldCoordinates(p); -} - -void QmitkAdaptiveRegionGrowingToolGUI::OnPointAdded() -{ - if (m_RegionGrow3DTool.IsNull()) - return; - - mitk::DataNode *node = m_RegionGrow3DTool->GetPointSetNode(); - - if (node != nullptr) - { - mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData()); - - if (pointSet.IsNull()) - { - QMessageBox::critical(nullptr, "QmitkAdaptiveRegionGrowingToolGUI", "PointSetNode does not contain a pointset"); - return; - } - - m_Controls.m_lblSetSeedpoint->setText(""); - - const mitk::Image *image = dynamic_cast(m_InputImageNode->GetData()); - const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); - - auto image3D = GetImageByTimePoint(image, timePoint); - - if (nullptr == image3D) - { - MITK_WARN << "Cannot run segementation. Currently selected timepoint is not in the time bounds of the selected " - "reference image. Time point: " - << timePoint; - return; - } - - if (!pointSet->GetTimeGeometry()->IsValidTimePoint(timePoint)) - return; - - mitk::Point3D seedPoint = - pointSet - ->GetPointSet(static_cast(pointSet->GetTimeGeometry()->TimePointToTimeStep(timePoint))) - ->GetPoints() - ->ElementAt(0); - - if (image3D->GetGeometry()->IsInside(seedPoint)) - mitkPixelTypeMultiplex3( - AccessPixel, image3D->GetChannelDescriptor().GetPixelType(), image3D, seedPoint, m_SeedpointValue) else return; - - /* In this case the seedpoint is placed e.g. in the lung or bronchialtree - * The lowerFactor sets the windowsize depending on the regiongrowing direction - */ - m_CurrentRGDirectionIsUpwards = true; - if (m_SeedpointValue < -500) - { - m_CurrentRGDirectionIsUpwards = false; - } - - // Initializing the region by the area around the seedpoint - m_SeedPointValueMean = 0; - - itk::Index<3> currentIndex, runningIndex; - mitk::ScalarType pixelValues[125]; - unsigned int pos(0); - - image3D->GetGeometry(0)->WorldToIndex(seedPoint, currentIndex); - runningIndex = currentIndex; - - for (int i = runningIndex[0] - 2; i <= runningIndex[0] + 2; i++) - { - for (int j = runningIndex[1] - 2; j <= runningIndex[1] + 2; j++) - { - for (int k = runningIndex[2] - 2; k <= runningIndex[2] + 2; k++) - { - currentIndex[0] = i; - currentIndex[1] = j; - currentIndex[2] = k; - - if (image3D->GetGeometry()->IsIndexInside(currentIndex)) - { - int component = 0; - m_InputImageNode->GetIntProperty("Image.Displayed Component", component); - mitkPixelTypeMultiplex4(mitk::FastSinglePixelAccess, - image3D->GetChannelDescriptor().GetPixelType(), - image3D, - nullptr, - currentIndex, - pixelValues[pos]); - - pos++; - } - else - { - pixelValues[pos] = std::numeric_limits::min(); - pos++; - } - } - } - } - - // Now calculation mean of the pixelValues - // Now calculation mean of the pixelValues - unsigned int numberOfValues(0); - for (auto &pixelValue : pixelValues) - { - if (pixelValue > std::numeric_limits::min()) - { - m_SeedPointValueMean += pixelValue; - numberOfValues++; - } - } - m_SeedPointValueMean = m_SeedPointValueMean / numberOfValues; - - mitk::ScalarType var = 0; - if (numberOfValues > 1) - { - for (auto &pixelValue : pixelValues) - { - if (pixelValue > std::numeric_limits::min()) - { - var += (pixelValue - m_SeedPointValueMean) * (pixelValue - m_SeedPointValueMean); - } - } - var /= numberOfValues - 1; - } - mitk::ScalarType stdDev = sqrt(var); - - /* - * Here the upper- and lower threshold is calculated: - * The windowSize is 20% of the maximum range of the intensity values existing in the current image - * If the RG direction is upwards the lower TH is meanSeedValue-0.15*windowSize and upper TH is - * meanSeedValue+0.85*windowsSize - * if the RG direction is downwards the lower TH is meanSeedValue-0.85*windowSize and upper TH is - * meanSeedValue+0.15*windowsSize - */ - const auto timeStepOfImage = image->GetTimeGeometry()->TimePointToTimeStep(timePoint); - mitk::ScalarType min = image->GetStatistics()->GetScalarValueMin(timeStepOfImage); - mitk::ScalarType max = image->GetStatistics()->GetScalarValueMax(timeStepOfImage); - - mitk::ScalarType windowSize = max - min; - - windowSize = 0.15 * windowSize; - - if (m_CurrentRGDirectionIsUpwards) - { - m_LOWERTHRESHOLD = m_SeedPointValueMean - stdDev; - m_UPPERTHRESHOLD = m_SeedpointValue + windowSize; - if (m_UPPERTHRESHOLD > max) - m_UPPERTHRESHOLD = max; - m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD); - m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD); - } - else - { - m_UPPERTHRESHOLD = m_SeedPointValueMean; - if (m_SeedpointValue > m_SeedPointValueMean) - m_UPPERTHRESHOLD = m_SeedpointValue; - m_LOWERTHRESHOLD = m_SeedpointValue - windowSize; - if (m_LOWERTHRESHOLD < min) - m_LOWERTHRESHOLD = min; - m_Controls.m_ThresholdSlider->setMinimumValue(m_LOWERTHRESHOLD); - m_Controls.m_ThresholdSlider->setMaximumValue(m_UPPERTHRESHOLD); - } - } -} - -mitk::Image::ConstPointer QmitkAdaptiveRegionGrowingToolGUI::GetImageByTimePoint(const mitk::Image *image, - mitk::TimePointType timePoint) const -{ - if (nullptr == image) - return image; - - if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) - return nullptr; - - if (image->GetDimension() != 4) - return image; - - auto imageTimeSelector = mitk::ImageTimeSelector::New(); - - imageTimeSelector->SetInput(image); - imageTimeSelector->SetTimeNr(static_cast(image->GetTimeGeometry()->TimePointToTimeStep(timePoint))); - - imageTimeSelector->UpdateLargestPossibleRegion(); - - return imageTimeSelector->GetOutput(); -} - -void QmitkAdaptiveRegionGrowingToolGUI::RunSegmentation() -{ - if (m_InputImageNode.IsNull()) - { - QMessageBox::information(nullptr, "Adaptive Region Growing functionality", "Please specify the image in Datamanager!"); - return; - } - - mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode(); - - if (node.IsNull()) - { - QMessageBox::information(nullptr, "Adaptive Region Growing functionality", "Please insert a seed point inside the " - "image.\n\nFirst press the \"Define Seed " - "Point\" button,\nthen click left mouse " - "button inside the image."); - return; - } - - // safety if no pointSet or pointSet empty - mitk::PointSet::Pointer seedPointSet = dynamic_cast(node->GetData()); - if (seedPointSet.IsNull()) - { - m_Controls.m_pbRunSegmentation->setEnabled(true); - QMessageBox::information( - nullptr, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point."); - return; - } - - mitk::Image::Pointer orgImage = dynamic_cast(m_InputImageNode->GetData()); - - if (orgImage.IsNotNull()) - { - const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); - - if (!seedPointSet->GetTimeGeometry()->IsValidTimePoint(timePoint)) - mitkThrow() << "Point set is not defined for specified time point. Time point: " << timePoint; - - int timeStep = static_cast(seedPointSet->GetTimeGeometry()->TimePointToTimeStep(timePoint)); - - if (!(seedPointSet->GetSize(timeStep))) - { - m_Controls.m_pbRunSegmentation->setEnabled(true); - QMessageBox::information( - nullptr, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point."); - return; - } - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - - mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet(timeStep)->GetPoints()->Begin().Value(); - - auto image3D = GetImageByTimePoint(orgImage, timePoint); - - if (image3D.IsNotNull()) - { - // QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); //set the cursor to waiting - AccessByItk_2(image3D, StartRegionGrowing, image3D->GetGeometry(), seedPoint); - // QApplication::restoreOverrideCursor();//reset cursor - } - else - { - QApplication::restoreOverrideCursor(); // reset cursor - QMessageBox::information( - nullptr, "Adaptive Region Growing functionality", "Only images of dimension 3 or 4 can be processed!"); - return; - } - } - EnableControls(true); // Segmentation ran successfully, so enable all controls. - node->SetVisibility(true); - QApplication::restoreOverrideCursor(); // reset cursor -} - -template -void QmitkAdaptiveRegionGrowingToolGUI::StartRegionGrowing(const itk::Image *itkImage, - const mitk::BaseGeometry *imageGeometry, - const mitk::PointSet::PointType seedPoint) -{ - typedef itk::Image InputImageType; - typedef typename InputImageType::IndexType IndexType; - typedef itk::ConnectedAdaptiveThresholdImageFilter RegionGrowingFilterType; - typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); - typedef itk::BinaryThresholdImageFilter ThresholdFilterType; - typedef itk::MaskImageFilter MaskImageFilterType; - - if (!imageGeometry->IsInside(seedPoint)) - { - QApplication::restoreOverrideCursor(); // reset cursor to be able to click ok with the regular mouse cursor - QMessageBox::information(nullptr, - "Segmentation functionality", - "The seed point is outside of the image! Please choose a position inside the image!"); - return; - } - - IndexType seedIndex; - imageGeometry->WorldToIndex(seedPoint, seedIndex); // convert world coordinates to image indices - - if (m_SeedpointValue > m_UPPERTHRESHOLD || m_SeedpointValue < m_LOWERTHRESHOLD) - { - QApplication::restoreOverrideCursor(); // reset cursor to be able to click ok with the regular mouse cursor - QMessageBox::information( - nullptr, - "Segmentation functionality", - "The seed point is outside the defined thresholds! Please set a new seed point or adjust the thresholds."); - MITK_INFO << "Mean: " << m_SeedPointValueMean; - return; - } - - // Setting the direction of the regiongrowing. For dark structures e.g. the lung the regiongrowing - // is performed starting at the upper value going to the lower one - regionGrower->SetGrowingDirectionIsUpwards(m_CurrentRGDirectionIsUpwards); - regionGrower->SetInput(itkImage); - regionGrower->AddSeed(seedIndex); - // In some cases we have to subtract 1 for the lower threshold and add 1 to the upper. - // Otherwise no region growing is done. Maybe a bug in the ConnectiveAdaptiveThresholdFilter - mitk::ScalarType maxPixelValue = m_Controls.m_ThresholdSlider->maximum(); - mitk::ScalarType minPixelValue = m_Controls.m_ThresholdSlider->minimum(); - - if ((m_LOWERTHRESHOLD - minPixelValue) >= 1) - { - regionGrower->SetLower(m_LOWERTHRESHOLD - 1); - } - else - { - regionGrower->SetLower(m_LOWERTHRESHOLD); - } - - if ((maxPixelValue - m_UPPERTHRESHOLD) >= 1) - { - regionGrower->SetUpper(m_UPPERTHRESHOLD + 1); - } - else - { - regionGrower->SetUpper(m_UPPERTHRESHOLD); - } - - - try - { - regionGrower->Update(); - } - catch (itk::ExceptionObject &exc) - { - QMessageBox errorInfo; - errorInfo.setWindowTitle("Adaptive RG Segmentation Functionality"); - errorInfo.setIcon(QMessageBox::Critical); - errorInfo.setText("An error occurred during region growing!"); - errorInfo.setDetailedText(exc.what()); - errorInfo.exec(); - return; // can't work - } - catch (...) - { - QMessageBox::critical(nullptr, "Adaptive RG Segmentation Functionality", "An error occurred during region growing!"); - return; - } - - mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput())->Clone(); - // initialize slider - m_Controls.m_PreviewSlider->setMinimum(m_LOWERTHRESHOLD); - - mitk::ScalarType max = m_SeedpointValue + resultImage->GetStatistics()->GetScalarValueMax(); - if (max < m_UPPERTHRESHOLD) - m_Controls.m_PreviewSlider->setMaximum(max); - else - m_Controls.m_PreviewSlider->setMaximum(m_UPPERTHRESHOLD); - - this->m_DetectedLeakagePoint = regionGrower->GetLeakagePoint(); - - if (m_CurrentRGDirectionIsUpwards) - { - m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean - 1); - } - else - { - m_Controls.m_PreviewSlider->setValue(m_SeedPointValueMean + 1); - } - this->m_SliderInitialized = true; - - // create new node and then delete the old one if there is one - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - newNode->SetData(resultImage); - - // set some properties - newNode->SetProperty("name", mitk::StringProperty::New(m_NAMEFORLABLEDSEGMENTATIONIMAGE)); - newNode->SetProperty("helper object", mitk::BoolProperty::New(true)); - newNode->SetProperty("color", mitk::ColorProperty::New(0.0, 1.0, 0.0)); - newNode->SetProperty("layer", mitk::IntProperty::New(1)); - newNode->SetProperty("opacity", mitk::FloatProperty::New(0.7)); - - // delete the old image, if there was one: - mitk::DataNode::Pointer binaryNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - m_DataStorage->Remove(binaryNode); - - // now add result to data tree - m_DataStorage->Add(newNode, m_InputImageNode); - - typename InputImageType::Pointer inputImageItk; - mitk::CastToItkImage(resultImage, inputImageItk); - // volume rendering preview masking - typename ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); - thresholdFilter->SetInput(inputImageItk); - thresholdFilter->SetInsideValue(1); - thresholdFilter->SetOutsideValue(0); - - double sliderVal = this->m_Controls.m_PreviewSlider->value(); - if (m_CurrentRGDirectionIsUpwards) - { - thresholdFilter->SetLowerThreshold(sliderVal); - thresholdFilter->SetUpperThreshold(itk::NumericTraits::max()); - } - else - { - thresholdFilter->SetLowerThreshold(itk::NumericTraits::NonpositiveMin()); - thresholdFilter->SetUpperThreshold(sliderVal); - } - thresholdFilter->SetInPlace(false); - - typename MaskImageFilterType::Pointer maskFilter = MaskImageFilterType::New(); - maskFilter->SetInput(inputImageItk); - maskFilter->SetInPlace(false); - maskFilter->SetMaskImage(thresholdFilter->GetOutput()); - maskFilter->SetOutsideValue(0); - maskFilter->UpdateLargestPossibleRegion(); - - mitk::Image::Pointer mitkMask; - mitk::CastToMitkImage(maskFilter->GetOutput(), mitkMask); - mitk::DataNode::Pointer maskedNode = mitk::DataNode::New(); - maskedNode->SetData(mitkMask); - - // set some properties - maskedNode->SetProperty("name", mitk::StringProperty::New(m_NAMEFORMASKEDSEGMENTATION)); - maskedNode->SetProperty("helper object", mitk::BoolProperty::New(true)); - maskedNode->SetProperty("color", mitk::ColorProperty::New(0.0, 1.0, 0.0)); - maskedNode->SetProperty("layer", mitk::IntProperty::New(1)); - maskedNode->SetProperty("opacity", mitk::FloatProperty::New(0.0)); - - // delete the old image, if there was one: - mitk::DataNode::Pointer deprecatedMask = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); - m_DataStorage->Remove(deprecatedMask); - - // now add result to data tree - m_DataStorage->Add(maskedNode, m_InputImageNode); - - this->InitializeLevelWindow(); - - if (m_UseVolumeRendering) - this->EnableVolumeRendering(true); - - m_UpdateSuggestedThreshold = true; // reset first stored threshold value - // Setting progress to finished - mitk::ProgressBar::GetInstance()->Progress(357); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -void QmitkAdaptiveRegionGrowingToolGUI::InitializeLevelWindow() -{ - // get the preview from the datatree - mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - - mitk::LevelWindow tempLevelWindow; - newNode->GetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); - - mitk::ScalarType *level = new mitk::ScalarType(0.0); - mitk::ScalarType *window = new mitk::ScalarType(1.0); - - int upper; - if (m_CurrentRGDirectionIsUpwards) - { - upper = m_UPPERTHRESHOLD - m_SeedpointValue; - } - else - { - upper = m_SeedpointValue - m_LOWERTHRESHOLD; - } - - tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper)); - - // get the suggested threshold from the detected leakage-point and adjust the slider - - if (m_CurrentRGDirectionIsUpwards) - { - this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue); - *level = m_UPPERTHRESHOLD - (m_SeedpointValue) + 0.5; - } - else - { - this->m_Controls.m_PreviewSlider->setValue(m_SeedpointValue); - *level = (m_SeedpointValue)-m_LOWERTHRESHOLD + 0.5; - } - - tempLevelWindow.SetLevelWindow(*level, *window); - newNode->SetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); - // update the widgets - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - - m_SliderInitialized = true; - - // inquiry need to fix bug#1828 - static int lastSliderPosition = 0; - if ((this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1) == lastSliderPosition) - { - this->ChangeLevelWindow(lastSliderPosition); - } - lastSliderPosition = this->m_SeedpointValue + this->m_DetectedLeakagePoint - 1; - - if (m_UseVolumeRendering) - this->UpdateVolumeRenderingThreshold((int)(*level + 0.5)); // lower threshold for labeled image -} - -void QmitkAdaptiveRegionGrowingToolGUI::ChangeLevelWindow(double newValue) -{ - if (m_SliderInitialized) - { - // do nothing, if no preview exists - mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - if (newNode.IsNull()) - return; - - mitk::LevelWindow tempLevelWindow; - - newNode->GetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); // get the levelWindow associated with the preview - - mitk::ScalarType level; // = this->m_UPPERTHRESHOLD - newValue + 0.5; - mitk::ScalarType *window = new mitk::ScalarType(1); - - // adjust the levelwindow according to the position of the slider (newvalue) - if (m_CurrentRGDirectionIsUpwards) - { - level = m_UPPERTHRESHOLD - newValue + 0.5; - tempLevelWindow.SetLevelWindow(level, *window); - } - else - { - level = newValue - m_LOWERTHRESHOLD + 0.5; - tempLevelWindow.SetLevelWindow(level, *window); - } - - newNode->SetLevelWindow(tempLevelWindow, nullptr, "levelwindow"); - - if (m_UseVolumeRendering) - this->UpdateVolumeRenderingThreshold((int)(level - 0.5)); // lower threshold for labeled image - - newNode->SetVisibility(true); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::DecreaseSlider() -{ - // moves the slider one step to the left, when the "-"-button is pressed - if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->minimum()) - { - int newValue = this->m_Controls.m_PreviewSlider->value() - 1; - this->ChangeLevelWindow(newValue); - this->m_Controls.m_PreviewSlider->setValue(newValue); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::IncreaseSlider() -{ - // moves the slider one step to the right, when the "+"-button is pressed - if (this->m_Controls.m_PreviewSlider->value() != this->m_Controls.m_PreviewSlider->maximum()) - { - int newValue = this->m_Controls.m_PreviewSlider->value() + 1; - this->ChangeLevelWindow(newValue); - this->m_Controls.m_PreviewSlider->setValue(newValue); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::ConfirmSegmentation() -{ - // get image node - if (m_InputImageNode.IsNull()) - { - QMessageBox::critical(nullptr, "Adaptive region growing functionality", "Please specify the image in Datamanager!"); - return; - } - // get image data - mitk::Image::Pointer orgImage = dynamic_cast(m_InputImageNode->GetData()); - if (orgImage.IsNull()) - { - QMessageBox::critical(nullptr, "Adaptive region growing functionality", "No Image found!"); - return; - } - // get labeled segmentation - mitk::Image::Pointer labeledSeg = - (mitk::Image *)m_DataStorage->GetNamedObject(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - if (labeledSeg.IsNull()) - { - QMessageBox::critical(nullptr, "Adaptive region growing functionality", "No Segmentation Preview found!"); - return; - } - - mitk::DataNode::Pointer newNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - if (newNode.IsNull()) - return; - - QmitkConfirmSegmentationDialog dialog; - QString segName = QString::fromStdString(m_RegionGrow3DTool->GetCurrentSegmentationName()); - - dialog.SetSegmentationName(segName); - int result = dialog.exec(); - - switch (result) - { - case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION: - m_RegionGrow3DTool->SetOverwriteExistingSegmentation(false); - break; - case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION: - m_RegionGrow3DTool->SetOverwriteExistingSegmentation(true); - break; - case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION: - return; - } - - mitk::Image::Pointer img = dynamic_cast(newNode->GetData()); - AccessByItk(img, ITKThresholding); - - // disable volume rendering preview after the segmentation node was created - this->EnableVolumeRendering(false); - newNode->SetVisibility(false); - m_Controls.m_cbVolumeRendering->setChecked(false); - // TODO disable slider etc... - - if (m_RegionGrow3DTool.IsNotNull()) - { - m_RegionGrow3DTool->ConfirmSegmentation(); - } -} - -template -void QmitkAdaptiveRegionGrowingToolGUI::ITKThresholding(itk::Image *itkImage) -{ - mitk::Image::Pointer originalSegmentation = - dynamic_cast(this->m_RegionGrow3DTool->GetTargetSegmentationNode()->GetData()); - - const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); - - if (!originalSegmentation->GetTimeGeometry()->IsValidTimePoint(timePoint)) - mitkThrow() << "Segmentation is not defined for specified time point. Time point: " << timePoint; - - int timeStep = static_cast(originalSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint)); - - - if (originalSegmentation) - { - typedef itk::Image InputImageType; - typedef itk::Image SegmentationType; - - // select single 3D volume if we have more than one time step - typename SegmentationType::Pointer originalSegmentationInITK = SegmentationType::New(); - if (originalSegmentation->GetTimeGeometry()->CountTimeSteps() > 1) - { - mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New(); - timeSelector->SetInput(originalSegmentation); - timeSelector->SetTimeNr(timeStep); - timeSelector->UpdateLargestPossibleRegion(); - CastToItkImage(timeSelector->GetOutput(), originalSegmentationInITK); - } - else // use original - { - CastToItkImage(originalSegmentation, originalSegmentationInITK); - } - - // Fill current preiview image in segmentation image - originalSegmentationInITK->FillBuffer(0); - itk::ImageRegionIterator itOutput(originalSegmentationInITK, - originalSegmentationInITK->GetLargestPossibleRegion()); - itk::ImageRegionIterator itInput(itkImage, itkImage->GetLargestPossibleRegion()); - itOutput.GoToBegin(); - itInput.GoToBegin(); - - // calculate threhold from slider value - int currentTreshold = 0; - if (m_CurrentRGDirectionIsUpwards) - { - currentTreshold = m_UPPERTHRESHOLD - m_Controls.m_PreviewSlider->value() + 1; - } - else - { - currentTreshold = m_Controls.m_PreviewSlider->value() - m_LOWERTHRESHOLD; - } - - // iterate over image and set pixel in segmentation according to thresholded labeled image - while (!itOutput.IsAtEnd() && !itInput.IsAtEnd()) - { - // Use threshold slider to determine if pixel is set to 1 - if (itInput.Value() != 0 && itInput.Value() >= static_cast::PixelType>(currentTreshold)) - { - itOutput.Set(1); - } - - ++itOutput; - ++itInput; - } - - // combine current working segmentation image with our region growing result - originalSegmentation->SetVolume((void *)(originalSegmentationInITK->GetPixelContainer()->GetBufferPointer()), - timeStep); - - originalSegmentation->Modified(); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - } -} - -void QmitkAdaptiveRegionGrowingToolGUI::EnableControls(bool enable) -{ - if (m_RegionGrow3DTool.IsNull()) - return; - - // Check if seed point is already set, if not leave RunSegmentation disabled - // if even m_DataStorage is nullptr leave node nullptr - mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode(); - if (node.IsNull()) - { - this->m_Controls.m_pbRunSegmentation->setEnabled(false); - } - else - { - this->m_Controls.m_pbRunSegmentation->setEnabled(enable); - } - - // Check if a segmentation exists, if not leave segmentation dependent disabled. - // if even m_DataStorage is nullptr leave node nullptr - node = m_DataStorage ? m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE) : nullptr; - if (node.IsNull()) - { - this->m_Controls.m_PreviewSlider->setEnabled(false); - this->m_Controls.m_pbConfirmSegementation->setEnabled(false); - } - else - { - this->m_Controls.m_PreviewSlider->setEnabled(enable); - this->m_Controls.m_pbConfirmSegementation->setEnabled(enable); - } - - this->m_Controls.m_cbVolumeRendering->setEnabled(enable); -} - -void QmitkAdaptiveRegionGrowingToolGUI::EnableVolumeRendering(bool enable) -{ - mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); - - if (node.IsNull()) - return; - - node->SetBoolProperty("volumerendering", enable); - - double val = this->m_Controls.m_PreviewSlider->value(); - this->ChangeLevelWindow(val); - - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -void QmitkAdaptiveRegionGrowingToolGUI::UpdateVolumeRenderingThreshold(int) -{ - typedef short PixelType; - typedef itk::Image InputImageType; - typedef itk::BinaryThresholdImageFilter ThresholdFilterType; - typedef itk::MaskImageFilter MaskImageFilterType; - - mitk::DataNode::Pointer grownImageNode = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - mitk::Image::Pointer grownImage = dynamic_cast(grownImageNode->GetData()); - - if (!grownImage) - { - MITK_ERROR << "Missing data node for labeled segmentation image."; - return; - } - - InputImageType::Pointer itkGrownImage; - mitk::CastToItkImage(grownImage, itkGrownImage); - - ThresholdFilterType::Pointer thresholdFilter = ThresholdFilterType::New(); - thresholdFilter->SetInput(itkGrownImage); - thresholdFilter->SetInPlace(false); - - double sliderVal = this->m_Controls.m_PreviewSlider->value(); - PixelType threshold = itk::NumericTraits::min(); - if (m_CurrentRGDirectionIsUpwards) - { - threshold = static_cast(m_UPPERTHRESHOLD - sliderVal + 0.5); - - thresholdFilter->SetLowerThreshold(threshold); - thresholdFilter->SetUpperThreshold(itk::NumericTraits::max()); - } - else - { - threshold = sliderVal - m_LOWERTHRESHOLD + 0.5; - - thresholdFilter->SetLowerThreshold(itk::NumericTraits::min()); - thresholdFilter->SetUpperThreshold(threshold); - } - thresholdFilter->UpdateLargestPossibleRegion(); - - MaskImageFilterType::Pointer maskFilter = MaskImageFilterType::New(); - maskFilter->SetInput(itkGrownImage); - maskFilter->SetInPlace(false); - maskFilter->SetMaskImage(thresholdFilter->GetOutput()); - maskFilter->SetOutsideValue(0); - maskFilter->UpdateLargestPossibleRegion(); - - mitk::Image::Pointer mitkMaskedImage; - mitk::CastToMitkImage(maskFilter->GetOutput(), mitkMaskedImage); - mitk::DataNode::Pointer maskNode = m_DataStorage->GetNamedNode(m_NAMEFORMASKEDSEGMENTATION); - maskNode->SetData(mitkMaskedImage); -} - -void QmitkAdaptiveRegionGrowingToolGUI::UseVolumeRendering(bool on) -{ - m_UseVolumeRendering = on; - - this->EnableVolumeRendering(on); -} - -void QmitkAdaptiveRegionGrowingToolGUI::SetLowerThresholdValue(double lowerThreshold) -{ - m_LOWERTHRESHOLD = lowerThreshold; -} - -void QmitkAdaptiveRegionGrowingToolGUI::SetUpperThresholdValue(double upperThreshold) -{ - m_UPPERTHRESHOLD = upperThreshold; -} - -void QmitkAdaptiveRegionGrowingToolGUI::Deactivated() -{ - // make the segmentation preview node invisible - mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE); - if (node.IsNotNull()) - { - node->SetVisibility(false); - } - - // disable volume rendering preview after the segmentation node was created - this->EnableVolumeRendering(false); - m_Controls.m_cbVolumeRendering->setChecked(false); -} - -void QmitkAdaptiveRegionGrowingToolGUI::Activated() -{ -} diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h deleted file mode 100644 index 79f848ea27..0000000000 --- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h +++ /dev/null @@ -1,229 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -#ifndef QMITK_QmitkAdaptiveRegionGrowingToolGUI_H -#define QMITK_QmitkAdaptiveRegionGrowingToolGUI_H - -#include "itkImage.h" -#include "mitkDataStorage.h" -#include "mitkGeometry3D.h" -#include "mitkPointSet.h" - -#include "qwidget.h" -#include "ui_QmitkAdaptiveRegionGrowingToolGUIControls.h" - -#include - -#include "QmitkToolGUI.h" - -#include "mitkAdaptiveRegionGrowingTool.h" - -class DataNode; -class QmitkAdaptiveRegionGrowingToolGUIControls; - -/*! -* -* \brief QmitkAdaptiveRegionGrowingToolGUI -* -* Adaptive Region Growing View class of the segmentation. -* -*/ - -class MITKSEGMENTATIONUI_EXPORT QmitkAdaptiveRegionGrowingToolGUI : public QmitkToolGUI -{ - Q_OBJECT - -public: - /** - * @brief mitkClassMacro - */ - mitkClassMacro(QmitkAdaptiveRegionGrowingToolGUI, QmitkToolGUI); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - QmitkAdaptiveRegionGrowingToolGUI(QWidget *parent = nullptr); - - /** \brief Method to create the connections for the component. This Method is obligatory even if no connections is - * needed*/ - virtual void CreateConnections(); - - ///** \brief Method to set the default data storage.*/ - virtual void SetDataStorage(mitk::DataStorage *dataStorage); - - /** - * @brief Method to set the name of a data node. - * @param labledSegmentation Name of the labeled segmentation - * @param binaryImage Name of the binary image - * @param surface Name of the surface - * @param maskedSegmentation - */ - void SetDataNodeNames(std::string labledSegmentation, - std::string binaryImage, - /*std::string vesselTree,*/ std::string surface, - std::string maskedSegmentation); - - /** - * @brief Method to enable/disable controls for region growing - * - * This method checks if a seed point is set and a segmentation exists. - * @param enable enable/disable controls - */ - void EnableControls(bool enable); - - /** - * @brief Method to set the input image node - * @param node data node - */ - void SetInputImageNode(mitk::DataNode *node); - - void Deactivated(); - void Activated(); - - /** - * @brief The created GUI from the .ui-File. This Attribute is obligatory - */ - Ui::QmitkAdaptiveRegionGrowingToolGUIControls m_Controls; - -protected slots: - - /** - * @brief Method to start the segmentation - * - * This method is called, when the "Start Segmentation" button is clicked. - */ - void RunSegmentation(); - - /** - * @brief Method to change the level window - * - * This method is called, when the level window slider is changed via the slider in the control widget - * @param newValue new value - */ - void ChangeLevelWindow(double newValue); - - /** - * @brief Method to increase the preview slider - * - * This method is called, when the + button is clicked and increases the value by 1 - */ - void IncreaseSlider(); - - /** - * @brief Method to decrease the preview slider - * - * This method is called, when the - button is clicked and decreases the value by 1 - */ - void DecreaseSlider(); - - /** - * @brief Method to confirm the preview segmentation - * - * This method is called, when the "Confirm Segmentation" button is clicked. - */ - void ConfirmSegmentation(); - - /** - * @brief Method to switch the volume rendering on/off - * @param on - */ - void UseVolumeRendering(bool on); - - /** - * @brief Method to set the lower threshold - * - * This method is called, when the minimum threshold slider has changed - * @param lowerThreshold lower threshold - */ - void SetLowerThresholdValue(double lowerThreshold); - - /** - * @brief Method to set upper threshold - * - * This Method is called, when the maximum threshold slider has changed - * @param upperThreshold upper threshold - */ - void SetUpperThresholdValue(double upperThreshold); - - /** - * @brief Method to determine which tool to activate - * - * This method listens to the tool manager and activates this tool if requested otherwise disables this view - */ - void OnNewToolAssociated(mitk::Tool *); - -protected: - mitk::AdaptiveRegionGrowingTool::Pointer m_RegionGrow3DTool; - - /** \brief Destructor. */ - ~QmitkAdaptiveRegionGrowingToolGUI() override; - - mitk::DataStorage *m_DataStorage; - - mitk::DataNode::Pointer m_InputImageNode; - - /** - * @brief Method to calculate parameter settings, when a seed point is set - */ - void OnPointAdded(); - - /** - * @brief Method to extract a 3D image based on a given time point that can be taken from the SliceNavigationController - * - * This ensures that the seed point is taken from the current selected 3D image - */ - mitk::Image::ConstPointer GetImageByTimePoint(const mitk::Image *image, - mitk::TimePointType timePoint) const; - -private: - std::string m_NAMEFORORGIMAGE; - std::string m_NAMEFORLABLEDSEGMENTATIONIMAGE; - std::string m_NAMEFORBINARYIMAGE; - std::string m_NAMEFORSURFACE; - std::string m_NAMEFORMASKEDSEGMENTATION; - - mitk::ScalarType m_LOWERTHRESHOLD; // Hounsfield value - mitk::ScalarType m_UPPERTHRESHOLD; // Hounsfield value - mitk::ScalarType m_SeedPointValueMean; - - void RemoveHelperNodes(); - - int m_DetectedLeakagePoint; - - bool m_CurrentRGDirectionIsUpwards; // defines fixed threshold (true = LOWERTHRESHOLD fixed, false = UPPERTHRESHOLD - // fixed) - - int m_SeedpointValue; - bool m_SliderInitialized; - bool m_UseVolumeRendering; - bool m_UpdateSuggestedThreshold; - float m_SuggestedThValue; - - long m_PointSetAddObserverTag; - long m_PointSetMoveObserverTag; - - template - void StartRegionGrowing(const itk::Image *itkImage, - const mitk::BaseGeometry *imageGeometry, - const mitk::PointSet::PointType seedPoint); - - template - void ITKThresholding(itk::Image *inputImage); - - void InitializeLevelWindow(); - - void EnableVolumeRendering(bool enable); - - void UpdateVolumeRenderingThreshold(int thValue); -}; - -#endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui deleted file mode 100644 index 2b91deefe8..0000000000 --- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui +++ /dev/null @@ -1,227 +0,0 @@ - - - QmitkAdaptiveRegionGrowingToolGUIControls - - - - 0 - 0 - 264 - 171 - - - - - 0 - 0 - - - - - 0 - 0 - - - - QmitkAdaptiveRegionGrowingWidget - - - Move to adjust the segmentation - - - - 0 - - - - - - 0 - 0 - - - - Shift+Click to place seedpoint - - - 0 - - - - - - - Define thresholds: - - - true - - - - 0 - - - 6 - - - 0 - - - 0 - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - - 0 - 0 - - - - - - - Press to start the segmentation of the tubular structure. - - - Run Segmentation - - - Alt+R - - - - - - - false - - - - 0 - 0 - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Enable/disable GPU volume rendering for the segmentation preview.</span></p></body></html> - - - Qt::LeftToRight - - - 3D preview - - - false - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Adapt Region Growing: - - - true - - - - 0 - - - 6 - - - 0 - - - 0 - - - - - - - - - - - false - - - - - - Press to confirm the segmentation and calculate 3D representation. - - - &Confirm Segmentation - - - Alt+C - - - - - - - - - ctkRangeWidget - QWidget -
ctkRangeWidget.h
- 1 -
- - ctkSliderWidget - QWidget -
ctkSliderWidget.h
- 1 -
-
- - -
diff --git a/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.cpp b/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.cpp index f4a276d6ff..6004ea96c8 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.cpp @@ -1,210 +1,186 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkAutoSegmentationToolGUIBase.h" #include #include #include #include #include bool DefaultEnableConfirmSegBtnFunction(bool enabled) { return enabled; } QmitkAutoSegmentationToolGUIBase::QmitkAutoSegmentationToolGUIBase(bool mode2D) : QmitkToolGUI(), m_EnableConfirmSegBtnFnc(DefaultEnableConfirmSegBtnFunction), m_Mode2D(mode2D) { connect(this, SIGNAL(NewToolAssociated(mitk::Tool *)), this, SLOT(OnNewToolAssociated(mitk::Tool *))); } QmitkAutoSegmentationToolGUIBase::~QmitkAutoSegmentationToolGUIBase() { if (m_Tool.IsNotNull()) { m_Tool->CurrentlyBusy -= mitk::MessageDelegate1(this, &QmitkAutoSegmentationToolGUIBase::BusyStateChanged); } } void QmitkAutoSegmentationToolGUIBase::OnNewToolAssociated(mitk::Tool *tool) { if (m_Tool.IsNotNull()) { this->DisconnectOldTool(m_Tool); } m_Tool = dynamic_cast(tool); if (nullptr == m_MainLayout) { // create the visible widgets m_MainLayout = new QVBoxLayout(this); m_ConfirmSegBtn = new QPushButton("Confirm Segmentation", this); connect(m_ConfirmSegBtn, SIGNAL(clicked()), this, SLOT(OnAcceptPreview())); m_CheckIgnoreLocks = new QCheckBox("Ignore label locks", this); m_CheckIgnoreLocks->setChecked(m_Tool->GetOverwriteStyle() == mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks); m_CheckIgnoreLocks->setToolTip("If checked, the lock state of labels will be ignored when the preview segmentation is confermed. Thus also locked label pixels can be changed by the operation."); m_CheckMerge = new QCheckBox("Merge with existing content", this); m_CheckMerge->setChecked(m_Tool->GetMergeStyle()==mitk::MultiLabelSegmentation::MergeStyle::Merge); m_CheckMerge->setToolTip("If checked, the preview segmantation will be merged with the existing segmantation into a union. If unchecked, the preview content will replace the old segmantation"); m_CheckProcessAll = new QCheckBox("Process all time steps", this); m_CheckProcessAll->setChecked(false); m_CheckProcessAll->setToolTip("Process all time steps of the dynamic segmentation and not just the currently visible time step."); m_CheckProcessAll->setVisible(!m_Mode2D); //remark: keept m_CheckProcessAll deactivated in 2D because in this refactoring //it should be kept to the status quo and it was not clear how interpolation //would behave. As soon as it is sorted out we can remove that "feature switch" //or the comment. - m_CheckCreateNew = new QCheckBox("Create as new segmentation", this); - m_CheckCreateNew->setChecked(false); - m_CheckCreateNew->setToolTip("Add the confirmed segmentation as a new segmentation instead of overwriting the currently selected."); - m_CheckCreateNew->setVisible(!m_Mode2D); - //remark: keept m_CheckCreateNew deactivated in 2D because in this refactoring - //it should be kept to the status quo and it was not clear how interpolation - //would behave. As soon as it is sorted out we can remove that "feature switch" - //or the comment. - this->InitializeUI(m_MainLayout); m_MainLayout->addWidget(m_ConfirmSegBtn); m_MainLayout->addWidget(m_CheckIgnoreLocks); m_MainLayout->addWidget(m_CheckMerge); m_MainLayout->addWidget(m_CheckProcessAll); - m_MainLayout->addWidget(m_CheckCreateNew); } if (m_Tool.IsNotNull()) { this->ConnectNewTool(m_Tool); } } void QmitkAutoSegmentationToolGUIBase::OnAcceptPreview() { if (m_Tool.IsNotNull()) { if (m_CheckIgnoreLocks->isChecked()) { m_Tool->SetOverwriteStyle(mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks); } else { m_Tool->SetOverwriteStyle(mitk::MultiLabelSegmentation::OverwriteStyle::RegardLocks); } if (m_CheckMerge->isChecked()) { m_Tool->SetMergeStyle(mitk::MultiLabelSegmentation::MergeStyle::Merge); } else { m_Tool->SetMergeStyle(mitk::MultiLabelSegmentation::MergeStyle::Replace); } - if (m_CheckCreateNew->isChecked()) - { - m_Tool->SetOverwriteExistingSegmentation(false); - } - else - { - m_Tool->SetOverwriteExistingSegmentation(true); - } - m_Tool->SetCreateAllTimeSteps(m_CheckProcessAll->isChecked()); m_ConfirmSegBtn->setEnabled(false); m_Tool->ConfirmSegmentation(); } } void QmitkAutoSegmentationToolGUIBase::DisconnectOldTool(mitk::AutoSegmentationWithPreviewTool* oldTool) { oldTool->CurrentlyBusy -= mitk::MessageDelegate1(this, &QmitkAutoSegmentationToolGUIBase::BusyStateChanged); } void QmitkAutoSegmentationToolGUIBase::ConnectNewTool(mitk::AutoSegmentationWithPreviewTool* newTool) { newTool->CurrentlyBusy += mitk::MessageDelegate1(this, &QmitkAutoSegmentationToolGUIBase::BusyStateChanged); - newTool->SetOverwriteExistingSegmentation(true); m_CheckProcessAll->setVisible(newTool->GetTargetSegmentationNode()->GetData()->GetTimeSteps() > 1); this->EnableWidgets(true); } void QmitkAutoSegmentationToolGUIBase::InitializeUI(QBoxLayout* /*mainLayout*/) { //default implementation does nothing } void QmitkAutoSegmentationToolGUIBase::BusyStateChanged(bool isBusy) { if (isBusy) { QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); } else { QApplication::restoreOverrideCursor(); } this->EnableWidgets(!isBusy); } void QmitkAutoSegmentationToolGUIBase::EnableWidgets(bool enabled) { if (nullptr != m_MainLayout) { if (nullptr != m_ConfirmSegBtn) { m_ConfirmSegBtn->setEnabled(m_EnableConfirmSegBtnFnc(enabled)); } if (nullptr != m_CheckIgnoreLocks) { m_CheckIgnoreLocks->setEnabled(enabled); } if (nullptr != m_CheckMerge) { m_CheckMerge->setEnabled(enabled); } if (nullptr != m_CheckProcessAll) { m_CheckProcessAll->setEnabled(enabled); } - if (nullptr != m_CheckCreateNew) - { - m_CheckCreateNew->setEnabled(enabled); - } } } void QmitkAutoSegmentationToolGUIBase::SetMergeStyle(mitk::MultiLabelSegmentation::MergeStyle mergeStyle) { if (nullptr != m_CheckMerge) { m_CheckMerge->setChecked(mergeStyle == mitk::MultiLabelSegmentation::MergeStyle::Merge); } }; void QmitkAutoSegmentationToolGUIBase::SetOverwriteStyle(mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle) { if (nullptr != m_CheckIgnoreLocks) { m_CheckIgnoreLocks->setChecked(overwriteStyle == mitk::MultiLabelSegmentation::OverwriteStyle::IgnoreLocks); } }; diff --git a/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.h b/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.h index 54701e27ca..1012ac78c1 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.h +++ b/Modules/SegmentationUI/Qmitk/QmitkAutoSegmentationToolGUIBase.h @@ -1,96 +1,95 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkAutoSegmentationToolGUIBase_h_Included #define QmitkAutoSegmentationToolGUIBase_h_Included #include "QmitkToolGUI.h" #include "mitkAutoSegmentationWithPreviewTool.h" #include class QCheckBox; class QPushButton; class QBoxLayout; /** \ingroup org_mitk_gui_qt_interactivesegmentation_internal \brief GUI base clase for tools derived from mitk::AutoSegmentationTool. */ class MITKSEGMENTATIONUI_EXPORT QmitkAutoSegmentationToolGUIBase : public QmitkToolGUI { Q_OBJECT public: mitkClassMacro(QmitkAutoSegmentationToolGUIBase, QmitkToolGUI); itkCloneMacro(Self); itkGetConstMacro(Mode2D, bool); protected slots: void OnNewToolAssociated(mitk::Tool *); void OnAcceptPreview(); protected: QmitkAutoSegmentationToolGUIBase(bool mode2D); ~QmitkAutoSegmentationToolGUIBase() override; virtual void DisconnectOldTool(mitk::AutoSegmentationWithPreviewTool* oldTool); virtual void ConnectNewTool(mitk::AutoSegmentationWithPreviewTool* newTool); /**This method is called by OnNewToolAssociated if the UI is initialized the first time to allow derived classes to introduce own UI code. Overwrite to change. The implementation should ensure that alle widgets needed for the tool UI are properly allocated. If one needs to eecute time (e.g. to connect events between the tool and the UI) each time the tool changes, override the functions ConnectNewTool() and DisconnectOldTool().*/ virtual void InitializeUI(QBoxLayout* mainLayout); void BusyStateChanged(bool isBusy) override; using EnableConfirmSegBtnFunctionType = std::function; EnableConfirmSegBtnFunctionType m_EnableConfirmSegBtnFnc; /**This method is used to control/set the enabled state of the tool UI widgets. It is e.g. used if the busy state is changed (see BusyStateChanged). Override the default implmentation, e.g. if a tool adds his own UI elements (normally by overriding InitializeUI()) and wants to control how the widgets are enabled/disabled.*/ virtual void EnableWidgets(bool enabled); template TTool* GetConnectedToolAs() { return dynamic_cast(m_Tool.GetPointer()); }; void SetMergeStyle(mitk::MultiLabelSegmentation::MergeStyle mergeStyle); void SetOverwriteStyle(mitk::MultiLabelSegmentation::OverwriteStyle overwriteStyle); private: QCheckBox* m_CheckIgnoreLocks = nullptr; QCheckBox* m_CheckMerge = nullptr; QCheckBox* m_CheckProcessAll = nullptr; - QCheckBox* m_CheckCreateNew = nullptr; QPushButton* m_ConfirmSegBtn = nullptr; QBoxLayout* m_MainLayout = nullptr; /**Indicates if the tool is in 2D or 3D mode.*/ bool m_Mode2D; mitk::AutoSegmentationWithPreviewTool::Pointer m_Tool; }; #endif diff --git a/Modules/SegmentationUI/files.cmake b/Modules/SegmentationUI/files.cmake index 36584cbe80..a3e73418c1 100644 --- a/Modules/SegmentationUI/files.cmake +++ b/Modules/SegmentationUI/files.cmake @@ -1,87 +1,84 @@ set( CPP_FILES -Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp Qmitk/QmitkAutoSegmentationToolGUIBase.cpp Qmitk/QmitkAutoMLSegmentationToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUIBase.cpp Qmitk/QmitkBinaryThresholdToolGUI.cpp Qmitk/QmitkBinaryThresholdULToolGUI.cpp Qmitk/QmitkCalculateGrayValueStatisticsToolGUI.cpp Qmitk/QmitkConfirmSegmentationDialog.cpp Qmitk/QmitkCopyToClipBoardDialog.cpp Qmitk/QmitkDrawPaintbrushToolGUI.cpp Qmitk/QmitkErasePaintbrushToolGUI.cpp Qmitk/QmitkLiveWireTool2DGUI.cpp Qmitk/QmitkNewSegmentationDialog.cpp Qmitk/QmitkOtsuTool3DGUI.cpp Qmitk/QmitkPaintbrushToolGUI.cpp Qmitk/QmitkPickingToolGUI.cpp Qmitk/QmitkPixelManipulationToolGUI.cpp Qmitk/QmitkSlicesInterpolator.cpp Qmitk/QmitkToolGUI.cpp Qmitk/QmitkToolGUIArea.cpp Qmitk/QmitkToolSelectionBox.cpp Qmitk/QmitknnUNetToolGUI.cpp Qmitk/QmitknnUNetToolSlots.cpp #Added from ML Qmitk/QmitkLabelSetWidget.cpp Qmitk/QmitkSurfaceStampWidget.cpp Qmitk/QmitkMaskStampWidget.cpp Qmitk/QmitkSliceBasedInterpolatorWidget.cpp Qmitk/QmitkStaticDynamicSegmentationDialog.cpp Qmitk/QmitkSurfaceBasedInterpolatorWidget.cpp Qmitk/QmitkSimpleLabelSetListWidget.cpp ) set(MOC_H_FILES -Qmitk/QmitkAdaptiveRegionGrowingToolGUI.h Qmitk/QmitkAutoSegmentationToolGUIBase.h Qmitk/QmitkAutoMLSegmentationToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUIBase.h Qmitk/QmitkBinaryThresholdToolGUI.h Qmitk/QmitkBinaryThresholdULToolGUI.h Qmitk/QmitkCalculateGrayValueStatisticsToolGUI.h Qmitk/QmitkConfirmSegmentationDialog.h Qmitk/QmitkCopyToClipBoardDialog.h Qmitk/QmitkDrawPaintbrushToolGUI.h Qmitk/QmitkErasePaintbrushToolGUI.h Qmitk/QmitkLiveWireTool2DGUI.h Qmitk/QmitkNewSegmentationDialog.h Qmitk/QmitkOtsuTool3DGUI.h Qmitk/QmitkPaintbrushToolGUI.h Qmitk/QmitkPickingToolGUI.h Qmitk/QmitkPixelManipulationToolGUI.h Qmitk/QmitkSlicesInterpolator.h Qmitk/QmitkToolGUI.h Qmitk/QmitkToolGUIArea.h Qmitk/QmitkToolSelectionBox.h Qmitk/QmitknnUNetToolGUI.h Qmitk/QmitknnUNetGPU.h Qmitk/QmitknnUNetEnsembleLayout.h Qmitk/QmitknnUNetFolderParser.h #Added from ML Qmitk/QmitkLabelSetWidget.h Qmitk/QmitkSurfaceStampWidget.h Qmitk/QmitkMaskStampWidget.h Qmitk/QmitkSliceBasedInterpolatorWidget.h Qmitk/QmitkStaticDynamicSegmentationDialog.h Qmitk/QmitkSurfaceBasedInterpolatorWidget.h Qmitk/QmitkSimpleLabelSetListWidget.h ) set(UI_FILES -Qmitk/QmitkAdaptiveRegionGrowingToolGUIControls.ui Qmitk/QmitkConfirmSegmentationDialog.ui Qmitk/QmitkOtsuToolWidgetControls.ui Qmitk/QmitkLiveWireTool2DGUIControls.ui #Added from ML Qmitk/QmitkLabelSetWidgetControls.ui Qmitk/QmitkSurfaceStampWidgetGUIControls.ui Qmitk/QmitkMaskStampWidgetGUIControls.ui Qmitk/QmitkSliceBasedInterpolatorWidgetGUIControls.ui Qmitk/QmitkSurfaceBasedInterpolatorWidgetGUIControls.ui Qmitk/QmitknnUNetToolGUIControls.ui ) set(QRC_FILES resources/SegmentationUI.qrc )