diff --git a/Modules/QtWidgets/LabelSetImage_48.png b/Modules/QtWidgets/LabelSetImage_48.png
new file mode 100644
index 0000000000..b1117f4696
Binary files /dev/null and b/Modules/QtWidgets/LabelSetImage_48.png differ
diff --git a/Modules/QtWidgets/resource/Qmitk.qrc b/Modules/QtWidgets/resource/Qmitk.qrc
index ba779c5657..2b4501588d 100644
--- a/Modules/QtWidgets/resource/Qmitk.qrc
+++ b/Modules/QtWidgets/resource/Qmitk.qrc
@@ -1,14 +1,15 @@
-
+
Binaerbilder_48.png
Images_48.png
PointSet_48.png
Segmentation_48.png
Surface_48.png
mm_pointer.png
mm_scroll.png
mm_zoom.png
mm_contrast.png
mm_pan.png
+ LabelSetImage_48.png
diff --git a/Modules/QtWidgets/src/QmitkNodeDescriptorManager.cpp b/Modules/QtWidgets/src/QmitkNodeDescriptorManager.cpp
index 2969362b5b..da0344c151 100644
--- a/Modules/QtWidgets/src/QmitkNodeDescriptorManager.cpp
+++ b/Modules/QtWidgets/src/QmitkNodeDescriptorManager.cpp
@@ -1,180 +1,184 @@
/*===================================================================
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 "QmitkNodeDescriptorManager.h"
#include
#include
#include
#include
#include
#include
#include
#include
QmitkNodeDescriptorManager* QmitkNodeDescriptorManager::GetInstance()
{
static QmitkNodeDescriptorManager _Instance;
return &_Instance;
/*
static std::auto_ptr instance;
if(instance.get() == 0)
{
instance.reset(new QmitkNodeDescriptorManager());
instance->Initialize();
}
return instance.get();*/
}
void QmitkNodeDescriptorManager::Initialize()
{
// Adding "Images"
mitk::NodePredicateDataType::Pointer isImage = mitk::NodePredicateDataType::New("Image");
this->AddDescriptor(new QmitkNodeDescriptor(tr("Image"), QString(":/Qmitk/Images_48.png"), isImage, this));
// Adding "Image Masks"
mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
mitk::NodePredicateAnd::Pointer isBinaryImage = mitk::NodePredicateAnd::New(isBinary, isImage);
this->AddDescriptor(new QmitkNodeDescriptor(tr("ImageMask"), QString(":/Qmitk/Binaerbilder_48.png"), isBinaryImage, this));
+ // Adding "LabelSet Image"
+ mitk::NodePredicateDataType::Pointer isLabelSetImage = mitk::NodePredicateDataType::New("LabelSetImage");
+ this->AddDescriptor(new QmitkNodeDescriptor(tr("LabelSetImage"), QString(":/Qmitk/LabelSetImage_48.png"), isLabelSetImage, this));
+
// Adding "PointSet"
mitk::NodePredicateDataType::Pointer isPointSet = mitk::NodePredicateDataType::New("PointSet");
this->AddDescriptor(new QmitkNodeDescriptor(tr("PointSet"), QString(":/Qmitk/PointSet_48.png"), isPointSet, this));
// Adding "Surface"
mitk::NodePredicateDataType::Pointer isSurface = mitk::NodePredicateDataType::New("Surface");
this->AddDescriptor(new QmitkNodeDescriptor(tr("Surface"), QString(":/Qmitk/Surface_48.png"), isSurface, this));
// Adding "NoneBinaryImages"
mitk::NodePredicateNot::Pointer isNotBinary = mitk::NodePredicateNot::New(isBinary);
mitk::NodePredicateAnd::Pointer isNoneBinaryImage = mitk::NodePredicateAnd::New(isImage, isNotBinary);
this->AddDescriptor(new QmitkNodeDescriptor(tr("NoneBinaryImage"), QString(":/Qmitk/Images_48.png"), isNoneBinaryImage, this));
}
void QmitkNodeDescriptorManager::AddDescriptor( QmitkNodeDescriptor* _Descriptor )
{
_Descriptor->setParent(this);
m_NodeDescriptors.push_back(_Descriptor);
}
void QmitkNodeDescriptorManager::RemoveDescriptor( QmitkNodeDescriptor* _Descriptor )
{
int index = m_NodeDescriptors.indexOf(_Descriptor);
if(index != -1)
{
m_NodeDescriptors.removeAt(index);
_Descriptor->setParent(0);
delete _Descriptor;
}
}
QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const mitk::DataNode* _Node ) const
{
QmitkNodeDescriptor* _Descriptor = m_UnknownDataNodeDescriptor;
for(QList::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
{
if((*it)->CheckNode(_Node))
_Descriptor = *it;
}
return _Descriptor;
}
QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetDescriptor( const QString& _ClassName ) const
{
QmitkNodeDescriptor* _Descriptor = 0;
if( _ClassName == "Unknown" )
{
return m_UnknownDataNodeDescriptor;
}
else
{
for(QList::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
{
if((*it)->GetClassName() == _ClassName)
_Descriptor = *it;
}
}
return _Descriptor;
}
QList QmitkNodeDescriptorManager::GetActions( const mitk::DataNode* _Node ) const
{
QList actions = m_UnknownDataNodeDescriptor->GetBatchActions();
actions.append(m_UnknownDataNodeDescriptor->GetActions());
QmitkNodeDescriptor* lastDescriptor = m_UnknownDataNodeDescriptor;
for(QList::const_iterator it = m_NodeDescriptors.begin(); it != m_NodeDescriptors.end(); ++it)
{
if((*it)->CheckNode(_Node))
{
actions.append(lastDescriptor->GetSeparator());
lastDescriptor = *it;
actions.append(lastDescriptor->GetBatchActions());
actions.append(lastDescriptor->GetActions());
}
}
return actions;
}
QList QmitkNodeDescriptorManager::GetActions( const QList &_Nodes ) const
{
QList actions = m_UnknownDataNodeDescriptor->GetBatchActions();
QSet nodeDescriptors;
QmitkNodeDescriptor* lastDescriptor;
// find all descriptors for the nodes (unique)
foreach (mitk::DataNode::Pointer node, _Nodes)
{
lastDescriptor = this->GetDescriptor(node);
nodeDescriptors.insert(lastDescriptor);
}
// add all actions for the found descriptors
lastDescriptor = m_UnknownDataNodeDescriptor;
foreach (QmitkNodeDescriptor* descr, nodeDescriptors)
{
actions.append(lastDescriptor->GetSeparator());
lastDescriptor = descr;
actions.append(lastDescriptor->GetBatchActions());
}
return actions;
}
QmitkNodeDescriptorManager::QmitkNodeDescriptorManager()
: m_UnknownDataNodeDescriptor(new QmitkNodeDescriptor("Unknown", QString(":/Qmitk/DataTypeUnknown_48.png"), 0, this))
{
this->Initialize();
}
QmitkNodeDescriptorManager::~QmitkNodeDescriptorManager()
{
//delete m_UnknownDataNodeDescriptor;
//qDeleteAll(m_NodeDescriptors);
}
QmitkNodeDescriptor* QmitkNodeDescriptorManager::GetUnknownDataNodeDescriptor() const
{
return m_UnknownDataNodeDescriptor;
}
diff --git a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp
index e96bfe4518..ae9e1495e4 100644
--- a/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkBinaryThresholdULTool.cpp
@@ -1,321 +1,321 @@
/*===================================================================
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 "mitkBinaryThresholdULTool.xpm"
#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 "mitkImageTimeSelector.h"
#include
#include
#include "mitkMaskAndCutRoiImageFilter.h"
#include "mitkPadImageFilter.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()
{
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);
}
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()
{
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());
if(workingimage)
m_ThresholdFeedbackNode->SetData( workingimage->Clone() );
else
m_ThresholdFeedbackNode->SetData( mitk::Image::New() );
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())
{
m_SensibleMinimumThresholdValue = static_cast( originalImage->GetScalarValueMin() );
m_SensibleMaximumThresholdValue = static_cast( originalImage->GetScalarValueMax() );
}
m_CurrentLowerThresholdValue = (m_SensibleMaximumThresholdValue + m_SensibleMinimumThresholdValue) / 3.0;
m_CurrentUpperThresholdValue = 2.0 * m_CurrentLowerThresholdValue;
IntervalBordersChanged.Send(m_SensibleMinimumThresholdValue, m_SensibleMaximumThresholdValue);
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::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));
}
RenderingManager::GetInstance()->RequestUpdateAll();
}
}
diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool.h b/Modules/Segmentation/Interactions/mitkFastMarchingTool.h
index 761545fcc5..f987cba635 100644
--- a/Modules/Segmentation/Interactions/mitkFastMarchingTool.h
+++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool.h
@@ -1,184 +1,184 @@
/*===================================================================
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 mitkFastMarchingTool_h_Included
#define mitkFastMarchingTool_h_Included
#include "mitkFeedbackContourTool.h"
#include "mitkLegacyAdaptors.h"
#include
#include "mitkDataNode.h"
#include "mitkPointSet.h"
#include "mitkToolCommand.h"
#include "mitkPositionEvent.h"
#include "mitkMessage.h"
#include "itkImage.h"
//itk filter
#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
namespace us {
class ModuleResource;
}
namespace mitk
{
class StateMachineAction;
class InteractionEvent;
/**
\brief FastMarching semgentation tool.
The segmentation is done by setting one or more seed points on the image
and adapting the time range and threshold. The pipeline is:
Smoothing->GradientMagnitude->SigmoidFunction->FastMarching->Threshold
The resulting binary image is seen as a segmentation of an object.
For detailed documentation see ITK Software Guide section 9.3.1 Fast Marching Segmentation.
*/
class MITKSEGMENTATION_EXPORT FastMarchingTool : public FeedbackContourTool
{
mitkNewMessageMacro(Ready);
public:
mitkClassMacro(FastMarchingTool, FeedbackContourTool);
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/* typedefs for itk pipeline */
typedef float InternalPixelType;
typedef itk::Image< InternalPixelType, 2 > InternalImageType;
- typedef unsigned char OutputPixelType;
+ typedef mitk::Tool::DefaultSegmentationDataType OutputPixelType;
typedef itk::Image< OutputPixelType, 2 > OutputImageType;
typedef itk::BinaryThresholdImageFilter< InternalImageType, OutputImageType > ThresholdingFilterType;
typedef itk::CurvatureAnisotropicDiffusionImageFilter< InternalImageType, InternalImageType > SmoothingFilterType;
typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< InternalImageType, InternalImageType > GradientFilterType;
typedef itk::SigmoidImageFilter< InternalImageType, InternalImageType > SigmoidFilterType;
typedef itk::FastMarchingImageFilter< InternalImageType, InternalImageType > FastMarchingFilterType;
typedef FastMarchingFilterType::NodeContainer NodeContainer;
typedef FastMarchingFilterType::NodeType NodeType;
/* icon stuff */
virtual const char** GetXPM() const override;
virtual const char* GetName() const override;
virtual us::ModuleResource GetCursorIconResource() const override;
us::ModuleResource GetIconResource() const override;
/// \brief Set parameter used in Threshold filter.
void SetUpperThreshold(double);
/// \brief Set parameter used in Threshold filter.
void SetLowerThreshold(double);
/// \brief Set parameter used in Fast Marching filter.
void SetStoppingValue(double);
/// \brief Set parameter used in Gradient Magnitude filter.
void SetSigma(double);
/// \brief Set parameter used in Fast Marching filter.
void SetAlpha(double);
/// \brief Set parameter used in Fast Marching filter.
void SetBeta(double);
/// \brief Adds the feedback image to the current working image.
virtual void ConfirmSegmentation();
/// \brief Set the working time step.
virtual void SetCurrentTimeStep(int t);
/// \brief Clear all seed points.
void ClearSeeds();
/// \brief Updates the itk pipeline and shows the result of FastMarching.
void Update();
protected:
FastMarchingTool();
virtual ~FastMarchingTool();
void ConnectActionsAndFunctions() override;
//virtual float CanHandleEvent( StateEvent const *stateEvent) const;
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Initialize();
virtual void BuildITKPipeline();
/// \brief Add point action of StateMachine pattern
virtual bool OnAddPoint ( StateMachineAction*, InteractionEvent* interactionEvent );
/// \brief Delete action of StateMachine pattern
virtual bool OnDelete ( StateMachineAction*, InteractionEvent* interactionEvent );
/// \brief Reset all relevant inputs of the itk pipeline.
void Reset();
mitk::ToolCommand::Pointer m_ProgressCommand;
Image::Pointer m_ReferenceImage;
Image::Pointer m_ReferenceImageSlice;
bool m_NeedUpdate;
int m_CurrentTimeStep;
mitk::InteractionPositionEvent::Pointer m_PositionEvent;
float m_LowerThreshold; //used in Threshold filter
float m_UpperThreshold; //used in Threshold filter
float m_StoppingValue; //used in Fast Marching filter
float m_Sigma; //used in GradientMagnitude filter
float m_Alpha; //used in Sigmoid filter
float m_Beta; //used in Sigmoid filter
NodeContainer::Pointer m_SeedContainer; //seed points for FastMarching
InternalImageType::Pointer m_ReferenceImageSliceAsITK; //the reference image as itk::Image
mitk::DataNode::Pointer m_ResultImageNode;//holds the result as a preview image
mitk::DataNode::Pointer m_SeedsAsPointSetNode;//used to visualize the seed points
mitk::PointSet::Pointer m_SeedsAsPointSet;
ThresholdingFilterType::Pointer m_ThresholdFilter;
SmoothingFilterType::Pointer m_SmoothFilter;
GradientFilterType::Pointer m_GradientMagnitudeFilter;
SigmoidFilterType::Pointer m_SigmoidFilter;
FastMarchingFilterType::Pointer m_FastMarchingFilter;
private:
PlaneGeometry::Pointer m_WorkingPlane;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
index d80548d0bc..52da82660d 100644
--- a/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
+++ b/Modules/Segmentation/Interactions/mitkFastMarchingTool3D.h
@@ -1,171 +1,171 @@
/*===================================================================
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 mitkFastMarchingTool3D_h_Included
#define mitkFastMarchingTool3D_h_Included
#include "mitkAutoSegmentationTool.h"
#include "mitkLegacyAdaptors.h"
#include
#include "mitkDataNode.h"
#include "mitkPointSet.h"
#include "mitkPointSetInteractor.h"
#include "mitkToolCommand.h"
#include "mitkMessage.h"
#include "itkImage.h"
//itk filter
#include "itkFastMarchingImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
#include "itkSigmoidImageFilter.h"
#include "itkCurvatureAnisotropicDiffusionImageFilter.h"
namespace us {
class ModuleResource;
}
namespace mitk
{
/**
\brief FastMarching semgentation tool.
The segmentation is done by setting one or more seed points on the image
and adapting the time range and threshold. The pipeline is:
Smoothing->GradientMagnitude->SigmoidFunction->FastMarching->Threshold
The resulting binary image is seen as a segmentation of an object.
For detailed documentation see ITK Software Guide section 9.3.1 Fast Marching Segmentation.
*/
class MITKSEGMENTATION_EXPORT FastMarchingTool3D : public AutoSegmentationTool
{
mitkNewMessageMacro(Ready);
public:
mitkClassMacro(FastMarchingTool3D, AutoSegmentationTool)
itkFactorylessNewMacro(Self)
itkCloneMacro(Self)
/* typedefs for itk pipeline */
typedef float InternalPixelType;
typedef itk::Image< InternalPixelType, 3 > InternalImageType;
- typedef unsigned char OutputPixelType;
+ typedef mitk::Tool::DefaultSegmentationDataType OutputPixelType;
typedef itk::Image< OutputPixelType, 3 > OutputImageType;
typedef itk::BinaryThresholdImageFilter< InternalImageType, OutputImageType > ThresholdingFilterType;
typedef itk::CurvatureAnisotropicDiffusionImageFilter< InternalImageType, InternalImageType > SmoothingFilterType;
typedef itk::GradientMagnitudeRecursiveGaussianImageFilter< InternalImageType, InternalImageType > GradientFilterType;
typedef itk::SigmoidImageFilter< InternalImageType, InternalImageType > SigmoidFilterType;
typedef itk::FastMarchingImageFilter< InternalImageType, InternalImageType > FastMarchingFilterType;
typedef FastMarchingFilterType::NodeContainer NodeContainer;
typedef FastMarchingFilterType::NodeType NodeType;
bool CanHandle(BaseData* referenceData) const override;
/* icon stuff */
virtual const char** GetXPM() const override;
virtual const char* GetName() const override;
us::ModuleResource GetIconResource() const override;
/// \brief Set parameter used in Threshold filter.
void SetUpperThreshold(double);
/// \brief Set parameter used in Threshold filter.
void SetLowerThreshold(double);
/// \brief Set parameter used in Fast Marching filter.
void SetStoppingValue(double);
/// \brief Set parameter used in Gradient Magnitude filter.
void SetSigma(double);
/// \brief Set parameter used in Fast Marching filter.
void SetAlpha(double);
/// \brief Set parameter used in Fast Marching filter.
void SetBeta(double);
/// \brief Adds the feedback image to the current working image.
virtual void ConfirmSegmentation();
/// \brief Set the working time step.
virtual void SetCurrentTimeStep(int t);
/// \brief Clear all seed points.
void ClearSeeds();
/// \brief Updates the itk pipeline and shows the result of FastMarching.
void Update();
protected:
FastMarchingTool3D();
virtual ~FastMarchingTool3D();
virtual void Activated() override;
virtual void Deactivated() override;
virtual void Initialize();
/// \brief Add point action of StateMachine pattern
virtual void OnAddPoint ();
/// \brief Delete action of StateMachine pattern
virtual void OnDelete ();
/// \brief Reset all relevant inputs of the itk pipeline.
void Reset();
mitk::ToolCommand::Pointer m_ProgressCommand;
Image::Pointer m_ReferenceImage;
bool m_NeedUpdate;
int m_CurrentTimeStep;
float m_LowerThreshold; //used in Threshold filter
float m_UpperThreshold; //used in Threshold filter
float m_StoppingValue; //used in Fast Marching filter
float m_Sigma; //used in GradientMagnitude filter
float m_Alpha; //used in Sigmoid filter
float m_Beta; //used in Sigmoid filter
NodeContainer::Pointer m_SeedContainer; //seed points for FastMarching
InternalImageType::Pointer m_ReferenceImageAsITK; //the reference image as itk::Image
mitk::DataNode::Pointer m_ResultImageNode;//holds the result as a preview image
mitk::DataNode::Pointer m_SeedsAsPointSetNode;//used to visualize the seed points
mitk::PointSet::Pointer m_SeedsAsPointSet;
mitk::PointSetInteractor::Pointer m_SeedPointInteractor;
unsigned int m_PointSetAddObserverTag;
unsigned int m_PointSetRemoveObserverTag;
ThresholdingFilterType::Pointer m_ThresholdFilter;
SmoothingFilterType::Pointer m_SmoothFilter;
GradientFilterType::Pointer m_GradientMagnitudeFilter;
SigmoidFilterType::Pointer m_SigmoidFilter;
FastMarchingFilterType::Pointer m_FastMarchingFilter;
};
} // namespace
#endif
diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
index aabebb886d..1083ef4282 100644
--- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
+++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp
@@ -1,303 +1,303 @@
/*===================================================================
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.
===================================================================*/
// MITK
#include "mitkOtsuTool3D.h"
#include "mitkToolManager.h"
#include "mitkRenderingManager.h"
#include
#include
#include
#include
#include
#include
#include "mitkOtsuSegmentationFilter.h"
#include "mitkImage.h"
#include "mitkImageAccessByItk.h"
// ITK
#include
#include
#include
#include "mitkRegionGrow3DTool.xpm"
// us
#include
#include
#include
#include
#include
namespace mitk {
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, OtsuTool3D, "Otsu Segmentation");
}
mitk::OtsuTool3D::OtsuTool3D()
{
}
mitk::OtsuTool3D::~OtsuTool3D()
{
}
void mitk::OtsuTool3D::Activated()
{
if (m_ToolManager)
{
m_OriginalImage = dynamic_cast(m_ToolManager->GetReferenceData(0)->GetData());
m_BinaryPreviewNode = mitk::DataNode::New();
m_BinaryPreviewNode->SetName("Binary_Preview");
m_BinaryPreviewNode->SetProperty( "color", ColorProperty::New(0.0, 1.0, 0.0) );
m_BinaryPreviewNode->SetProperty( "opacity", FloatProperty::New(0.3) );
//m_BinaryPreviewNode->SetBoolProperty("helper object", true);
//m_BinaryPreviewNode->SetProperty("binary", mitk::BoolProperty::New(true));
m_ToolManager->GetDataStorage()->Add( this->m_BinaryPreviewNode );
m_MultiLabelResultNode = mitk::DataNode::New();
m_MultiLabelResultNode->SetName("Otsu_Preview");
//m_MultiLabelResultNode->SetBoolProperty("helper object", true);
m_MultiLabelResultNode->SetVisibility(true);
m_MaskedImagePreviewNode = mitk::DataNode::New();
m_MaskedImagePreviewNode->SetName("Volume_Preview");
//m_MultiLabelResultNode->SetBoolProperty("helper object", true);
m_MaskedImagePreviewNode->SetVisibility(false);
m_ToolManager->GetDataStorage()->Add( this->m_MultiLabelResultNode );
}
}
void mitk::OtsuTool3D::Deactivated()
{
m_ToolManager->GetDataStorage()->Remove( this->m_MultiLabelResultNode );
m_MultiLabelResultNode = NULL;
m_ToolManager->GetDataStorage()->Remove( this->m_BinaryPreviewNode );
m_BinaryPreviewNode = NULL;
m_ToolManager->GetDataStorage()->Remove( this->m_MaskedImagePreviewNode);
m_MaskedImagePreviewNode = NULL;
}
const char** mitk::OtsuTool3D::GetXPM() const
{
return NULL;
}
us::ModuleResource mitk::OtsuTool3D::GetIconResource() const
{
us::Module* module = us::GetModuleContext()->GetModule();
us::ModuleResource resource = module->GetResource("Otsu_48x48.png");
return resource;
}
void mitk::OtsuTool3D::RunSegmentation(int regions, bool useValley, int numberOfBins)
{
//this->m_OtsuSegmentationDialog->setCursor(Qt::WaitCursor);
int numberOfThresholds = regions - 1;
unsigned int timestep = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->GetPos();
mitk::Image::Pointer image3D = Get3DImage(m_OriginalImage, timestep);
mitk::OtsuSegmentationFilter::Pointer otsuFilter = mitk::OtsuSegmentationFilter::New();
otsuFilter->SetNumberOfThresholds( numberOfThresholds );
otsuFilter->SetValleyEmphasis( useValley );
otsuFilter->SetNumberOfBins( numberOfBins );
otsuFilter->SetInput( image3D );
try
{
otsuFilter->Update();
}
catch( ... )
{
mitkThrow() << "itkOtsuFilter error (image dimension must be in {2, 3} and image must not be RGB)";
}
m_ToolManager->GetDataStorage()->Remove( this->m_MultiLabelResultNode );
m_MultiLabelResultNode = NULL;
m_MultiLabelResultNode = mitk::DataNode::New();
m_MultiLabelResultNode->SetName("Otsu_Preview");
m_MultiLabelResultNode->SetVisibility(true);
m_ToolManager->GetDataStorage()->Add( this->m_MultiLabelResultNode );
m_MultiLabelResultNode->SetOpacity(1.0);
this->m_MultiLabelResultNode->SetData( otsuFilter->GetOutput() );
m_MultiLabelResultNode->SetProperty("binary", mitk::BoolProperty::New(false));
mitk::RenderingModeProperty::Pointer renderingMode = mitk::RenderingModeProperty::New();
renderingMode->SetValue( mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR );
m_MultiLabelResultNode->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);
m_MultiLabelResultNode->SetProperty("LookupTable",prop);
mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New();
mitk::LevelWindow levelwindow;
levelwindow.SetRangeMinMax(0, numberOfThresholds + 1);
levWinProp->SetLevelWindow( levelwindow );
m_MultiLabelResultNode->SetProperty( "levelwindow", levWinProp );
//m_BinaryPreviewNode->SetVisibility(false);
// m_MultiLabelResultNode->SetVisibility(true);
//this->m_OtsuSegmentationDialog->setCursor(Qt::ArrowCursor);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::OtsuTool3D::ConfirmSegmentation()
{
GetTargetSegmentationNode()->SetData(dynamic_cast(m_BinaryPreviewNode->GetData()));
m_ToolManager->ActivateTool(-1);
}
void mitk::OtsuTool3D::UpdateBinaryPreview(std::vector regionIDs)
{
m_MultiLabelResultNode->SetVisibility(false);
mitk::Image::Pointer multiLabelSegmentation = dynamic_cast(m_MultiLabelResultNode->GetData());
AccessByItk_1( multiLabelSegmentation, CalculatePreview, regionIDs);
}
template< typename TPixel, unsigned int VImageDimension>
void mitk::OtsuTool3D::CalculatePreview(itk::Image< TPixel, VImageDimension>* itkImage, std::vector regionIDs)
{
typedef itk::Image< TPixel, VImageDimension > InputImageType;
- typedef itk::Image< unsigned char, VImageDimension > OutputImageType;
+ typedef itk::Image< mitk::Tool::DefaultSegmentationDataType, VImageDimension > OutputImageType;
typedef itk::BinaryThresholdImageFilter< InputImageType, OutputImageType > FilterType;
typename FilterType::Pointer filter = FilterType::New();
//InputImageType::Pointer itkImage;
typename OutputImageType::Pointer itkBinaryTempImage1;
typename OutputImageType::Pointer itkBinaryTempImage2;
typename OutputImageType::Pointer itkBinaryResultImage;
//mitk::Image::Pointer multiLabelSegmentation = dynamic_cast(m_MultiLabelResultNode->GetData());
//mitk::CastToItkImage(multiLabelSegmentation, itkImage);
filter->SetInput(itkImage);
filter->SetLowerThreshold(regionIDs[0]);
filter->SetUpperThreshold(regionIDs[0]);
filter->SetInsideValue(1);
filter->SetOutsideValue(0);
filter->Update();
itkBinaryTempImage2 = filter->GetOutput();
typename itk::OrImageFilter::Pointer orFilter = itk::OrImageFilter::New();
// if more than one region id is used compute the union of all given binary regions
for (std::vector::iterator it = regionIDs.begin() ; it != regionIDs.end(); ++it)
{
filter->SetLowerThreshold(*it);
filter->SetUpperThreshold(*it);
filter->SetInsideValue(1);
filter->SetOutsideValue(0);
filter->Update();
itkBinaryTempImage1 = filter->GetOutput();
orFilter->SetInput1(itkBinaryTempImage1);
orFilter->SetInput2(itkBinaryTempImage2);
orFilter->UpdateLargestPossibleRegion();
itkBinaryResultImage = orFilter->GetOutput();
itkBinaryTempImage2 = itkBinaryResultImage;
}
//----------------------------------------------------------------------------------------------------
mitk::Image::Pointer binarySegmentation;
mitk::CastToMitkImage( itkBinaryResultImage, binarySegmentation);
m_BinaryPreviewNode->SetData(binarySegmentation);
m_BinaryPreviewNode->SetVisibility(true);
m_BinaryPreviewNode->SetProperty("outline binary", mitk::BoolProperty::New(false));
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
//void mitk::OtsuTool3D::UpdateBinaryPreview(int regionID)
//{
// m_MultiLabelResultNode->SetVisibility(false);
// //pixel with regionID -> binary image
// const unsigned short dim = 3;
// typedef unsigned char PixelType;
//
// typedef itk::Image< PixelType, dim > InputImageType;
// typedef itk::Image< PixelType, dim > OutputImageType;
//
// typedef itk::BinaryThresholdImageFilter< InputImageType, OutputImageType > FilterType;
//
// FilterType::Pointer filter = FilterType::New();
//
// InputImageType::Pointer itkImage;
//
// mitk::Image::Pointer multiLabelSegmentation = dynamic_cast(m_MultiLabelResultNode->GetData());
// mitk::CastToItkImage(multiLabelSegmentation, itkImage);
//
// filter->SetInput(itkImage);
// filter->SetLowerThreshold(regionID);
// filter->SetUpperThreshold(regionID);
// filter->SetInsideValue(1);
// filter->SetOutsideValue(0);
// filter->Update();
// mitk::Image::Pointer binarySegmentation;
// mitk::CastToMitkImage( filter->GetOutput(), binarySegmentation);
// m_BinaryPreviewNode->SetData(binarySegmentation);
// m_BinaryPreviewNode->SetVisibility(true);
// m_BinaryPreviewNode->SetProperty("outline binary", mitk::BoolProperty::New(false));
//
// mitk::RenderingManager::GetInstance()->RequestUpdateAll();
//}
const char* mitk::OtsuTool3D::GetName() const
{
return "Otsu";
}
void mitk::OtsuTool3D::UpdateVolumePreview(bool volumeRendering)
{
if (volumeRendering)
{
m_MaskedImagePreviewNode->SetBoolProperty("volumerendering", true);
m_MaskedImagePreviewNode->SetBoolProperty("volumerendering.uselod", true);
}
else
{
m_MaskedImagePreviewNode->SetBoolProperty("volumerendering", false);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::OtsuTool3D::ShowMultiLabelResultNode(bool show)
{
m_MultiLabelResultNode->SetVisibility(show);
m_BinaryPreviewNode->SetVisibility(!show);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
int mitk::OtsuTool3D::GetNumberOfBins()
{
ScalarType min = m_OriginalImage.GetPointer()->GetStatistics()->GetScalarValueMin();
ScalarType max = m_OriginalImage.GetPointer()->GetStatistics()->GetScalarValueMaxNoRecompute();
return static_cast(max-min) + 1;
}
diff --git a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
index e1a3cbb629..818b02df29 100644
--- a/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkRegionGrow3DTool.cpp
@@ -1,439 +1,439 @@
/*===================================================================
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 "mitkRegionGrow3DTool.h"
#include "mitkToolManager.h"
#include "mitkRenderingManager.h"
#include "mitkLevelWindowProperty.h"
#include "mitkPointSetInteractor.h"
#include "mitkGlobalInteraction.h"
#include "mitkITKImageImport.h"
#include "itkImage.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkConnectedAdaptiveThresholdImageFilter.h"
#include "mitkImageCast.h"
#include "mitkImageAccessByItk.h"
#include "mitkMaskAndCutRoiImageFilter.h"
#include "mitkPadImageFilter.h"
#include "mitkRegionGrow3DTool.xpm"
namespace mitk {
MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, RegionGrow3DTool, "RegionGrower 3D");
}
mitk::RegionGrow3DTool::RegionGrow3DTool(): Tool("PressMoveRelease"),
m_LowerThreshold(-5000),
m_UpperThreshold(5000),
m_CurrentRGDirectionIsUpwards(false)
{
CONNECT_FUNCTION( "Release", OnMouseReleased);
m_FeedbackNode = DataNode::New();
m_FeedbackNode->SetProperty( "color", ColorProperty::New(1.0, 0.0, 0.0) );
m_FeedbackNode->SetProperty( "texture interpolation", BoolProperty::New(false) );
m_FeedbackNode->SetProperty( "layer", IntProperty::New( 100 ) );
m_FeedbackNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(100, 1) ) );
m_FeedbackNode->SetProperty( "name", StringProperty::New("failsafe region grow feedback") );
m_FeedbackNode->SetProperty( "opacity", FloatProperty::New(0.3) );
m_FeedbackNode->SetProperty( "helper object", BoolProperty::New(true) );
m_FeedbackNode->SetVisibility(false);
m_PointSetNode = mitk::DataNode::New();
m_PointSetNode->SetName("regiongrow3d pointset");
m_PointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true));
m_PointSetNode->SetProperty("layer", mitk::IntProperty::New(2));
mitk::PointSet::Pointer pointSet = mitk::PointSet::New();
m_PointSetNode->SetData(pointSet);
}
mitk::RegionGrow3DTool::~RegionGrow3DTool()
{
}
bool mitk::RegionGrow3DTool::OnMouseReleased( StateMachineAction*, InteractionEvent* /*interactionEvent*/ )
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor());
if (interactor.IsNotNull())
{
mitk::PointSet::Pointer pointSet = dynamic_cast (m_PointSetNode->GetData());
if (pointSet.IsNotNull())
{
if (pointSet->GetSize() == 1)
{
//check if we have a valid picture
this->RunSegmentation();
SeedButtonToggled.Send(false);
}
}
}
return true;
}
void mitk::RegionGrow3DTool::Activated()
{
if (m_ToolManager)
{
m_ToolManager->RoiDataChanged += mitk::MessageDelegate(this, &mitk::RegionGrow3DTool::UpdatePreview);
m_OriginalImageNode = m_ToolManager->GetReferenceData(0);
m_NodeToProceed = m_OriginalImageNode;
if (m_NodeToProceed.IsNotNull())
{
SetupPreviewNodeFor(m_NodeToProceed);
mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData());
if (image.IsNotNull())
{
m_RoiMin = image->GetScalarValueMin();
m_RoiMax = image->GetScalarValueMax();
}
}
else
m_ToolManager->ActivateTool(-1);
}
}
void mitk::RegionGrow3DTool::Deactivated()
{
m_ToolManager->RoiDataChanged -= mitk::MessageDelegate(this, &mitk::RegionGrow3DTool::UpdatePreview);
if (mitk::DataStorage* ds = m_ToolManager->GetDataStorage())
{
ds->Remove(m_PointSetNode);
ds->Remove(m_FeedbackNode);
}
m_FeedbackNode->SetData(NULL);
m_FeedbackNode->SetLevelWindow(NULL);
m_FeedbackNode->SetVisibility(false);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
const char* mitk::RegionGrow3DTool::GetName() const
{
return "RegionGrower 3D";
}
const char** mitk::RegionGrow3DTool::GetXPM() const
{
return mitkRegionGrow3DTool_xpm;
}
void mitk::RegionGrow3DTool::SetSeedPoint(bool toggled)
{
if (!m_ToolManager->GetDataStorage()->Exists(m_PointSetNode)) //no pointSet present
m_ToolManager->GetDataStorage()->Add(m_PointSetNode, m_OriginalImageNode);
//add Interactor if there is none and add it to GlobalInteraction
if (toggled == true) // button is down
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor());
if (interactor.IsNull())
{
//create a new interactor and add it to node
interactor = mitk::PointSetInteractor::New("singlepointinteractorwithoutshiftclick", m_PointSetNode, 1);
}
mitk::GlobalInteraction::GetInstance()->AddInteractor(interactor);
}
else
{
mitk::PointSetInteractor::Pointer interactor = dynamic_cast (m_PointSetNode->GetInteractor());
if (interactor.IsNotNull())
{
m_PointSetNode->SetInteractor(NULL);
mitk::GlobalInteraction::GetInstance()->RemoveInteractor(interactor);
}
}
}
void mitk::RegionGrow3DTool::RunSegmentation()
{
//safety if no pointSet or pointSet empty
mitk::PointSet::Pointer seedPointSet = dynamic_cast (m_PointSetNode->GetData());
if (seedPointSet.IsNull())
{
return;
}
if (!(seedPointSet->GetSize() > 0))
{
return;
}
mitk::PointSet::PointType seedPoint = seedPointSet->GetPointSet()->GetPoints()->Begin().Value();
mitk::Image::Pointer image = dynamic_cast (m_NodeToProceed->GetData());
if (image.IsNotNull())
{
m_LowerThreshold = static_cast (m_RoiMin);
m_UpperThreshold = static_cast (m_RoiMax);
AccessByItk_2(image, StartRegionGrowing, image->GetGeometry(), seedPoint);
}
}
template
void mitk::RegionGrow3DTool::StartRegionGrowing(itk::Image* itkImage, mitk::BaseGeometry* imageGeometry, mitk::PointSet::PointType seedPoint)
{
typedef itk::Image InputImageType;
typedef typename InputImageType::IndexType IndexType;
typedef itk::ConnectedAdaptiveThresholdImageFilter RegionGrowingFilterType;
typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New();
if ( !imageGeometry->IsInside(seedPoint) )
{
return;
}
IndexType seedIndex;
imageGeometry->WorldToIndex( seedPoint, seedIndex);// convert world coordinates to image indices
//int seedValue = itkImage->GetPixel(seedIndex);
regionGrower->SetInput( itkImage );
regionGrower->AddSeed( seedIndex );
regionGrower->SetLower( m_LowerThreshold );
regionGrower->SetUpper( m_UpperThreshold );
regionGrower->SetGrowingDirectionIsUpwards( m_CurrentRGDirectionIsUpwards );
try
{
regionGrower->Update();
}
catch( ... )
{
MITK_ERROR << "Something went wrong!" << endl;
return;
}
m_SeedpointValue = regionGrower->GetSeedpointValue();
//initialize slider
if(m_CurrentRGDirectionIsUpwards)
{
UpperThresholdValueChanged.Send(m_UpperThreshold);
LowerThresholdValueChanged.Send(m_SeedpointValue);
}
else
{
UpperThresholdValueChanged.Send(m_SeedpointValue);
LowerThresholdValueChanged.Send(m_LowerThreshold);
}
m_DetectedLeakagePoint = regionGrower->GetLeakagePoint();
mitk::Image::Pointer resultImage = mitk::ImportItkImage(regionGrower->GetOutput())->Clone();
m_FeedbackNode->SetData( resultImage );
m_FeedbackNode->SetVisibility(true);
InitializeLevelWindow();
}
void mitk::RegionGrow3DTool::InitializeLevelWindow()
{
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "levelWindow");
mitk::ScalarType* level = new mitk::ScalarType(0.5);
mitk::ScalarType* window = new mitk::ScalarType(1);
int upper;
if (m_CurrentRGDirectionIsUpwards)
{
upper = m_UpperThreshold - m_SeedpointValue;
}
else
{
upper = m_SeedpointValue - m_LowerThreshold;
}
tempLevelWindow.SetRangeMinMax(mitk::ScalarType(0), mitk::ScalarType(upper));
tempLevelWindow.SetLevelWindow(*level, *window);
m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow");
//get the suggested threshold from the detected leakage-point and adjust the slider
if (m_CurrentRGDirectionIsUpwards)
{
SliderValueChanged.Send(m_SeedpointValue + m_DetectedLeakagePoint -1);
}
else
{
SliderValueChanged.Send(m_SeedpointValue - m_DetectedLeakagePoint +1);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::ChangeLevelWindow(int value)
{
if (m_FeedbackNode.IsNull())
return;
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow(tempLevelWindow, NULL, "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 - value + 0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
else
{
level = value - m_LowerThreshold +0.5;
tempLevelWindow.SetLevelWindow(level, *window);
}
m_FeedbackNode->SetLevelWindow(tempLevelWindow, NULL, "levelWindow");
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::ConfirmSegmentation( std::string name, mitk::Color color)
{
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
new_node->SetColor(color);
new_node->SetName(name);
new_node->SetProperty("binary", mitk::BoolProperty::New("true"));
mitk::Image* image = dynamic_cast (m_FeedbackNode->GetData());
mitk::LevelWindow tempLevelWindow;
m_FeedbackNode->GetLevelWindow( tempLevelWindow, NULL, "levelWindow");
int upperThresholdLabeledImage = (short int) tempLevelWindow.GetRangeMax();
int lowerThresholdLabeledImage = (short int) tempLevelWindow.GetLowerWindowBound() + 1;
typedef itk::Image InputImageType;
- typedef itk::Image SegmentationType;
+ typedef itk::Image SegmentationType;
typedef itk::BinaryThresholdImageFilter ThresholdFilterType;
ThresholdFilterType::Pointer filter = ThresholdFilterType::New();
InputImageType::Pointer itkImage;
mitk::CastToItkImage(image, itkImage);
filter->SetInput(itkImage);
filter->SetInsideValue(1);
filter->SetOutsideValue(0);
filter->SetUpperThreshold(upperThresholdLabeledImage);
filter->SetLowerThreshold(lowerThresholdLabeledImage);
filter->Update();
mitk::Image::Pointer new_image = mitk::Image::New();
mitk::CastToMitkImage(filter->GetOutput(), new_image);
//pad to original size
if (m_OriginalImageNode.GetPointer() != m_NodeToProceed.GetPointer())
{
mitk::PadImageFilter::Pointer padFilter = mitk::PadImageFilter::New();
padFilter->SetInput(0, new_image);
padFilter->SetInput(1, dynamic_cast (m_OriginalImageNode->GetData()));
padFilter->SetBinaryFilter(true);
padFilter->SetUpperThreshold(1);
padFilter->SetLowerThreshold(1);
padFilter->Update();
new_image = padFilter->GetOutput();
}
new_node->SetData(new_image);
m_ToolManager->GetDataStorage()->Add(new_node);
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
m_ToolManager->ActivateTool(-1);
}
void mitk::RegionGrow3DTool::CancelSegmentation()
{
m_ToolManager->ActivateTool(-1);
}
void mitk::RegionGrow3DTool::SetupPreviewNodeFor( DataNode* nodeToProceed)
{
if (nodeToProceed)
{
Image::Pointer image = dynamic_cast( nodeToProceed->GetData() );
if (image.IsNotNull())
{
m_FeedbackNode->SetData( image );
int layer(50);
nodeToProceed->GetIntProperty("layer", layer);
m_FeedbackNode->SetIntProperty("layer", layer+1);
m_FeedbackNode->SetLevelWindow(NULL);
if (DataStorage* storage = m_ToolManager->GetDataStorage())
{
if (storage->Exists(m_FeedbackNode))
storage->Remove(m_FeedbackNode);
storage->Add( m_FeedbackNode, nodeToProceed );
}
}
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void mitk::RegionGrow3DTool::UpdatePreview()
{
typedef itk::Image ItkImageType;
typedef itk::Image ItkMaskType;
mitk::DataNode::Pointer node = m_ToolManager->GetRoiData(0);
if (node.IsNull())
{
this->SetupPreviewNodeFor(m_OriginalImageNode);
m_NodeToProceed = m_OriginalImageNode;
mitk::Image::Pointer image = dynamic_cast (m_OriginalImageNode->GetData());
if (image.IsNotNull())
{
m_RoiMin = image->GetScalarValueMin();
m_RoiMax = image->GetScalarValueMax();
}
return;
}
mitk::MaskAndCutRoiImageFilter::Pointer roiFilter = mitk::MaskAndCutRoiImageFilter::New();
roiFilter->SetInput(dynamic_cast (m_NodeToProceed->GetData()));
roiFilter->SetRegionOfInterest(node->GetData());
roiFilter->Update();
mitk::DataNode::Pointer new_node = mitk::DataNode::New();
mitk::Image::Pointer tmpImage = roiFilter->GetOutput();
new_node->SetData(tmpImage);
m_RoiMax = roiFilter->GetMaxValue();
m_RoiMin = roiFilter->GetMinValue();
this->SetupPreviewNodeFor(new_node);
m_NodeToProceed = new_node;
//this->RunSegmentation();
}
void mitk::RegionGrow3DTool::SetCurrentRGDirectionIsUpwards(bool flag)
{
m_CurrentRGDirectionIsUpwards = flag;
}
diff --git a/Modules/Segmentation/Interactions/mitkTool.cpp b/Modules/Segmentation/Interactions/mitkTool.cpp
index 51cb0f5803..24adad3290 100644
--- a/Modules/Segmentation/Interactions/mitkTool.cpp
+++ b/Modules/Segmentation/Interactions/mitkTool.cpp
@@ -1,255 +1,275 @@
/*===================================================================
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 "mitkTool.h"
#include "mitkProperties.h"
+#include "mitkDataNodeFactory.h"
+#include "mitkImageReadAccessor.h"
#include "mitkImageWriteAccessor.h"
+#include "mitkLabelSetImage.h"
#include "mitkLevelWindowProperty.h"
+#include "mitkLookupTableProperty.h"
+#include "mitkProperties.h"
#include "mitkVtkResliceInterpolationProperty.h"
-#include "mitkImageReadAccessor.h"
// us
-#include
#include
+#include
+// itk
#include
mitk::Tool::Tool(const char* type)
: m_PredicateImages(NodePredicateDataType::New("Image")) // for reference images
, m_PredicateDim3(NodePredicateDimension::New(3, 1))
, m_PredicateDim4(NodePredicateDimension::New(4, 1))
, m_PredicateDimension( mitk::NodePredicateOr::New(m_PredicateDim3, m_PredicateDim4) )
, m_PredicateImage3D( NodePredicateAnd::New(m_PredicateImages, m_PredicateDimension) )
, m_PredicateBinary(NodePredicateProperty::New("binary", BoolProperty::New(true)))
, m_PredicateNotBinary( NodePredicateNot::New(m_PredicateBinary) )
, m_PredicateSegmentation(NodePredicateProperty::New("segmentation", BoolProperty::New(true)))
, m_PredicateNotSegmentation( NodePredicateNot::New(m_PredicateSegmentation) )
, m_PredicateHelper(NodePredicateProperty::New("helper object", BoolProperty::New(true)))
, m_PredicateNotHelper( NodePredicateNot::New(m_PredicateHelper) )
, m_PredicateImageColorful( NodePredicateAnd::New(m_PredicateNotBinary, m_PredicateNotSegmentation) )
, m_PredicateImageColorfulNotHelper( NodePredicateAnd::New(m_PredicateImageColorful, m_PredicateNotHelper) )
, m_PredicateReference( NodePredicateAnd::New(m_PredicateImage3D, m_PredicateImageColorfulNotHelper) )
, m_IsSegmentationPredicate(NodePredicateAnd::New(NodePredicateOr::New(m_PredicateBinary, m_PredicateSegmentation), m_PredicateNotHelper))
, m_InteractorType( type )
{
}
mitk::Tool::~Tool()
{
}
bool mitk::Tool::CanHandle(BaseData* referenceData) const
{
return true;
}
void mitk::Tool::InitializeStateMachine()
{
if (m_InteractorType.empty())
return;
m_InteractorType += ".xml";
try
{
LoadStateMachine( m_InteractorType, us::GetModuleContext()->GetModule() );
SetEventConfig( "SegmentationToolsConfig.xml", us::GetModuleContext()->GetModule() );
}
catch( const std::exception& e )
{
MITK_ERROR << "Could not load statemachine pattern " << m_InteractorType << " with exception: " << e.what();
}
}
void mitk::Tool::Notify( InteractionEvent* interactionEvent, bool isHandled )
{
// to use the state machine pattern,
// the event is passed to the state machine interface to be handled
if ( !isHandled )
{
this->HandleEvent(interactionEvent, NULL);
}
}
void mitk::Tool::ConnectActionsAndFunctions()
{
}
bool mitk::Tool::FilterEvents(InteractionEvent* , DataNode* )
{
return true;
}
const char* mitk::Tool::GetGroup() const
{
return "default";
}
void mitk::Tool::SetToolManager(ToolManager* manager)
{
m_ToolManager = manager;
}
void mitk::Tool::Activated()
{
}
void mitk::Tool::Deactivated()
{
// ToDo: reactivate this feature!
//StateMachine::ResetStatemachineToStartState(); // forget about the past
}
itk::Object::Pointer mitk::Tool::GetGUI(const std::string& toolkitPrefix, const std::string& toolkitPostfix)
{
itk::Object::Pointer object;
std::string classname = this->GetNameOfClass();
std::string guiClassname = toolkitPrefix + classname + toolkitPostfix;
std::list allGUIs = itk::ObjectFactoryBase::CreateAllInstance(guiClassname.c_str());
for( std::list::iterator iter = allGUIs.begin();
iter != allGUIs.end();
++iter )
{
if (object.IsNull())
{
object = dynamic_cast( iter->GetPointer() );
}
else
{
MITK_ERROR << "There is more than one GUI for " << classname << " (several factories claim ability to produce a " << guiClassname << " ) " << std::endl;
return NULL; // people should see and fix this error
}
}
return object;
}
mitk::NodePredicateBase::ConstPointer mitk::Tool::GetReferenceDataPreference() const
{
return m_PredicateReference.GetPointer();
}
mitk::NodePredicateBase::ConstPointer mitk::Tool::GetWorkingDataPreference() const
{
return m_IsSegmentationPredicate.GetPointer();
}
+
mitk::DataNode::Pointer mitk::Tool::CreateEmptySegmentationNode( Image* original, const std::string& organName, const mitk::Color& color )
{
// we NEED a reference image for size etc.
if (!original) return NULL;
// actually create a new empty segmentation
PixelType pixelType(mitk::MakeScalarPixelType() );
- Image::Pointer segmentation = Image::New();
+ LabelSetImage::Pointer segmentation = LabelSetImage::New();
if (original->GetDimension() == 2)
{
const unsigned int dimensions[] = { original->GetDimension(0), original->GetDimension(1), 1 };
segmentation->Initialize(pixelType, 3, dimensions);
+ segmentation->AddLayer();
}
else
{
- segmentation->Initialize(pixelType, original->GetDimension(), original->GetDimensions());
+ segmentation->Initialize(original);
}
- unsigned int byteSize = sizeof(DefaultSegmentationDataType);
+ mitk::Label::Pointer label = mitk::Label::New();
+ label->SetName(organName);
+ label->SetColor(color);
+ label->SetValue(1);
+ segmentation->GetActiveLabelSet()->AddLabel(label);
+ segmentation->GetActiveLabelSet()->SetActiveLabel(1);
+
+ unsigned int byteSize = sizeof(mitk::Label::PixelType);
if(segmentation->GetDimension() < 4)
{
for (unsigned int dim = 0; dim < segmentation->GetDimension(); ++dim)
{
byteSize *= segmentation->GetDimension(dim);
}
- mitk::ImageWriteAccessor writeAccess(segmentation, segmentation->GetVolumeData(0));
+ mitk::ImageWriteAccessor writeAccess(segmentation.GetPointer(), segmentation->GetVolumeData(0));
memset( writeAccess.GetData(), 0, byteSize );
}
else
- {//if we have a time-resolved image we need to set memory to 0 for each time step
+ {
+ //if we have a time-resolved image we need to set memory to 0 for each time step
for (unsigned int dim = 0; dim < 3; ++dim)
{
byteSize *= segmentation->GetDimension(dim);
}
for( unsigned int volumeNumber = 0; volumeNumber < segmentation->GetDimension(3); volumeNumber++)
{
- mitk::ImageWriteAccessor writeAccess(segmentation, segmentation->GetVolumeData(volumeNumber));
+ mitk::ImageWriteAccessor writeAccess(segmentation.GetPointer(), segmentation->GetVolumeData(volumeNumber));
memset( writeAccess.GetData(), 0, byteSize );
}
}
if (original->GetTimeGeometry() )
{
TimeGeometry::Pointer originalGeometry = original->GetTimeGeometry()->Clone();
segmentation->SetTimeGeometry( originalGeometry );
}
else
{
Tool::ErrorMessage("Original image does not have a 'Time sliced geometry'! Cannot create a segmentation.");
return NULL;
}
return CreateSegmentationNode( segmentation, organName, color );
}
mitk::DataNode::Pointer mitk::Tool::CreateSegmentationNode( Image* image, const std::string& organName, const mitk::Color& color )
{
if (!image) return NULL;
// decorate the datatreenode with some properties
DataNode::Pointer segmentationNode = DataNode::New();
segmentationNode->SetData( image );
// name
segmentationNode->SetProperty( "name", StringProperty::New( organName ) );
// visualization properties
segmentationNode->SetProperty( "binary", BoolProperty::New(true) );
- segmentationNode->SetProperty( "color", ColorProperty::New(color) );
+// segmentationNode->SetProperty( "color", ColorProperty::New(color) );
+ mitk::LookupTable::Pointer lut = mitk::LookupTable::New();
+ lut->SetType(mitk::LookupTable::MULTILABEL);
+ mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New();
+ lutProp->SetLookupTable(lut);
+ segmentationNode->SetProperty("LookupTable", lutProp);
segmentationNode->SetProperty( "texture interpolation", BoolProperty::New(false) );
segmentationNode->SetProperty( "layer", IntProperty::New(10) );
segmentationNode->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow(0.5, 1) ) );
segmentationNode->SetProperty( "opacity", FloatProperty::New(0.3) );
segmentationNode->SetProperty( "segmentation", BoolProperty::New(true) );
segmentationNode->SetProperty( "reslice interpolation", VtkResliceInterpolationProperty::New() ); // otherwise -> segmentation appears in 2 slices sometimes (only visual effect, not different data)
// For MITK-3M3 release, the volume of all segmentations should be shown
segmentationNode->SetProperty( "showVolume", BoolProperty::New( true ) );
return segmentationNode;
}
us::ModuleResource mitk::Tool::GetIconResource() const
{
// Each specific tool should load its own resource. This one will be invalid
return us::ModuleResource();
}
us::ModuleResource mitk::Tool::GetCursorIconResource() const
{
// Each specific tool should load its own resource. This one will be invalid
return us::ModuleResource();
}
diff --git a/Modules/Segmentation/Interactions/mitkTool.h b/Modules/Segmentation/Interactions/mitkTool.h
index aa8d4c8c60..f323a264eb 100644
--- a/Modules/Segmentation/Interactions/mitkTool.h
+++ b/Modules/Segmentation/Interactions/mitkTool.h
@@ -1,254 +1,255 @@
/*===================================================================
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 mitkTool_h_Included
#define mitkTool_h_Included
#include "mitkCommon.h"
#include
#include "mitkStateMachine.h"
#include "mitkToolEvents.h"
#include "itkObjectFactoryBase.h"
#include "itkVersion.h"
#include "mitkToolFactoryMacro.h"
#include "mitkMessage.h"
#include "mitkDataNode.h"
#include "mitkNodePredicateProperty.h"
#include "mitkNodePredicateDataType.h"
#include "mitkNodePredicateDimension.h"
#include "mitkNodePredicateAnd.h"
#include "mitkNodePredicateOr.h"
#include "mitkNodePredicateNot.h"
#include
#include
#include
#include "mitkInteractionEventObserver.h"
#include "mitkEventStateMachine.h"
+#include
namespace us {
class ModuleResource;
}
namespace mitk
{
class ToolManager;
/**
\brief Base class of all tools used by mitk::ToolManager.
\sa ToolManager
\sa SegTool2D
\ingroup Interaction
\ingroup ToolManagerEtAl
There is a separate page describing the \ref QmitkInteractiveSegmentationTechnicalPage.
Every tool is a mitk::StateMachine, which can follow any transition pattern that it likes. One important thing to know is, that
every derived tool should always call SuperClass::Deactivated() in its own implementation of Deactivated, because mitk::Tool
resets the StateMachine in this method. Only if you are very sure that you covered all possible things that might happen to your
own tool, you should consider not to reset the StateMachine from time to time.
To learn about the MITK implementation of state machines in general, have a look at \ref InteractionPage.
To derive a non-abstract tool, you inherit from mitk::Tool (or some other base class further down the inheritance tree), and in your
own parameterless constructor (that is called from the itkFactorylessNewMacro that you use) you pass a StateMachine pattern name to the superclass.
Names for valid patterns can be found in StateMachine.xml (which might be enhanced by you).
You have to implement at least GetXPM() and GetName() to provide some identification.
Each Tool knows its ToolManager, which can provide the data that the tool should work on.
\warning Only to be instantiated by mitk::ToolManager (because SetToolManager has to be called). All other uses are unsupported.
$Author$
*/
class MITKSEGMENTATION_EXPORT Tool : public EventStateMachine
, public InteractionEventObserver
{
public:
- typedef unsigned char DefaultSegmentationDataType;
+ typedef mitk::Label::PixelType DefaultSegmentationDataType;
/**
* \brief To let GUI process new events (e.g. qApp->processEvents() )
*/
Message<> GUIProcessEventsMessage;
/**
* \brief To send error messages (to be shown by some GUI)
*/
Message1 ErrorMessage;
/**
* \brief To send whether the tool is busy (to be shown by some GUI)
*/
Message1 CurrentlyBusy;
/**
* \brief To send general messages (to be shown by some GUI)
*/
Message1 GeneralMessage;
mitkClassMacro(Tool, EventStateMachine);
// no New(), there should only be subclasses
/**
\brief Returns an icon in the XPM format.
This icon has to fit into some kind of button in most applications, so make it smaller than 25x25 pixels.
XPM is e.g. supported by The Gimp. But if you open any XPM file in your text editor, you will see that you could also "draw" it with an editor.
*/
virtual const char** GetXPM() const = 0;
/**
* \brief Returns the path of an icon.
*
* This icon is preferred to the XPM icon.
*/
virtual std::string GetIconPath() const { return ""; }
/**
* \brief Returns the path of a cursor icon.
*
*/
virtual us::ModuleResource GetCursorIconResource() const;
/**
* @brief Returns the tool button icon of the tool wrapped by a usModuleResource
* @return a valid ModuleResource or an invalid if this function
* is not reimplemented
*/
virtual us::ModuleResource GetIconResource() const;
/**
\brief Returns the name of this tool. Make it short!
This name has to fit into some kind of button in most applications, so take some time to think of a good name!
*/
virtual const char* GetName() const = 0;
/**
\brief Name of a group.
You can group several tools by assigning a group name. Graphical tool selectors might use this information to group tools. (What other reason could there be?)
*/
virtual const char* GetGroup() const;
virtual void InitializeStateMachine();
/**
* \brief Interface for GUI creation.
*
* This is the basic interface for creation of a GUI object belonging to one tool.
*
* Tools that support a GUI (e.g. for display/editing of parameters) should follow some rules:
*
* - A Tool and its GUI are two separate classes
* - There may be several instances of a GUI at the same time.
* - mitk::Tool is toolkit (Qt, wxWidgets, etc.) independent, the GUI part is of course dependent
* - The GUI part inherits both from itk::Object and some GUI toolkit class
* - The GUI class name HAS to be constructed like "toolkitPrefix" tool->GetClassName() + "toolkitPostfix", e.g. MyTool -> wxMyToolGUI
* - For each supported toolkit there is a base class for tool GUIs, which contains some convenience methods
* - Tools notify the GUI about changes using ITK events. The GUI must observe interesting events.
* - The GUI base class may convert all ITK events to the GUI toolkit's favoured messaging system (Qt -> signals)
* - Calling methods of a tool by its GUI is done directly.
* In some cases GUIs don't want to be notified by the tool when they cause a change in a tool.
* There is a macro CALL_WITHOUT_NOTICE(method()), which will temporarily disable all notifications during a method call.
*/
virtual itk::Object::Pointer GetGUI(const std::string& toolkitPrefix, const std::string& toolkitPostfix);
virtual NodePredicateBase::ConstPointer GetReferenceDataPreference() const;
virtual NodePredicateBase::ConstPointer GetWorkingDataPreference() const;
DataNode::Pointer CreateEmptySegmentationNode( Image* original, const std::string& organName, const mitk::Color& color );
DataNode::Pointer CreateSegmentationNode( Image* image, const std::string& organName, const mitk::Color& color );
virtual bool CanHandle(BaseData* referenceData) const;
protected:
friend class ToolManager;
virtual void SetToolManager(ToolManager*);
void ConnectActionsAndFunctions() override;
/**
\brief Called when the tool gets activated (registered to mitk::GlobalInteraction).
Derived tools should call their parents implementation.
*/
virtual void Activated();
/**
\brief Called when the tool gets deactivated (unregistered from mitk::GlobalInteraction).
Derived tools should call their parents implementation.
*/
virtual void Deactivated();
Tool(); // purposely hidden
Tool( const char*); // purposely hidden
virtual ~Tool();
virtual void Notify( InteractionEvent* interactionEvent,bool isHandled ) override;
bool FilterEvents(InteractionEvent* , DataNode* ) override;
ToolManager* m_ToolManager;
private:
// for reference data
NodePredicateDataType::Pointer m_PredicateImages;
NodePredicateDimension::Pointer m_PredicateDim3;
NodePredicateDimension::Pointer m_PredicateDim4;
NodePredicateOr::Pointer m_PredicateDimension;
NodePredicateAnd::Pointer m_PredicateImage3D;
NodePredicateProperty::Pointer m_PredicateBinary;
NodePredicateNot::Pointer m_PredicateNotBinary;
NodePredicateProperty::Pointer m_PredicateSegmentation;
NodePredicateNot::Pointer m_PredicateNotSegmentation;
NodePredicateProperty::Pointer m_PredicateHelper;
NodePredicateNot::Pointer m_PredicateNotHelper;
NodePredicateAnd::Pointer m_PredicateImageColorful;
NodePredicateAnd::Pointer m_PredicateImageColorfulNotHelper;
NodePredicateAnd::Pointer m_PredicateReference;
// for working data
NodePredicateAnd::Pointer m_IsSegmentationPredicate;
std::string m_InteractorType;
};
} // namespace
#endif
diff --git a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
index 8411094a17..60d9a12802 100644
--- a/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
+++ b/Modules/SegmentationUI/Qmitk/QmitkAdaptiveRegionGrowingToolGUI.cpp
@@ -1,855 +1,855 @@
/*===================================================================
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 "QmitkAdaptiveRegionGrowingToolGUI.h"
#include "QmitkStdMultiWidget.h"
#include
#include "mitkNodePredicateDataType.h"
#include "mitkProperties.h"
#include "mitkITKImageImport.h"
#include "mitkImageAccessByItk.h"
#include "mitkTransferFunctionProperty.h"
#include "mitkImageTimeSelector.h"
#include "mitkImageStatisticsHolder.h"
#include
#include
#include
#include
#include "itkOrImageFilter.h"
#include "mitkImageCast.h"
#include "QmitkConfirmSegmentationDialog.h"
#include "mitkPixelTypeMultiplex.h"
#include "mitkImagePixelReadAccessor.h"
MITK_TOOL_GUI_MACRO( , QmitkAdaptiveRegionGrowingToolGUI, "")
QmitkAdaptiveRegionGrowingToolGUI::QmitkAdaptiveRegionGrowingToolGUI(QWidget* parent) :
QmitkToolGUI(), m_MultiWidget(NULL), m_UseVolumeRendering(false), m_UpdateSuggestedThreshold(true), m_SuggestedThValue(0.0), m_DataStorage(NULL)
{
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);
this->CreateConnections();
this->SetDataNodeNames("labeledRGSegmentation","RGResult","RGFeedbackSurface");
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);
}
}
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( (QObject*) (m_Controls.m_cbVolumeRendering), SIGNAL(toggled(bool)), this, SLOT(UseVolumeRendering(bool) ));
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)
{
m_NAMEFORLABLEDSEGMENTATIONIMAGE = labledSegmentation;
m_NAMEFORBINARYIMAGE = binaryImage;
m_NAMEFORSURFACE = surface;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetDataStorage(mitk::DataStorage* dataStorage)
{
m_DataStorage = dataStorage;
}
void QmitkAdaptiveRegionGrowingToolGUI::SetMultiWidget(QmitkStdMultiWidget* multiWidget)
{
m_MultiWidget = multiWidget;
}
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*/, const mitk::Image::Pointer 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 != NULL)
{
mitk::PointSet::Pointer pointSet = dynamic_cast(node->GetData());
if (pointSet.IsNull())
{
QMessageBox::critical(NULL, "QmitkAdaptiveRegionGrowingToolGUI", "PointSetNode does not contain a pointset");
return;
}
m_Controls.m_lblSetSeedpoint->setText("");
mitk::Image* image = dynamic_cast(m_InputImageNode->GetData());
mitk::Point3D seedPoint = pointSet->GetPointSet(mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep())->GetPoints()->ElementAt(0);
if (image->GetGeometry()->IsInside(seedPoint))
mitkPixelTypeMultiplex3(AccessPixel,image->GetChannelDescriptor().GetPixelType(),image,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);
image->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(image->GetGeometry()->IsIndexInside(currentIndex))
{
int component = 0;
m_InputImageNode->GetIntProperty("Image.Displayed Component", component);
pixelValues[pos] = image->GetPixelValueByIndex(currentIndex, 0, component);
pos++;
}
else
{
pixelValues[pos] = -10000000;
pos++;
}
}
}
}
//Now calculation mean of the pixelValues
unsigned int numberOfValues(0);
for (auto & pixelValue : pixelValues)
{
if(pixelValue > -10000000)
{
m_SeedPointValueMean += pixelValue;
numberOfValues++;
}
}
m_SeedPointValueMean = m_SeedPointValueMean/numberOfValues;
/*
* 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
*/
mitk::ScalarType min = image->GetStatistics()->GetScalarValueMin();
mitk::ScalarType max = image->GetStatistics()->GetScalarValueMax();
mitk::ScalarType windowSize = max - min;
windowSize = 0.15*windowSize;
if (m_CurrentRGDirectionIsUpwards)
{
m_LOWERTHRESHOLD = m_SeedPointValueMean;
if (m_SeedpointValue < m_SeedPointValueMean)
m_LOWERTHRESHOLD = m_SeedpointValue;
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);
}
}
}
void QmitkAdaptiveRegionGrowingToolGUI::RunSegmentation()
{
if (m_InputImageNode.IsNull())
{
QMessageBox::information( NULL, "Adaptive Region Growing functionality", "Please specify the image in Datamanager!");
return;
}
mitk::DataNode::Pointer node = m_RegionGrow3DTool->GetPointSetNode();
if (node.IsNull())
{
QMessageBox::information( NULL, "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( NULL, "Adaptive Region Growing functionality", "The seed point is empty! Please choose a new seed point.");
return;
}
int timeStep = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep();
if (!(seedPointSet->GetSize(timeStep)))
{
m_Controls.m_pbRunSegmentation->setEnabled(true);
QMessageBox::information( NULL, "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();
mitk::Image::Pointer orgImage = dynamic_cast (m_InputImageNode->GetData());
if (orgImage.IsNotNull())
{
if (orgImage->GetDimension() == 4)
{
mitk::ImageTimeSelector::Pointer timeSelector = mitk::ImageTimeSelector::New();
timeSelector->SetInput(orgImage);
timeSelector->SetTimeNr( timeStep );
timeSelector->UpdateLargestPossibleRegion();
mitk::Image* timedImage = timeSelector->GetOutput();
AccessByItk_2( timedImage , StartRegionGrowing, timedImage->GetGeometry(), seedPoint);
}
else if (orgImage->GetDimension() == 3)
{
//QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); //set the cursor to waiting
AccessByItk_2(orgImage, StartRegionGrowing, orgImage->GetGeometry(), seedPoint);
//QApplication::restoreOverrideCursor();//reset cursor
}
else
{
QApplication::restoreOverrideCursor();//reset cursor
QMessageBox::information( NULL, "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(itk::Image* itkImage, mitk::BaseGeometry* imageGeometry, 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::MinimumMaximumImageCalculator MinMaxValueFilterType;
if ( !imageGeometry->IsInside(seedPoint) )
{
QApplication::restoreOverrideCursor();//reset cursor to be able to click ok with the regular mouse cursor
QMessageBox::information( NULL, "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_SeedpointValueSetGrowingDirectionIsUpwards( 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
regionGrower->SetLower( m_LOWERTHRESHOLD-1 );
regionGrower->SetUpper( m_UPPERTHRESHOLD+1);
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( NULL, "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_LOWERTHRESHOLD+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 );
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, NULL, "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, NULL, "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_MultiWidget)
{
this->m_MultiWidget->levelWindowWidget->GetManager()->SetAutoTopMostImage(false);
this->m_MultiWidget->levelWindowWidget->GetManager()->SetLevelWindowProperty(static_cast(newNode->GetProperty("levelwindow")));
}
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, NULL, "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, NULL, "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( NULL, "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( NULL, "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( NULL, "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* 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...
}
template
void QmitkAdaptiveRegionGrowingToolGUI::ITKThresholding(itk::Image* itkImage)
{
mitk::Image::Pointer originalSegmentation = dynamic_cast(this->m_RegionGrow3DTool->
GetTargetSegmentationNode()->GetData());
int timeStep = mitk::BaseRenderer::GetInstance( mitk::BaseRenderer::GetRenderWindowByName("stdmulti.widget1") )->GetTimeStep();
if (originalSegmentation)
{
typedef itk::Image InputImageType;
- typedef itk::Image SegmentationType;
+ 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() >= 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 NULL leave node NULL
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 NULL leave node NULL
node = m_DataStorage?m_DataStorage->GetNamedNode(m_NAMEFORLABLEDSEGMENTATIONIMAGE):NULL;
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_NAMEFORLABLEDSEGMENTATIONIMAGE);
if(node.IsNull())
return;
if(m_MultiWidget)
m_MultiWidget->SetWidgetPlanesVisibility(!enable);
if (enable)
{
node->SetBoolProperty("volumerendering", enable);
node->SetBoolProperty("volumerendering.uselod", true);
}
else
{
node->SetBoolProperty("volumerendering", enable);
}
mitk::RenderingManager::GetInstance()->RequestUpdateAll();
}
void QmitkAdaptiveRegionGrowingToolGUI::UpdateVolumeRenderingThreshold(int thValue)
{
mitk::DataNode::Pointer node = m_DataStorage->GetNamedNode( m_NAMEFORLABLEDSEGMENTATIONIMAGE);
mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New();
if (m_UpdateSuggestedThreshold)
{
m_SuggestedThValue = thValue;
m_UpdateSuggestedThreshold = false;
}
// grayvalue->opacity
{
vtkPiecewiseFunction *f = tf->GetScalarOpacityFunction();
f->RemoveAllPoints();
f->AddPoint(0, 0);
f->AddPoint(thValue+0.5, 0);
f->AddPoint(thValue+1.5, 1);
f->AddPoint(1000, 1);
f->ClampingOn();
f->Modified();
}
// grayvalue->color
{
float a = 255.0;
vtkColorTransferFunction *ctf = tf->GetColorTransferFunction();
ctf->RemoveAllPoints();
//ctf->AddRGBPoint(-1000, 0.0, 0.0, 0.0);
ctf->AddRGBPoint(m_SuggestedThValue+1, 203/a, 104/a, 102/a);
ctf->AddRGBPoint(m_SuggestedThValue, 255/a, 0/a, 0/a);
ctf->ClampingOn();
ctf->Modified();
}
// GradientOpacityFunction
{
vtkPiecewiseFunction *gof = tf->GetGradientOpacityFunction();
gof->RemoveAllPoints();
gof->AddPoint(-10000, 1);
gof->AddPoint(10000, 1);
gof->ClampingOn();
gof->Modified();
}
mitk::TransferFunctionProperty::Pointer tfp = mitk::TransferFunctionProperty::New();
tfp->SetValue(tf);
node->SetProperty("TransferFunction", tfp);
}
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/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp
index a6d4af341e..8b75ca8758 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp
@@ -1,158 +1,161 @@
/*===================================================================
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 "QmitkSurfaceToImageWidget.h"
#include
#include
#include
#include
#include
#include
#include
+#include
#include
static const char* const HelpText = "Select an image and a surface above";
QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent)
: QmitkSegmentationUtilityWidget(timeNavigationController, parent)
{
m_Controls.setupUi(this);
m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::ImageAndSegmentationPredicate);
m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::SurfacePredicate);
m_Controls.dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
connect (m_Controls.btnSurface2Image, SIGNAL(pressed()), this, SLOT(OnSurface2ImagePressed()));
connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)),
this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*)));
if( m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() &&
m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() )
{
this->OnSelectionChanged( 0, m_Controls.dataSelectionWidget->GetSelection(0));
}
}
QmitkSurfaceToImageWidget::~QmitkSurfaceToImageWidget()
{
}
void QmitkSurfaceToImageWidget::EnableButtons(bool enable)
{
m_Controls.btnSurface2Image->setEnabled(enable);
}
-void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection)
+void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int /*index*/, const mitk::DataNode* /*selection*/)
{
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::DataNode::Pointer imageNode = dataSelectionWidget->GetSelection(0);
mitk::DataNode::Pointer surfaceNode = dataSelectionWidget->GetSelection(1);
if (imageNode.IsNull() || surfaceNode.IsNull() )
{
dataSelectionWidget->SetHelpText(HelpText);
this->EnableButtons(false);
}
else
{
mitk::Image::Pointer image = dynamic_cast( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Surface::Pointer surface = dynamic_cast( dataSelectionWidget->GetSelection(1)->GetData() );
if( image->GetTimeSteps() != surface->GetTimeSteps() )
{
dataSelectionWidget->SetHelpText("Image and surface are of different size");
this->EnableButtons(false);
}
else
{
dataSelectionWidget->SetHelpText("");
this->EnableButtons();
}
}
}
void QmitkSurfaceToImageWidget::OnSurface2ImagePressed()
{
this->EnableButtons(false);
QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget;
mitk::Image::Pointer image = dynamic_cast( dataSelectionWidget->GetSelection(0)->GetData() );
mitk::Surface::Pointer surface = dynamic_cast( dataSelectionWidget->GetSelection(1)->GetData() );
if( image.IsNull() || surface.IsNull())
{
MITK_ERROR << "Selection does not contain an image and/or a surface";
QMessageBox::information( this, "Surface To Image", "Selection does not contain an image and/or a surface", QMessageBox::Ok );
this->EnableButtons();
return;
}
mitk::Image::Pointer resultImage(nullptr);
resultImage = this->ConvertSurfaceToImage( image, surface );
if( resultImage.IsNull() )
{
MITK_ERROR << "Convert Surface to binary image failed";
QMessageBox::information( this, "Surface To Image", "Convert Surface to binary image failed", QMessageBox::Ok );
this->EnableButtons();
return;
}
//create name for result node
std::string nameOfResultImage = dataSelectionWidget->GetSelection(0)->GetName();
nameOfResultImage.append("_");
nameOfResultImage.append(dataSelectionWidget->GetSelection(1)->GetName());
//create data node and add to data storage
mitk::DataNode::Pointer resultNode = mitk::DataNode::New();
resultNode->SetData( resultImage );
resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) );
- resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
+// resultNode->SetProperty("binary", mitk::BoolProperty::New(true) );
dataSelectionWidget->GetDataStorage()->Add(resultNode, dataSelectionWidget->GetSelection(0));
this->EnableButtons();
}
-mitk::Image::Pointer QmitkSurfaceToImageWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface )
+mitk::LabelSetImage::Pointer QmitkSurfaceToImageWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface )
{
mitk::ProgressBar::GetInstance()->AddStepsToDo(2);
mitk::ProgressBar::GetInstance()->Progress();
mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
surfaceToImageFilter->MakeOutputBinaryOn();
surfaceToImageFilter->SetInput(surface);
surfaceToImageFilter->SetImage(image);
try
{
surfaceToImageFilter->Update();
}
catch(itk::ExceptionObject& excpt)
{
MITK_ERROR << excpt.GetDescription();
return nullptr;
}
mitk::ProgressBar::GetInstance()->Progress();
mitk::Image::Pointer resultImage = surfaceToImageFilter->GetOutput();
+ mitk::LabelSetImage::Pointer multilabelImage = mitk::LabelSetImage::New();
+ multilabelImage->InitializeByLabeledImage(resultImage);
- return resultImage;
+ return multilabelImage;
}
diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h
index f68206cb8d..71cae691aa 100644
--- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h
+++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h
@@ -1,67 +1,68 @@
/*===================================================================
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 QmitkSurfaceToImageWidget_h
#define QmitkSurfaceToImageWidget_h
#include "../QmitkSegmentationUtilityWidget.h"
#include
namespace mitk {
class Surface;
class Image;
+ class LabelSetImage;
}
/*!
\brief QmitkSurfaceToImageWidget
The Tool converts a surface to a binary image. The Method requires
a surface and an image, which header information defines the output
image. The resulting binary image has the same dimension, size, and
Geometry3D as the input image.
*/
class QmitkSurfaceToImageWidget : public QmitkSegmentationUtilityWidget
{
Q_OBJECT
public:
/** @brief Default constructor, including creation of GUI elements and signals/slots connections. */
explicit QmitkSurfaceToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = nullptr);
/** @brief Defaul destructor. */
~QmitkSurfaceToImageWidget();
private slots:
/** @brief This slot is called if the selection in the workbench is changed. */
void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection);
/** @brief This slot is called if user activates the button to convert a surface into a binary image. */
void OnSurface2ImagePressed();
private:
/** @brief Enable buttons if data selction is valid. */
void EnableButtons(bool enable = true);
/** @brief Convert a surface into an binary image. */
- itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, itk::SmartPointer surface );
+ itk::SmartPointer ConvertSurfaceToImage( itk::SmartPointer image, itk::SmartPointer surface );
Ui::QmitkSurfaceToImageWidgetControls m_Controls;
};
#endif