diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp index 0b61593b90..da3195d7aa 100644 --- a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp +++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.cpp @@ -1,347 +1,393 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBinaryThresholdTool.h" #include "mitkToolManager.h" #include "mitkBoundingObjectToSegmentationFilter.h" #include #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkOrganTypeProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkImageTimeSelector.h" #include "mitkImageStatisticsHolder.h" #include #include #include "mitkPadImageFilter.h" #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkLabelSetImage.h" // us #include "usModule.h" #include "usModuleResource.h" #include "usGetModuleContext.h" namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, BinaryThresholdTool, "Thresholding tool"); } mitk::BinaryThresholdTool::BinaryThresholdTool() :m_SensibleMinimumThresholdValue(-100), m_SensibleMaximumThresholdValue(+100), m_CurrentThresholdValue(0.0), m_IsFloatImage(false) { m_ThresholdFeedbackNode = DataNode::New(); - m_ThresholdFeedbackNode->SetProperty("name", StringProperty::New("Thresholding feedback")); - m_ThresholdFeedbackNode->SetProperty("helper object", BoolProperty::New(true)); - m_ThresholdFeedbackNode->SetFloatProperty("labelset.contour.width", 0.0); + m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(0.0, 1.0, 0.0) ); + m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") ); + m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); + m_ThresholdFeedbackNode->SetProperty("binary", BoolProperty::New(true)); + m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); } mitk::BinaryThresholdTool::~BinaryThresholdTool() { } const char** mitk::BinaryThresholdTool::GetXPM() const { return NULL; } us::ModuleResource mitk::BinaryThresholdTool::GetIconResource() const { us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("Threshold_48x48.png"); return resource; } const char* mitk::BinaryThresholdTool::GetName() const { return "Threshold"; } void mitk::BinaryThresholdTool::Activated() { Superclass::Activated(); m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeForThresholding = m_OriginalImageNode; if (m_NodeForThresholding.IsNotNull()) { SetupPreviewNode(); } else { m_ToolManager->ActivateTool(-1); } } void mitk::BinaryThresholdTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::BinaryThresholdTool::OnRoiDataChanged); m_NodeForThresholding = NULL; m_OriginalImageNode = NULL; try { if (DataStorage* storage = m_ToolManager->GetDataStorage()) { storage->Remove(m_ThresholdFeedbackNode); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch (...) { // don't care } m_ThresholdFeedbackNode->SetData(NULL); Superclass::Deactivated(); } void mitk::BinaryThresholdTool::SetThresholdValue(double value) { if (m_ThresholdFeedbackNode.IsNotNull()) { m_CurrentThresholdValue = value; // Bug 19250: The range of 0.01 is rather random. It was 0.001 before and probably due to rounding error propagation in VTK code // it leads to strange banding effects on floating point images with a huge range (like -40000 - 40000). 0.01 lowers this effect // enough to work with our images. Might not work on images with really huge ranges, though. Anyways, still seems to be low enough // to work for floating point images with a range between 0 and 1. A better solution might be to dynamically calculate the value // based on the value range of the current image (as big as possible, as small as necessary). - m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 0.01) ) ); + //m_ThresholdFeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(m_CurrentThresholdValue, 0.01) ) ); UpdatePreview(); } } void mitk::BinaryThresholdTool::AcceptCurrentThresholdValue() { CreateNewSegmentationFromThreshold(m_NodeForThresholding); RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::CancelThresholding() { m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdTool::SetupPreviewNode() { + itk::RGBPixel pixel; + pixel[0] = 0.0f; + pixel[1] = 1.0f; + pixel[2] = 0.0f; + if (m_NodeForThresholding.IsNotNull()) { Image::Pointer image = dynamic_cast(m_NodeForThresholding->GetData()); Image::Pointer originalImage = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { - mitk::Image* workingimage = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); + mitk::LabelSetImage::Pointer workingImage = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); - if (workingimage) + if (workingImage.IsNotNull()) { - m_ThresholdFeedbackNode->SetData(workingimage->Clone()); + m_ThresholdFeedbackNode->SetData(workingImage->Clone()); + m_IsOldBinary = false; //Let's paint the feedback node green... mitk::LabelSetImage::Pointer previewImage = dynamic_cast (m_ThresholdFeedbackNode->GetData()); - itk::RGBPixel pixel; - pixel[0] = 0.0f; - pixel[1] = 1.0f; - pixel[2] = 0.0f; + if(previewImage.IsNull()) + { + MITK_ERROR << "Cannot create helper objects."; + return; + } + previewImage->GetActiveLabel()->SetColor(pixel); previewImage->GetActiveLabelSet()->UpdateLookupTable(previewImage->GetActiveLabel()->GetValue()); } else - m_ThresholdFeedbackNode->SetData(mitk::Image::New()); + { + mitk::Image::Pointer workingImageBin = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); + if(workingImageBin) + { + m_ThresholdFeedbackNode->SetData( workingImageBin->Clone() ); + m_IsOldBinary = true; + } + else + m_ThresholdFeedbackNode->SetData( mitk::Image::New() ); + } + + m_ThresholdFeedbackNode->SetColor(pixel); + m_ThresholdFeedbackNode->SetOpacity(0.5); int layer(50); m_NodeForThresholding->GetIntProperty("layer", layer); m_ThresholdFeedbackNode->SetIntProperty("layer", layer + 1); if (DataStorage* ds = m_ToolManager->GetDataStorage()) { if (!ds->Exists(m_ThresholdFeedbackNode)) ds->Add(m_ThresholdFeedbackNode, m_OriginalImageNode); } if (image.GetPointer() == originalImage.GetPointer()) { Image::StatisticsHolderPointer statistics = originalImage->GetStatistics(); m_SensibleMinimumThresholdValue = static_cast(statistics->GetScalarValueMin()); m_SensibleMaximumThresholdValue = static_cast(statistics->GetScalarValueMax()); } if ((originalImage->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR) && (originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::FLOAT || originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::DOUBLE)) m_IsFloatImage = true; else m_IsFloatImage = false; m_CurrentThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue) / 2.0; IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue, m_IsFloatImage); ThresholdingValueChanged.Send(m_CurrentThresholdValue); } } } template static void ITKSetVolume(itk::Image* originalImage, mitk::Image* segmentation, unsigned int timeStep) { segmentation->SetVolume((void*)originalImage->GetPixelContainer()->GetBufferPointer(), timeStep); } void mitk::BinaryThresholdTool::CreateNewSegmentationFromThreshold(DataNode* node) { if (node) { Image::Pointer feedBackImage = dynamic_cast(m_ThresholdFeedbackNode->GetData()); if (feedBackImage.IsNotNull()) { DataNode::Pointer emptySegmentation = GetTargetSegmentationNode(); if (emptySegmentation) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < feedBackImage->GetTimeSteps(); ++timeStep) { try { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput(feedBackImage); timeSelector->SetTimeNr(timeStep); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer image3D = timeSelector->GetOutput(); if (image3D->GetDimension() == 2) { AccessFixedDimensionByItk_2(image3D, ITKSetVolume, 2, dynamic_cast(emptySegmentation->GetData()), timeStep); } else { AccessFixedDimensionByItk_2(image3D, ITKSetVolume, 3, dynamic_cast(emptySegmentation->GetData()), timeStep); } } catch (...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); } } if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, dynamic_cast (emptySegmentation->GetData())); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); emptySegmentation->SetData(padFilter->GetOutput()); } m_ToolManager->SetWorkingData(emptySegmentation); m_ToolManager->GetWorkingData(0)->Modified(); } } } } void mitk::BinaryThresholdTool::OnRoiDataChanged() { mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); mitk::Image::Pointer image = dynamic_cast (m_NodeForThresholding->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_SensibleMaximumThresholdValue = static_cast (roiFilter->GetMaxValue()); m_SensibleMinimumThresholdValue = static_cast (roiFilter->GetMinValue()); m_NodeForThresholding = tmpNode; } else { m_NodeForThresholding = m_OriginalImageNode; } this->SetupPreviewNode(); this->UpdatePreview(); } template void mitk::BinaryThresholdTool::ITKThresholding(itk::Image* originalImage, Image* segmentation, double thresholdValue, unsigned int timeStep) { typedef itk::Image ImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); filter->SetInput(originalImage); filter->SetLowerThreshold(thresholdValue); filter->SetUpperThreshold(m_SensibleMaximumThresholdValue); filter->SetInsideValue(1); filter->SetOutsideValue(0); filter->Update(); segmentation->SetVolume((void*)(filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep); } +template +void mitk::BinaryThresholdTool::ITKThresholdingOldBinary( itk::Image* originalImage, Image* segmentation, double thresholdValue, unsigned int timeStep) +{ + typedef itk::Image ImageType; + typedef itk::Image SegmentationType; + typedef itk::BinaryThresholdImageFilter ThresholdFilterType; + + typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); + filter->SetInput(originalImage); + filter->SetLowerThreshold(thresholdValue); + filter->SetUpperThreshold(m_SensibleMaximumThresholdValue); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->Update(); + segmentation->SetVolume( (void*) (filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep); +} void mitk::BinaryThresholdTool::UpdatePreview() { mitk::Image::Pointer thresholdImage = dynamic_cast (m_NodeForThresholding->GetData()); - mitk::LabelSetImage::Pointer previewImage = dynamic_cast (m_ThresholdFeedbackNode->GetData()); + mitk::Image::Pointer previewImage = dynamic_cast (m_ThresholdFeedbackNode->GetData()); if (thresholdImage && previewImage) { for (unsigned int timeStep = 0; timeStep < thresholdImage->GetTimeSteps(); ++timeStep) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput(thresholdImage); timeSelector->SetTimeNr(timeStep); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer feedBackImage3D = timeSelector->GetOutput(); - AccessByItk_n(feedBackImage3D, ITKThresholding, (previewImage, m_CurrentThresholdValue, timeStep)); + + if(m_IsOldBinary) + { + AccessByItk_n(feedBackImage3D, ITKThresholdingOldBinary, (previewImage, m_CurrentThresholdValue, timeStep)); + } + else + { + AccessByItk_n(feedBackImage3D, ITKThresholding, (previewImage, m_CurrentThresholdValue, timeStep)); + } } RenderingManager::GetInstance()->RequestUpdateAll(); } } diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.h b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.h index ccaa7b2c94..f192cd7c00 100644 --- a/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.h +++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdTool.h @@ -1,95 +1,98 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkBinaryThresholdTool_h_Included #define mitkBinaryThresholdTool_h_Included #include "mitkCommon.h" #include #include "mitkAutoSegmentationTool.h" #include "mitkDataNode.h" #include namespace us { class ModuleResource; } namespace mitk { /** \brief Calculates the segmented volumes for binary images. \ingroup ToolManagerEtAl \sa mitk::Tool \sa QmitkInteractiveSegmentation Last contributor: $Author$ */ class MITKSEGMENTATION_EXPORT BinaryThresholdTool : public AutoSegmentationTool { public: Message3 IntervalBordersChanged; Message1 ThresholdingValueChanged; mitkClassMacro(BinaryThresholdTool, AutoSegmentationTool); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const char** GetXPM() const override; us::ModuleResource GetIconResource() const override; virtual const char* GetName() const override; virtual void Activated() override; virtual void Deactivated() override; virtual void SetThresholdValue(double value); virtual void AcceptCurrentThresholdValue(); virtual void CancelThresholding(); protected: BinaryThresholdTool(); // purposely hidden virtual ~BinaryThresholdTool(); void SetupPreviewNode(); void CreateNewSegmentationFromThreshold(DataNode* node); void OnRoiDataChanged(); void UpdatePreview(); template void ITKThresholding( itk::Image* originalImage, mitk::Image* segmentation, double thresholdValue, unsigned int timeStep ); + template + void ITKThresholdingOldBinary( itk::Image* originalImage, mitk::Image* segmentation, double thresholdValue, unsigned int timeStep ); DataNode::Pointer m_ThresholdFeedbackNode; DataNode::Pointer m_OriginalImageNode; DataNode::Pointer m_NodeForThresholding; double m_SensibleMinimumThresholdValue; double m_SensibleMaximumThresholdValue; double m_CurrentThresholdValue; bool m_IsFloatImage; + bool m_IsOldBinary = false; }; } // namespace #endif diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp index 3a53f7e173..3b5efa251b 100644 --- a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp +++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp @@ -1,347 +1,392 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBinaryThresholdULTool.h" #include "mitkToolManager.h" #include "mitkLevelWindowProperty.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkDataStorage.h" #include "mitkRenderingManager.h" #include #include "mitkImageCast.h" #include "mitkImageAccessByItk.h" #include "mitkImageStatisticsHolder.h" #include "mitkImageTimeSelector.h" #include #include #include "mitkMaskAndCutRoiImageFilter.h" #include "mitkPadImageFilter.h" #include "mitkLabelSetImage.h" // us #include "usModule.h" #include "usModuleResource.h" #include "usGetModuleContext.h" #include "usModuleContext.h" namespace mitk { MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, BinaryThresholdULTool, "ThresholdingUL tool"); } mitk::BinaryThresholdULTool::BinaryThresholdULTool() :m_SensibleMinimumThresholdValue(-100), m_SensibleMaximumThresholdValue(+100), m_CurrentLowerThresholdValue(1), m_CurrentUpperThresholdValue(1) { m_ThresholdFeedbackNode = DataNode::New(); m_ThresholdFeedbackNode->SetProperty( "color", ColorProperty::New(0.0, 1.0, 0.0) ); m_ThresholdFeedbackNode->SetProperty( "name", StringProperty::New("Thresholding feedback") ); m_ThresholdFeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) ); m_ThresholdFeedbackNode->SetProperty("binary", BoolProperty::New(true)); m_ThresholdFeedbackNode->SetProperty( "helper object", BoolProperty::New(true) ); } mitk::BinaryThresholdULTool::~BinaryThresholdULTool() { } const char** mitk::BinaryThresholdULTool::GetXPM() const { return NULL; } us::ModuleResource mitk::BinaryThresholdULTool::GetIconResource() const { us::Module* module = us::GetModuleContext()->GetModule(); us::ModuleResource resource = module->GetResource("TwoThresholds_48x48.png"); return resource; } const char* mitk::BinaryThresholdULTool::GetName() const { return "UL Threshold"; } void mitk::BinaryThresholdULTool::Activated() { Superclass::Activated(); m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::BinaryThresholdULTool::OnRoiDataChanged); m_OriginalImageNode = m_ToolManager->GetReferenceData(0); m_NodeForThresholding = m_OriginalImageNode; if ( m_NodeForThresholding.IsNotNull() ) { SetupPreviewNode(); } else { m_ToolManager->ActivateTool(-1); } } void mitk::BinaryThresholdULTool::Deactivated() { m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::BinaryThresholdULTool::OnRoiDataChanged); m_NodeForThresholding = NULL; m_OriginalImageNode = NULL; try { if (DataStorage* storage = m_ToolManager->GetDataStorage()) { storage->Remove( m_ThresholdFeedbackNode ); RenderingManager::GetInstance()->RequestUpdateAll(); } } catch(...) { // don't care } m_ThresholdFeedbackNode->SetData(NULL); Superclass::Deactivated(); } void mitk::BinaryThresholdULTool::SetThresholdValues(double lower, double upper) { if (m_ThresholdFeedbackNode.IsNotNull()) { m_CurrentLowerThresholdValue = lower; m_CurrentUpperThresholdValue = upper; UpdatePreview(); } } void mitk::BinaryThresholdULTool::AcceptCurrentThresholdValue() { CreateNewSegmentationFromThreshold(m_NodeForThresholding); RenderingManager::GetInstance()->RequestUpdateAll(); m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdULTool::CancelThresholding() { m_ToolManager->ActivateTool(-1); } void mitk::BinaryThresholdULTool::SetupPreviewNode() { + itk::RGBPixel pixel; + pixel[0] = 0.0f; + pixel[1] = 1.0f; + pixel[2] = 0.0f; + if (m_NodeForThresholding.IsNotNull()) { Image::Pointer image = dynamic_cast( m_NodeForThresholding->GetData() ); Image::Pointer originalImage = dynamic_cast (m_OriginalImageNode->GetData()); if (image.IsNotNull()) { - mitk::Image* workingimage = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); + mitk::LabelSetImage::Pointer workingImage = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); - if (workingimage) + if (workingImage.IsNotNull()) { - m_ThresholdFeedbackNode->SetData(workingimage->Clone()); + m_ThresholdFeedbackNode->SetData(workingImage->Clone()); + m_IsOldBinary = false; //Let's paint the feedback node green... mitk::LabelSetImage::Pointer previewImage = dynamic_cast (m_ThresholdFeedbackNode->GetData()); - itk::RGBPixel pixel; - pixel[0] = 0.0f; - pixel[1] = 1.0f; - pixel[2] = 0.0f; + if(previewImage.IsNull()) + { + MITK_ERROR << "Cannot create helper objects."; + return; + } + previewImage->GetActiveLabel()->SetColor(pixel); previewImage->GetActiveLabelSet()->UpdateLookupTable(previewImage->GetActiveLabel()->GetValue()); } else - m_ThresholdFeedbackNode->SetData( mitk::Image::New() ); + { + mitk::Image::Pointer workingImageBin = dynamic_cast(m_ToolManager->GetWorkingData(0)->GetData()); + if(workingImageBin) + { + m_ThresholdFeedbackNode->SetData( workingImageBin->Clone() ); + m_IsOldBinary = true; + } + else + m_ThresholdFeedbackNode->SetData( mitk::Image::New() ); + } + + m_ThresholdFeedbackNode->SetColor(pixel); + m_ThresholdFeedbackNode->SetOpacity(0.5); int layer(50); m_NodeForThresholding->GetIntProperty("layer", layer); m_ThresholdFeedbackNode->SetIntProperty("layer", layer+1); if (DataStorage* ds = m_ToolManager->GetDataStorage()) { if (!ds->Exists(m_ThresholdFeedbackNode)) ds->Add( m_ThresholdFeedbackNode, m_OriginalImageNode ); } if (image.GetPointer() == originalImage.GetPointer()) { Image::StatisticsHolderPointer statistics = originalImage->GetStatistics(); m_SensibleMinimumThresholdValue = static_cast( statistics->GetScalarValueMin() ); m_SensibleMaximumThresholdValue = static_cast( statistics->GetScalarValueMax() ); } double range = m_SensibleMaximumThresholdValue - m_SensibleMinimumThresholdValue; m_CurrentLowerThresholdValue = m_SensibleMinimumThresholdValue + range/3.0; m_CurrentUpperThresholdValue = m_SensibleMinimumThresholdValue + 2*range/3.0; bool isFloatImage = false; if ((originalImage->GetPixelType().GetPixelType() == itk::ImageIOBase::SCALAR) &&(originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::FLOAT || originalImage->GetPixelType().GetComponentType() == itk::ImageIOBase::DOUBLE)) { isFloatImage = true; } IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue, isFloatImage); ThresholdingValuesChanged.Send(m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue); } } } template static void ITKSetVolume( itk::Image* originalImage, mitk::Image* segmentation, unsigned int timeStep ) { segmentation->SetVolume( (void*) originalImage->GetPixelContainer()->GetBufferPointer(), timeStep); } void mitk::BinaryThresholdULTool::CreateNewSegmentationFromThreshold(DataNode* node) { if (node) { Image::Pointer feedBackImage = dynamic_cast( m_ThresholdFeedbackNode->GetData() ); if (feedBackImage.IsNotNull()) { // create a new image of the same dimensions and smallest possible pixel type DataNode::Pointer emptySegmentation = GetTargetSegmentationNode(); if (emptySegmentation) { // actually perform a thresholding and ask for an organ type for (unsigned int timeStep = 0; timeStep < feedBackImage->GetTimeSteps(); ++timeStep) { try { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( feedBackImage ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer feedBackImage3D = timeSelector->GetOutput(); if (feedBackImage3D->GetDimension() == 2) { AccessFixedDimensionByItk_2( feedBackImage3D, ITKSetVolume, 2, dynamic_cast(emptySegmentation->GetData()), timeStep ); } else { AccessFixedDimensionByItk_2( feedBackImage3D, ITKSetVolume, 3, dynamic_cast(emptySegmentation->GetData()), timeStep ); } } catch(...) { Tool::ErrorMessage("Error accessing single time steps of the original image. Cannot create segmentation."); } } //since we are maybe working on a smaller image, pad it to the size of the original image if (m_OriginalImageNode.GetPointer() != m_NodeForThresholding.GetPointer()) { mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New(); padFilter->SetInput(0, dynamic_cast (emptySegmentation->GetData())); padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData())); padFilter->SetBinaryFilter(true); padFilter->SetUpperThreshold(1); padFilter->SetLowerThreshold(1); padFilter->Update(); emptySegmentation->SetData(padFilter->GetOutput()); } m_ToolManager->SetWorkingData( emptySegmentation ); m_ToolManager->GetWorkingData(0)->Modified(); } } } } void mitk::BinaryThresholdULTool::OnRoiDataChanged() { mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0); if (node.IsNotNull()) { mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New(); mitk::Image::Pointer image = dynamic_cast (m_NodeForThresholding->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_SensibleMinimumThresholdValue = static_cast( roiFilter->GetMinValue()); m_SensibleMaximumThresholdValue = static_cast( roiFilter->GetMaxValue()); m_NodeForThresholding = tmpNode; } else m_NodeForThresholding = m_OriginalImageNode; this->SetupPreviewNode(); this->UpdatePreview(); } template static void ITKThresholding( itk::Image* originalImage, mitk::Image* segmentation, double lower, double upper, unsigned int timeStep ) { typedef itk::Image ImageType; typedef itk::Image SegmentationType; typedef itk::BinaryThresholdImageFilter ThresholdFilterType; typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); filter->SetInput(originalImage); filter->SetLowerThreshold(lower); filter->SetUpperThreshold(upper); filter->SetInsideValue(1); filter->SetOutsideValue(0); filter->Update(); segmentation->SetVolume( (void*) (filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep); } +template +static void ITKThresholdingOldBinary( itk::Image* originalImage, mitk::Image* segmentation, double lower, double upper, unsigned int timeStep ) +{ + typedef itk::Image ImageType; + typedef itk::Image SegmentationType; + typedef itk::BinaryThresholdImageFilter ThresholdFilterType; + + typename ThresholdFilterType::Pointer filter = ThresholdFilterType::New(); + filter->SetInput(originalImage); + filter->SetLowerThreshold(lower); + filter->SetUpperThreshold(upper); + filter->SetInsideValue(1); + filter->SetOutsideValue(0); + filter->Update(); + + segmentation->SetVolume( (void*) (filter->GetOutput()->GetPixelContainer()->GetBufferPointer()), timeStep); +} + void mitk::BinaryThresholdULTool::UpdatePreview() { mitk::Image::Pointer thresholdImage = dynamic_cast (m_NodeForThresholding->GetData()); mitk::Image::Pointer previewImage = dynamic_cast (m_ThresholdFeedbackNode->GetData()); if(thresholdImage && previewImage) { for (unsigned int timeStep = 0; timeStep < thresholdImage->GetTimeSteps(); ++timeStep) { ImageTimeSelector::Pointer timeSelector = ImageTimeSelector::New(); timeSelector->SetInput( thresholdImage ); timeSelector->SetTimeNr( timeStep ); timeSelector->UpdateLargestPossibleRegion(); Image::Pointer feedBackImage3D = timeSelector->GetOutput(); - AccessByItk_n(feedBackImage3D, ITKThresholding, (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep)); + if(m_IsOldBinary) + { + AccessByItk_n(feedBackImage3D, ITKThresholdingOldBinary, (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep)); + } + else + { + AccessByItk_n(feedBackImage3D, ITKThresholding, (previewImage, m_CurrentLowerThresholdValue, m_CurrentUpperThresholdValue, timeStep)); + } } RenderingManager::GetInstance()->RequestUpdateAll(); } } diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.h b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.h index 739b64e747..704ec0536a 100644 --- a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.h +++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.h @@ -1,98 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkBinaryThresholdULTool_h_Included #define mitkBinaryThresholdULTool_h_Included #include "mitkCommon.h" #include #include "mitkAutoSegmentationTool.h" #include "mitkDataNode.h" #include #include namespace us { class ModuleResource; } namespace mitk { /** \brief Calculates the segmented volumes for binary images. \ingroup ToolManagerEtAl \sa mitk::Tool \sa QmitkInteractiveSegmentation Last contributor: $Author$ */ class MITKSEGMENTATION_EXPORT BinaryThresholdULTool : public AutoSegmentationTool { public: Message3 IntervalBordersChanged; Message2 ThresholdingValuesChanged; mitkClassMacro(BinaryThresholdULTool, AutoSegmentationTool); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const char** GetXPM() const override; us::ModuleResource GetIconResource() const override; virtual const char* GetName() const override; virtual void Activated() override; virtual void Deactivated() override; virtual void SetThresholdValues(double lower, double upper); virtual void AcceptCurrentThresholdValue(); virtual void CancelThresholding(); protected: BinaryThresholdULTool(); // purposely hidden virtual ~BinaryThresholdULTool(); void SetupPreviewNode(); void CreateNewSegmentationFromThreshold(DataNode* node); void OnRoiDataChanged(); void UpdatePreview(); DataNode::Pointer m_ThresholdFeedbackNode; DataNode::Pointer m_OriginalImageNode; DataNode::Pointer m_NodeForThresholding; mitk::ScalarType m_SensibleMinimumThresholdValue; mitk::ScalarType m_SensibleMaximumThresholdValue; mitk::ScalarType m_CurrentLowerThresholdValue; mitk::ScalarType m_CurrentUpperThresholdValue; + bool m_IsOldBinary = false; + typedef itk::Image ImageType; typedef itk::Image< Tool::DefaultSegmentationDataType, 3> SegmentationType; // this is sure for new segmentations typedef itk::BinaryThresholdImageFilter ThresholdFilterType; ThresholdFilterType::Pointer m_ThresholdFilter; }; } // namespace #endif