diff --git a/Modules/Core/include/mitkImageTimeSelector.h b/Modules/Core/include/mitkImageTimeSelector.h index ea52c6dbdd..f3282099a2 100644 --- a/Modules/Core/include/mitkImageTimeSelector.h +++ b/Modules/Core/include/mitkImageTimeSelector.h @@ -1,60 +1,78 @@ /*============================================================================ 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 IMAGETIMESELECTOR_H_HEADER_INCLUDED_C1E4861D #define IMAGETIMESELECTOR_H_HEADER_INCLUDED_C1E4861D #include "mitkSubImageSelector.h" #include namespace mitk { //##Documentation //## @brief Provides access to a volume at a specific time of the input image //## //## If the input is generated by a ProcessObject, only the required data is //## requested. //## @ingroup Process class MITKCORE_EXPORT ImageTimeSelector : public SubImageSelector { public: mitkClassMacro(ImageTimeSelector, SubImageSelector); itkFactorylessNewMacro(Self); itkCloneMacro(Self); itkGetConstMacro(TimeNr, int); itkSetMacro(TimeNr, int); itkGetConstMacro(ChannelNr, int); itkSetMacro(ChannelNr, int); protected: ImageTimeSelector(); ~ImageTimeSelector() override; void GenerateOutputInformation() override; void GenerateInputRequestedRegion() override; void GenerateData() override; int m_TimeNr; int m_ChannelNr; }; + + /** Convinience helper that makes the application of the ImageTimeSelector one function call. It extracts the + image for the passed timestep, if the image has multiple time steps. + If a nullptr is passed as image, a nullptr will be returend. + If an image without timesteps is passed the, the image will be returned unaltered. The behavior of invalid time definition + is simerlar to the ImageTimeSelector filter.*/ + MITKCORE_EXPORT Image::ConstPointer SelectImageByTimeStep(const Image* image, unsigned int timestep); + /** Non const version.*/ + MITKCORE_EXPORT Image::Pointer SelectImageByTimeStep(Image* image, unsigned int timestep); + /** Convinience helper that makes the application of the ImageTimeSelector one function call. It extracts the + image for the passed time point, if the image has multiple time steps. + If a nullptr is passed as image, a nullptr will be returend. + If an image without timesteps is passed the, the image will be returned unaltered. The behavior of invalid time definition + is simerlar to the ImageTimeSelector filter.*/ + MITKCORE_EXPORT Image::ConstPointer SelectImageByTimePoint(const Image* image, TimePointType timePoint); + /** Non const version.*/ + MITKCORE_EXPORT Image::Pointer SelectImageByTimePoint(Image* image, TimePointType timePoint); + } // namespace mitk #endif /* IMAGETIMESELECTOR_H_HEADER_INCLUDED_C1E4861D */ diff --git a/Modules/Core/src/Algorithms/mitkImageTimeSelector.cpp b/Modules/Core/src/Algorithms/mitkImageTimeSelector.cpp index d7a5360da1..762d545183 100644 --- a/Modules/Core/src/Algorithms/mitkImageTimeSelector.cpp +++ b/Modules/Core/src/Algorithms/mitkImageTimeSelector.cpp @@ -1,97 +1,155 @@ /*============================================================================ 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 "mitkImageTimeSelector.h" mitk::ImageTimeSelector::ImageTimeSelector() : m_TimeNr(0), m_ChannelNr(0) { } mitk::ImageTimeSelector::~ImageTimeSelector() { } void mitk::ImageTimeSelector::GenerateOutputInformation() { Image::ConstPointer input = this->GetInput(); Image::Pointer output = this->GetOutput(); itkDebugMacro(<< "GenerateOutputInformation()"); int dim = (input->GetDimension() < 3 ? input->GetDimension() : 3); output->Initialize(input->GetPixelType(), dim, input->GetDimensions()); if ((unsigned int)m_TimeNr >= input->GetDimension(3)) { m_TimeNr = input->GetDimension(3) - 1; } // initialize geometry mitk::SlicedGeometry3D::Pointer sliced_geo = input->GetSlicedGeometry(m_TimeNr); if (sliced_geo.IsNull()) { mitkThrow() << "Failed to retrieve SlicedGeometry from input at timestep " << m_TimeNr; } mitk::SlicedGeometry3D::Pointer sliced_geo_clone = sliced_geo->Clone(); if (sliced_geo_clone.IsNull()) { mitkThrow() << "Failed to clone the retrieved sliced geometry."; } mitk::BaseGeometry::Pointer geom_3d = dynamic_cast(sliced_geo_clone.GetPointer()); if (geom_3d.IsNotNull()) { output->SetGeometry(geom_3d.GetPointer()); } else { mitkThrow() << "Failed to cast the retrieved SlicedGeometry to a Geometry3D object."; } output->SetPropertyList(input->GetPropertyList()->Clone()); } void mitk::ImageTimeSelector::GenerateData() { const Image::RegionType &requestedRegion = this->GetOutput()->GetRequestedRegion(); // do we really need a complete volume at a time? if (requestedRegion.GetSize(2) > 1) { mitk::ImageDataItem::Pointer im = this->GetVolumeData(m_TimeNr, m_ChannelNr)->Clone(); im->SetTimestep(0); im->SetManageMemory(false); this->SetVolumeItem(im, 0); } else // no, so take just a slice! this->SetSliceItem( this->GetSliceData(requestedRegion.GetIndex(2), m_TimeNr, m_ChannelNr), requestedRegion.GetIndex(2), 0); } void mitk::ImageTimeSelector::GenerateInputRequestedRegion() { Superclass::GenerateInputRequestedRegion(); ImageToImageFilter::InputImagePointer input = this->GetInput(); Image::Pointer output = this->GetOutput(); Image::RegionType requestedRegion; requestedRegion = output->GetRequestedRegion(); requestedRegion.SetIndex(3, m_TimeNr); requestedRegion.SetIndex(4, m_ChannelNr); requestedRegion.SetSize(3, 1); requestedRegion.SetSize(4, 1); input->SetRequestedRegion(&requestedRegion); } + +mitk::Image::ConstPointer mitk::SelectImageByTimeStep(const mitk::Image* image, unsigned int timestep) +{ + if (nullptr == image) + return image; + + if (image->GetDimension() != 4) + return image; + + ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + + imageTimeSelector->SetInput(image); + imageTimeSelector->SetTimeNr(static_cast(timestep)); + + imageTimeSelector->UpdateLargestPossibleRegion(); + + return imageTimeSelector->GetOutput(); +} + +mitk::Image::Pointer mitk::SelectImageByTimeStep(mitk::Image* image, unsigned int timestep) +{ + if (nullptr == image) + return image; + + if (image->GetDimension() != 4) + return image; + + ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); + + imageTimeSelector->SetInput(image); + imageTimeSelector->SetTimeNr(static_cast(timestep)); + + imageTimeSelector->UpdateLargestPossibleRegion(); + + return imageTimeSelector->GetOutput(); +} + +mitk::Image::ConstPointer mitk::SelectImageByTimePoint(const mitk::Image* image, TimePointType timePoint) +{ + if (nullptr == image) + return image; + + if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) + return nullptr; + + return SelectImageByTimeStep(image, image->GetTimeGeometry()->TimePointToTimeStep(timePoint)); +} + +mitk::Image::Pointer mitk::SelectImageByTimePoint(mitk::Image* image, TimePointType timePoint) +{ + if (nullptr == image) + return image; + + if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) + return nullptr; + + return SelectImageByTimeStep(image, image->GetTimeGeometry()->TimePointToTimeStep(timePoint)); +} diff --git a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp index 03813c8731..ef35be95dc 100644 --- a/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp +++ b/Modules/Segmentation/Interactions/mitkAutoSegmentationTool.cpp @@ -1,164 +1,132 @@ /*============================================================================ 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) { - if (nullptr == image) - return image; - - if (image->GetDimension() != 4) - return image; - - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - - imageTimeSelector->SetInput(image); - imageTimeSelector->SetTimeNr(static_cast(timestep)); - - imageTimeSelector->UpdateLargestPossibleRegion(); - - return imageTimeSelector->GetOutput(); + return SelectImageByTimeStep(image, timestep); } mitk::Image::Pointer mitk::AutoSegmentationTool::GetImageByTimeStep(mitk::Image* image, unsigned int timestep) { - if (nullptr == image) - return image; - - if (image->GetDimension() != 4) - return image; - - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - - imageTimeSelector->SetInput(image); - imageTimeSelector->SetTimeNr(static_cast(timestep)); - - imageTimeSelector->UpdateLargestPossibleRegion(); - - return imageTimeSelector->GetOutput(); + return SelectImageByTimeStep(image, timestep); } mitk::Image::ConstPointer mitk::AutoSegmentationTool::GetImageByTimePoint(const mitk::Image* image, TimePointType timePoint) { - if (nullptr == image) - return image; - - if (!image->GetTimeGeometry()->IsValidTimePoint(timePoint)) - return nullptr; - - return AutoSegmentationTool::GetImageByTimeStep(image, image->GetTimeGeometry()->TimePointToTimeStep(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)); } }