diff --git a/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.cpp b/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.cpp new file mode 100644 index 0000000000..cc5e700bbc --- /dev/null +++ b/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.cpp @@ -0,0 +1,139 @@ +/*============================================================================ + +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 "mitkFillRegionBaseTool.h" +#include "mitkToolManager.h" + +#include "mitkBaseRenderer.h" +#include "mitkDataStorage.h" + +#include "mitkITKImageImport.h" +#include "mitkImageAccessByItk.h" + +#include "mitkRenderingManager.h" + +#include + +mitk::FillRegionBaseTool::FillRegionBaseTool() : SegTool2D("MouseReleaseOnly") +{ +} + +mitk::FillRegionBaseTool::~FillRegionBaseTool() +{ +} + +void mitk::FillRegionBaseTool::ConnectActionsAndFunctions() +{ + CONNECT_FUNCTION("Release", OnClick); +} + + +template +void DoITKRegionGrowing(const itk::Image* oldSegImage, + mitk::Image::Pointer& filledRegionImage, itk::Index seedIndex, mitk::Label::PixelType& seedLabel ) +{ + typedef itk::Image InputImageType; + typedef itk::Image OutputImageType; + typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; + + seedLabel = oldSegImage->GetPixel(seedIndex); + + typename OutputImageType::Pointer itkResultImage; + filledRegionImage = nullptr; + + try + { + typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); + regionGrower->SetInput(oldSegImage); + regionGrower->SetReplaceValue(1); + regionGrower->AddSeed(seedIndex); + + regionGrower->SetLower(seedLabel); + regionGrower->SetUpper(seedLabel); + + regionGrower->Update(); + + itkResultImage = regionGrower->GetOutput(); + } + catch (const itk::ExceptionObject&) + { + return; // can't work + } + catch (...) + { + return; + } + mitk::CastToMitkImage(itkResultImage, filledRegionImage); +} + +#include "mitkIOUtil.h" + +void mitk::FillRegionBaseTool::OnClick(StateMachineAction*, InteractionEvent* interactionEvent) +{ + auto positionEvent = dynamic_cast(interactionEvent); + if (nullptr == positionEvent) + return; + + auto labelSetImage = dynamic_cast(this->GetWorkingData()); + if (nullptr == labelSetImage) + { + return; + } + + if (!IsPositionEventInsideImageRegion(positionEvent, labelSetImage)) + { + return; + } + + m_LastEventSender = positionEvent->GetSender(); + m_LastEventSlice = m_LastEventSender->GetSlice(); + + auto workingSlice = this->GetAffectedWorkingSlice(positionEvent); + + auto click = positionEvent->GetPositionInWorld(); + + auto workingImage = this->GetWorkingData(); + + auto fillImage = this->GenerateFillImage(workingSlice, click); + this->PrepareFilling(workingSlice, click); + + TransferLabelContent(fillImage, workingSlice, labelSetImage->GetActiveLabelSet(), 0, labelSetImage->GetExteriorLabel()->GetValue(), false, { {1, m_FillValue} }, m_MergeStyle); + + this->WriteBackSegmentationResult(positionEvent, workingSlice); + + mitk::RenderingManager::GetInstance()->RequestUpdate(positionEvent->GetSender()->GetRenderWindow()); +} + +mitk::Image::Pointer mitk::FillRegionBaseTool::GenerateFillImage(const Image* workingSlice, Point3D seedPoint) const +{ + itk::Index<2> seedIndex; + workingSlice->GetGeometry()->WorldToIndex(seedPoint, seedIndex); + + Image::Pointer fillImage; + Label::PixelType seedLabelValue; + + AccessFixedDimensionByItk_n(workingSlice, DoITKRegionGrowing, 2, (fillImage, seedIndex, seedLabelValue)); + + auto labelSetImage = dynamic_cast(this->GetWorkingData()); + if (nullptr != labelSetImage) + { + auto label = labelSetImage->GetLabel(seedLabelValue, labelSetImage->GetActiveLayer()); + + if (label->GetLocked()) + { + ErrorMessage.Send("Label of selected region is locked. Tool operation may not have an effect."); + } + } + + return fillImage; +} + diff --git a/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.h b/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.h new file mode 100644 index 0000000000..722cfde266 --- /dev/null +++ b/Modules/Segmentation/Interactions/mitkFillRegionBaseTool.h @@ -0,0 +1,74 @@ +/*============================================================================ + +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 mitkFillRegionBaseTool_h_Included +#define mitkFillRegionBaseTool_h_Included + +#include "mitkCommon.h" +#include "mitkContourModelUtils.h" +#include "mitkContourUtils.h" //TODO remove legacy support +#include "mitkImage.h" +#include "mitkSegTool2D.h" +#include + +#include "mitkDataNode.h" + +#include "mitkImageCast.h" + +namespace mitk +{ + /** + \brief Base class for tools that fill a connected region of a 2D slice + + \sa Tool + + \ingroup Interaction + \ingroup ToolManagerEtAl + + \warning Only to be instantiated by mitk::ToolManager. + + $Author: nolden $ + */ + class MITKSEGMENTATION_EXPORT FillRegionBaseTool : public SegTool2D + { + public: + mitkClassMacro(FillRegionBaseTool, SegTool2D); + + protected: + FillRegionBaseTool(); // purposely hidden + ~FillRegionBaseTool() override; + + void ConnectActionsAndFunctions() override; + + /// \brief Add a control point and finish current segment. + virtual void OnClick(StateMachineAction*, InteractionEvent* interactionEvent); + + /** Function that generates the mask image that indicates which pixels should be filled. + * Caller of this function assumes that all pixels that should be filled have the value 1. + * Pixels that should stay untouched should have the value 0. + * The default implementation marks the connected reagion around seedPoint, that has + * the same pixel value/label like the seedPoint. + * You may reimplement this function to change the strategy to determin the fill region.*/ + virtual Image::Pointer GenerateFillImage(const Image* workingSlice, Point3D seedPoint) const; + + /** Function that is called by OnClick before the filling is executed. If you want to do special + * preperation (e.g. change m_FillValue, you can overwrite this function. */ + virtual void PrepareFilling(const Image* workingSlice, Point3D seedPoint) = 0; + + Label::PixelType m_FillValue = 0; + MultiLabelSegmentation::MergeStyle m_MergeStyle = MultiLabelSegmentation::MergeStyle::Replace; + private: + }; + +} // namespace + +#endif diff --git a/Modules/Segmentation/Resources/Interactions/MouseReleaseOnly.xml b/Modules/Segmentation/Resources/Interactions/MouseReleaseOnly.xml new file mode 100644 index 0000000000..98f74e2964 --- /dev/null +++ b/Modules/Segmentation/Resources/Interactions/MouseReleaseOnly.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Modules/Segmentation/files.cmake b/Modules/Segmentation/files.cmake index 93b40ede21..241caf83cb 100644 --- a/Modules/Segmentation/files.cmake +++ b/Modules/Segmentation/files.cmake @@ -1,108 +1,110 @@ 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/mitkSegmentationHelper.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/mitkAddContourTool.cpp Interactions/mitkAutoCropTool.cpp Interactions/mitkSegWithPreviewTool.cpp Interactions/mitkBinaryThresholdBaseTool.cpp Interactions/mitkBinaryThresholdTool.cpp Interactions/mitkBinaryThresholdULTool.cpp Interactions/mitkContourModelInteractor.cpp Interactions/mitkContourModelLiveWireInteractor.cpp Interactions/mitkEditableContourTool.cpp Interactions/mitkLiveWireTool2D.cpp Interactions/mitkLassoTool.cpp Interactions/mitkContourTool.cpp Interactions/mitkDrawPaintbrushTool.cpp Interactions/mitkErasePaintbrushTool.cpp Interactions/mitkEraseRegionTool.cpp Interactions/mitkFeedbackContourTool.cpp + Interactions/mitkFillRegionBaseTool.cpp Interactions/mitkFillRegionTool.cpp Interactions/mitkOtsuTool3D.cpp Interactions/mitkPaintbrushTool.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 NewAdd_48x48.png NewAdd_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/EditableContourTool.xml Interactions/PickingTool.xml + Interactions/MouseReleaseOnly.xml Interactions/PressMoveRelease.xml Interactions/PressMoveReleaseAndPointSetting.xml Interactions/PressMoveReleaseWithCTRLInversion.xml Interactions/PressMoveReleaseWithCTRLInversionAllMouseMoves.xml Interactions/SegmentationToolsConfig.xml Interactions/ContourModelModificationConfig.xml Interactions/ContourModelModificationInteractor.xml )