diff --git a/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.cpp b/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.cpp new file mode 100644 index 0000000000..4f04dbfc21 --- /dev/null +++ b/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.cpp @@ -0,0 +1,198 @@ +/*============================================================================ + +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. + +============================================================================*/ + +// MITK +#include "mitkAutoMLSegmentationWithPreviewTool.h" +#include "mitkImageAccessByItk.h" +#include "mitkToolManager.h" +#include +#include +#include +#include +#include +#include + +// ITK +#include +#include + +mitk::AutoMLSegmentationWithPreviewTool::AutoMLSegmentationWithPreviewTool() : AutoSegmentationWithPreviewTool(true) +{ +} + +void mitk::AutoMLSegmentationWithPreviewTool::SetSelectedLabels(const SelectedLabelVectorType& regions) +{ + if (m_SelectedLabels != regions) + { + m_SelectedLabels = regions; + //Note: we do not call this->Modified() on puprose. Reason: changing the + //selected regions should not force to run otsu filter in DoUpdatePreview due to changed MTime. + } +} + +const mitk::LabelSetImage* mitk::AutoMLSegmentationWithPreviewTool::GetMLPreview() const +{ + if (m_MLPreviewNode.IsNotNull()) + { + const auto mlPreviewImage = dynamic_cast(this->m_MLPreviewNode->GetData()); + return mlPreviewImage; + } + + return nullptr; +} + +mitk::AutoMLSegmentationWithPreviewTool::SelectedLabelVectorType mitk::AutoMLSegmentationWithPreviewTool::GetSelectedLabels() const +{ + return this->m_SelectedLabels; +} + +void mitk::AutoMLSegmentationWithPreviewTool::Activated() +{ + Superclass::Activated(); + + m_SelectedLabels = {}; + + m_MLPreviewNode = mitk::DataNode::New(); + m_MLPreviewNode->SetProperty("name", StringProperty::New(std::string(this->GetName()) + "ML preview")); + m_MLPreviewNode->SetProperty("helper object", BoolProperty::New(true)); + m_MLPreviewNode->SetVisibility(true); + m_MLPreviewNode->SetOpacity(1.0); + + m_ToolManager->GetDataStorage()->Add(m_MLPreviewNode); +} + +void mitk::AutoMLSegmentationWithPreviewTool::Deactivated() +{ + m_ToolManager->GetDataStorage()->Remove(m_MLPreviewNode); + m_MLPreviewNode = nullptr; + + Superclass::Deactivated(); +} + +void mitk::AutoMLSegmentationWithPreviewTool::UpdateCleanUp() +{ + if (m_MLPreviewNode.IsNotNull()) + m_MLPreviewNode->SetVisibility(m_SelectedLabels.empty()); + + if (nullptr != this->GetPreviewSegmentationNode()) + this->GetPreviewSegmentationNode()->SetVisibility(!m_SelectedLabels.empty()); + + if (m_SelectedLabels.empty()) + { + this->ResetPreviewNode(); + } +} + +void mitk::AutoMLSegmentationWithPreviewTool::DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) +{ + const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); + + if (nullptr == m_MLPreviewNode->GetData() + || this->GetMTime() > m_MLPreviewNode->GetData()->GetMTime() + || this->m_LastMLTimeStep != timeStep //this covers the case where dynamic + //segmentations have to compute a preview + //for all time steps on confirmation + || this->GetLastTimePointOfUpdate() != timePoint //this ensures that static seg + //previews work with dynamic images + //with avoiding unnecessary other computations + ) + { + if (nullptr == inputAtTimeStep) + { + MITK_WARN << "Cannot run segementation. Currently selected input image is not set."; + return; + } + + this->m_LastMLTimeStep = timeStep; + + auto newMLPreview = ComputeMLPreview(inputAtTimeStep, timeStep); + + this->m_MLPreviewNode->SetData(newMLPreview); + this->m_MLPreviewNode->SetProperty("binary", mitk::BoolProperty::New(false)); + mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New(); + renderingMode->SetValue(mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR); + this->m_MLPreviewNode->SetProperty("Image Rendering.Mode", renderingMode); + mitk::LookupTable::Pointer lut = mitk::LookupTable::New(); + mitk::LookupTableProperty::Pointer prop = mitk::LookupTableProperty::New(lut); + vtkSmartPointer lookupTable = vtkSmartPointer::New(); + lookupTable->SetHueRange(1.0, 0.0); + lookupTable->SetSaturationRange(1.0, 1.0); + lookupTable->SetValueRange(1.0, 1.0); + lookupTable->SetTableRange(-1.0, 1.0); + lookupTable->Build(); + lut->SetVtkLookupTable(lookupTable); + prop->SetLookupTable(lut); + this->m_MLPreviewNode->SetProperty("LookupTable", prop); + mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); + mitk::LevelWindow levelwindow; + levelwindow.SetRangeMinMax(0, newMLPreview->GetScalarValueMax()); + levWinProp->SetLevelWindow(levelwindow); + this->m_MLPreviewNode->SetProperty("levelwindow", levWinProp); + } + + if (!m_SelectedLabels.empty()) + { + const auto mlPreviewImage = this->GetMLPreview(); + AccessByItk_n(mlPreviewImage, CalculateMergedSimplePreview, (previewImage, timeStep)); + } +} + +template +void mitk::AutoMLSegmentationWithPreviewTool::CalculateMergedSimplePreview(const itk::Image* itkImage, mitk::Image* segmentation, unsigned int timeStep) +{ + typedef itk::Image InputImageType; + typedef itk::Image OutputImageType; + + typedef itk::BinaryThresholdImageFilter FilterType; + + typename FilterType::Pointer filter = FilterType::New(); + + // InputImageType::Pointer itkImage; + typename OutputImageType::Pointer itkBinaryResultImage; + + filter->SetInput(itkImage); + filter->SetLowerThreshold(m_SelectedLabels[0]); + filter->SetUpperThreshold(m_SelectedLabels[0]); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->AddObserver(itk::ProgressEvent(), m_ProgressCommand); + filter->Update(); + itkBinaryResultImage = filter->GetOutput(); + itkBinaryResultImage->DisconnectPipeline(); + + // if more than one region id is used compute the union of all given binary regions + for (const auto labelID : m_SelectedLabels) + { + if (labelID != m_SelectedLabels[0]) + { + filter->SetLowerThreshold(labelID); + filter->SetUpperThreshold(labelID); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->Update(); + + typename OutputImageType::Pointer tempImage = filter->GetOutput(); + + typename itk::OrImageFilter::Pointer orFilter = + itk::OrImageFilter::New(); + orFilter->SetInput1(tempImage); + orFilter->SetInput2(itkBinaryResultImage); + orFilter->AddObserver(itk::ProgressEvent(), m_ProgressCommand); + + orFilter->UpdateLargestPossibleRegion(); + itkBinaryResultImage = orFilter->GetOutput(); + } + } + //---------------------------------------------------------------------------------------------------- + + segmentation->SetVolume((void*)(itkBinaryResultImage->GetPixelContainer()->GetBufferPointer()), timeStep); +} diff --git a/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.h b/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.h new file mode 100644 index 0000000000..94163df1ad --- /dev/null +++ b/Modules/Segmentation/Interactions/mitkAutoMLSegmentationWithPreviewTool.h @@ -0,0 +1,82 @@ +/*============================================================================ + +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 MITK_AUTO_ML_SEGMENTATION_WITH_PREVIEW_TOOL_H +#define MITK_AUTO_ML_SEGMENTATION_WITH_PREVIEW_TOOL_H + +#include "mitkAutoSegmentationWithPreviewTool.h" +#include "mitkDataNode.h" +#include "mitkLabelSetImage.h" + +#include + +namespace mitk +{ + /** + \brief Base class for any auto segmentation tool that provides a preview of the new segmentation and generates + segmentations with multiple labels. + + This tool class implements the basic logic to handle previews of multi label segmentations and + to allow to pick arbitrary labels as selected and merge them to a single segmentation to store this + segmentation as confirmed segmentation. + + \ingroup ToolManagerEtAl + \sa mitk::Tool + \sa QmitkInteractiveSegmentation + */ + class MITKSEGMENTATION_EXPORT AutoMLSegmentationWithPreviewTool : public AutoSegmentationWithPreviewTool + { + public: + mitkClassMacro(AutoMLSegmentationWithPreviewTool, AutoSegmentationWithPreviewTool); + + void Activated() override; + void Deactivated() override; + + using SelectedLabelVectorType = std::vector; + void SetSelectedLabels(const SelectedLabelVectorType& regions); + SelectedLabelVectorType GetSelectedLabels() const; + + const LabelSetImage* GetMLPreview() const; + + protected: + AutoMLSegmentationWithPreviewTool(); + ~AutoMLSegmentationWithPreviewTool() = default; + + void UpdateCleanUp() override; + void DoUpdatePreview(const Image* inputAtTimeStep, Image* previewImage, TimeStepType timeStep) override; + + /** Function to generate the new multi lable preview for a given time step input image. + * The function must be implemented by derived tools. + * This function is called by DoUpdatePreview if needed. + * Reasons are: + * - ML preview does not exist + * - Modify time of tools is newer then of ML preview + * - ML preview was not generated for the current selected timestep of input image or for the current selected timepoint.*/ + virtual LabelSetImage::Pointer ComputeMLPreview(const Image* inputAtTimeStep, TimeStepType timeStep) = 0; + + private: + /** Function to generate a simple (single lable) preview by merging all labels of the ML preview that are selected and + * copies that single label preview to the passed previewImage. + * This function is called by DoUpdatePreview if needed. + * @param mlPreviewImage Multi label preview that is the source. + * @param previewImage Pointer to the single label preview image that should receive the merged selected labels. + * @timeStep Time step of the previewImage that should be filled.*/ + template + void CalculateMergedSimplePreview(const itk::Image* mlImage, mitk::Image* segmentation, unsigned int timeStep); + + SelectedLabelVectorType m_SelectedLabels = {}; + + // holds the multilabel result as a preview image + mitk::DataNode::Pointer m_MLPreviewNode; + TimeStepType m_LastMLTimeStep = 0; + }; +} +#endif diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp index 8e9b4291f7..e8554c2228 100644 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp +++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationWithPreviewTool.cpp @@ -1,474 +1,478 @@ /*============================================================================ 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 "mitkLevelWindowProperty.h" #include "mitkProperties.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkImageStatisticsHolder.h" #include "mitkImageTimeSelector.h" #include "mitkLabelSetImage.h" #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkPadImageFilter.h" #include "mitkNodePredicateGeometry.h" mitk::AutoSegmentationWithPreviewTool::AutoSegmentationWithPreviewTool(bool lazyDynamicPreviews): m_LazyDynamicPreviews(lazyDynamicPreviews) { m_ProgressCommand = mitk::ToolCommand::New(); } mitk::AutoSegmentationWithPreviewTool::~AutoSegmentationWithPreviewTool() { } 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(); m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged); m_ToolManager->SelectedTimePointChanged += mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged); m_ReferenceDataNode = m_ToolManager->GetReferenceData(0); m_SegmentationInputNode = m_ReferenceDataNode; m_LastTimePointOfUpdate = 0; 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 { m_ToolManager->ActivateTool(-1); } } void mitk::AutoSegmentationWithPreviewTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged); m_ToolManager->SelectedTimePointChanged -= mitk::MessageDelegate(this, &mitk::AutoSegmentationWithPreviewTool::OnTimePointChanged); m_SegmentationInputNode = nullptr; m_ReferenceDataNode = nullptr; try { if (DataStorage *storage = m_ToolManager->GetDataStorage()) { storage->Remove(m_PreviewSegmentationNode); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch (...) { // don't care } - m_PreviewSegmentationNode->SetData(nullptr); + if (m_PreviewSegmentationNode.IsNotNull()) + { + m_PreviewSegmentationNode->SetData(nullptr); + } Superclass::Deactivated(); } void mitk::AutoSegmentationWithPreviewTool::ConfirmSegmentation() { if (m_LazyDynamicPreviews && m_CreateAllTimeSteps) { // 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) { m_ToolManager->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()); } void mitk::AutoSegmentationWithPreviewTool::ResetPreviewNode() { itk::RGBPixel previewColor; previewColor[0] = 0.0f; previewColor[1] = 1.0f; previewColor[2] = 0.0f; const auto image = this->GetSegmentationInput(); if (nullptr != image) { mitk::LabelSetImage::ConstPointer workingImage = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); if (workingImage.IsNotNull()) { auto newPreviewImage = workingImage->Clone(); 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... newPreviewImage->GetActiveLabel()->SetColor(previewColor); newPreviewImage->GetActiveLabelSet()->UpdateLookupTable(newPreviewImage->GetActiveLabel()->GetValue()); } else { mitk::Image::ConstPointer workingImageBin = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); if (workingImageBin.IsNotNull()) { auto newPreviewImage = workingImageBin->Clone(); if (newPreviewImage.IsNull()) { MITK_ERROR << "Cannot create preview helper objects. Unable to clone working image"; return; } m_PreviewSegmentationNode->SetData(newPreviewImage->Clone()); } 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 = m_ToolManager->GetDataStorage()) { if (!ds->Exists(m_PreviewSegmentationNode)) ds->Add(m_PreviewSegmentationNode, m_ReferenceDataNode); } } } template static void ITKSetVolume(const itk::Image *originalImage, mitk::Image *segmentation, unsigned int timeStep) { auto constPixelContainer = originalImage->GetPixelContainer(); //have to make a const cast because itk::PixelContainer does not provide a const correct access :( auto pixelContainer = const_cast::PixelContainer*>(constPixelContainer); segmentation->SetVolume((void *)pixelContainer->GetBufferPointer(), timeStep); } void mitk::AutoSegmentationWithPreviewTool::TransferImageAtTimeStep(const Image* sourceImage, Image* destinationImage, const TimeStepType timeStep) { try { Image::ConstPointer image3D = this->GetImageByTimeStep(sourceImage, timeStep); if (image3D->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_PRECISION, false)) { mitkThrow() << "Cannot transfer images. Tool is in an invalid state, source image and destination image do not have the same geometry."; } if (image3D->GetDimension() == 2) { AccessFixedDimensionByItk_2( image3D, ITKSetVolume, 2, destinationImage, timeStep); } else { AccessFixedDimensionByItk_2( image3D, ITKSetVolume, 3, destinationImage, 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 = mitk::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) { TransferImageAtTimeStep(previewImage, resultSegmentation, timeStep); } } else { const auto timeStep = resultSegmentation->GetTimeGeometry()->TimePointToTimeStep(timePoint); 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()) { mitk::PadImageFilter::Pointer padFilter = mitk::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()); } m_ToolManager->SetWorkingData(resultSegmentationNode); m_ToolManager->GetWorkingData(0)->Modified(); } } } void mitk::AutoSegmentationWithPreviewTool::OnRoiDataChanged() { mitk::DataNode::ConstPointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); mitk::Image::Pointer image = dynamic_cast(m_SegmentationInputNode->GetData()); if (image.IsNull()) return; roiFilter->SetInput(image); roiFilter->SetRegionOfInterest(node->GetData()); roiFilter->Update(); mitk::DataNode::Pointer tmpNode = mitk::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 = mitk::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(); } } } void mitk::AutoSegmentationWithPreviewTool::UpdatePreview(bool ignoreLazyPreviewSetting) { const auto inputImage = this->GetSegmentationInput(); auto previewImage = this->GetPreviewSegmentation(); int progress_steps = 200; + this->CurrentlyBusy.Send(true); + this->UpdatePrepare(); const auto timePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); try { - this->CurrentlyBusy.Send(true); if (nullptr != inputImage && nullptr != previewImage) { m_ProgressCommand->AddStepsToDo(progress_steps); if (previewImage->GetTimeSteps() > 1 && (ignoreLazyPreviewSetting || !m_LazyDynamicPreviews)) { for (unsigned int timeStep = 0; timeStep < inputImage->GetTimeSteps(); ++timeStep) { auto feedBackImage3D = this->GetImageByTimeStep(inputImage, timeStep); this->DoUpdatePreview(feedBackImage3D, previewImage, timeStep); } } else { auto feedBackImage3D = this->GetImageByTimePoint(inputImage, timePoint); auto timeStep = previewImage->GetTimeGeometry()->TimePointToTimeStep(timePoint); this->DoUpdatePreview(feedBackImage3D, 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); CurrentlyBusy.Send(false); throw; } this->UpdateCleanUp(); m_LastTimePointOfUpdate = timePoint; m_ProgressCommand->SetProgress(progress_steps); CurrentlyBusy.Send(false); } 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; } diff --git a/Modules/Segmentation/files.cmake b/Modules/Segmentation/files.cmake index 1deb993fd5..3bce31c9b5 100644 --- a/Modules/Segmentation/files.cmake +++ b/Modules/Segmentation/files.cmake @@ -1,117 +1,118 @@ 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/mitkOverwriteDirectedPlaneImageFilter.cpp Algorithms/mitkOverwriteSliceImageFilter.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/mitkCorrectorTool2D.cpp Interactions/mitkCreateSurfaceTool.cpp Interactions/mitkDrawPaintbrushTool.cpp Interactions/mitkErasePaintbrushTool.cpp Interactions/mitkEraseRegionTool.cpp Interactions/mitkFastMarchingTool.cpp Interactions/mitkFastMarchingTool3D.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/mitkWatershedTool.cpp Interactions/mitkPickingTool.cpp Interactions/mitkSegmentationInteractor.cpp #SO 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 Correction_48x48.png Correction_Cursor_32x32.png Erase_48x48.png Erase_Cursor_32x32.png FastMarching_48x48.png FastMarching_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 Watershed_48x48.png Watershed_Cursor_32x32.png Wipe_48x48.png Wipe_Cursor_32x32.png Interactions/dummy.xml Interactions/LiveWireTool.xml Interactions/FastMarchingTool.xml Interactions/PressMoveRelease.xml Interactions/PressMoveReleaseAndPointSetting.xml Interactions/PressMoveReleaseWithCTRLInversion.xml Interactions/PressMoveReleaseWithCTRLInversionAllMouseMoves.xml Interactions/SegmentationToolsConfig.xml Interactions/ContourModelModificationConfig.xml Interactions/ContourModelModificationInteractor.xml )