diff --git a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp index d8148c87f5..861598c809 100644 --- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp +++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.cpp @@ -1,294 +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::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/mitkOtsuTool3D.h b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h index 6ca05fa45c..27c7a84120 100644 --- a/Modules/Segmentation/Interactions/mitkOtsuTool3D.h +++ b/Modules/Segmentation/Interactions/mitkOtsuTool3D.h @@ -1,70 +1,72 @@ /*=================================================================== 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 MITKOTSUTOOL3D_H #define MITKOTSUTOOL3D_H #include #include "mitkAutoSegmentationTool.h" #include "itkImage.h" namespace us { class ModuleResource; } namespace mitk{ class Image; class MitkSegmentation_EXPORT OtsuTool3D : public AutoSegmentationTool { public: mitkClassMacro(OtsuTool3D, AutoSegmentationTool); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const char* GetName() const; virtual const char** GetXPM() const; us::ModuleResource GetIconResource() const; virtual void Activated(); virtual void Deactivated(); void RunSegmentation( int regions, bool useValley, int numberOfBins); void ConfirmSegmentation(); //void UpdateBinaryPreview(int regionID); void UpdateBinaryPreview(std::vector regionIDs); void UpdateVolumePreview(bool volumeRendering); void ShowMultiLabelResultNode(bool); + int GetNumberOfBins(); + protected: OtsuTool3D(); virtual ~OtsuTool3D(); template< typename TPixel, unsigned int VImageDimension> void CalculatePreview( itk::Image< TPixel, VImageDimension>* itkImage, std::vector regionIDs); itk::SmartPointer m_OriginalImage; //holds the user selected binary segmentation mitk::DataNode::Pointer m_BinaryPreviewNode; //holds the multilabel result as a preview image mitk::DataNode::Pointer m_MultiLabelResultNode; //holds the user selected binary segmentation masked original image mitk::DataNode::Pointer m_MaskedImagePreviewNode; };//class }//namespace #endif diff --git a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp index 3ad4067cf2..37b7703013 100644 --- a/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp +++ b/Modules/SegmentationUI/Qmitk/QmitkOtsuTool3DGUI.cpp @@ -1,173 +1,182 @@ /*=================================================================== 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 "QmitkOtsuTool3DGUI.h" #include "QmitkConfirmSegmentationDialog.h" #include #include #include #include #include #include MITK_TOOL_GUI_MACRO(MitkSegmentationUI_EXPORT, QmitkOtsuTool3DGUI, "") QmitkOtsuTool3DGUI::QmitkOtsuTool3DGUI() :QmitkToolGUI(), m_NumberOfRegions(0) { m_Controls.setupUi(this); connect( m_Controls.previewButton, SIGNAL(clicked()), this, SLOT(OnSpinboxValueAccept())); connect(m_Controls.m_selectionListWidget, SIGNAL(itemSelectionChanged()), this, SLOT(OnRegionSelectionChanged())); connect( m_Controls.m_Spinbox, SIGNAL(valueChanged(int)), this, SLOT(OnRegionSpinboxChanged(int)) ); connect( m_Controls.m_ConfSegButton, SIGNAL(clicked()), this, SLOT(OnSegmentationRegionAccept())); connect( this, SIGNAL(NewToolAssociated(mitk::Tool*)), this, SLOT(OnNewToolAssociated(mitk::Tool*)) ); connect(m_Controls.advancedSettingsButton, SIGNAL(toggled(bool)), this, SLOT(OnAdvancedSettingsButtonToggled(bool))); this->OnAdvancedSettingsButtonToggled(false); } QmitkOtsuTool3DGUI::~QmitkOtsuTool3DGUI() { } void QmitkOtsuTool3DGUI::OnRegionSpinboxChanged(int numberOfRegions) { //we have to change to minimum number of histogram bins accordingly int curBinValue = m_Controls.m_BinsSpinBox->value(); if (curBinValuesetValue(numberOfRegions); } void QmitkOtsuTool3DGUI::OnRegionSelectionChanged() { m_SelectedItems = m_Controls.m_selectionListWidget->selectedItems(); if (m_SelectedItems.size() == 0) { m_Controls.m_ConfSegButton->setEnabled( false ); m_OtsuTool3DTool->ShowMultiLabelResultNode(true); return; } if (m_OtsuTool3DTool.IsNotNull()) { // update preview of region QList::Iterator it; std::vector regionIDs; for (it = m_SelectedItems.begin(); it != m_SelectedItems.end(); ++it) regionIDs.push_back((*it)->text().toInt()); m_OtsuTool3DTool->UpdateBinaryPreview(regionIDs); m_Controls.m_ConfSegButton->setEnabled( true ); } } void QmitkOtsuTool3DGUI::OnAdvancedSettingsButtonToggled(bool toggled) { m_Controls.m_ValleyCheckbox->setVisible(toggled); m_Controls.binLabel->setVisible(toggled); m_Controls.m_BinsSpinBox->setVisible(toggled); + + if(toggled) + { + int max = m_OtsuTool3DTool->GetNumberOfBins(); + if(max >= m_Controls.m_BinsSpinBox->minimum()) + { + m_Controls.m_BinsSpinBox->setMaximum(max); + } + } } void QmitkOtsuTool3DGUI::OnNewToolAssociated(mitk::Tool* tool) { m_OtsuTool3DTool = dynamic_cast( tool ); } void QmitkOtsuTool3DGUI::OnSegmentationRegionAccept() { QmitkConfirmSegmentationDialog dialog; QString segName = QString::fromStdString(m_OtsuTool3DTool->GetCurrentSegmentationName()); dialog.SetSegmentationName(segName); int result = dialog.exec(); switch(result) { case QmitkConfirmSegmentationDialog::CREATE_NEW_SEGMENTATION: m_OtsuTool3DTool->SetOverwriteExistingSegmentation(false); break; case QmitkConfirmSegmentationDialog::OVERWRITE_SEGMENTATION: m_OtsuTool3DTool->SetOverwriteExistingSegmentation(true); break; case QmitkConfirmSegmentationDialog::CANCEL_SEGMENTATION: return; } if (m_OtsuTool3DTool.IsNotNull() && m_Controls.m_selectionListWidget->currentItem() != NULL) { m_OtsuTool3DTool->ConfirmSegmentation(); } } void QmitkOtsuTool3DGUI::OnSpinboxValueAccept() { if( m_NumberOfRegions == m_Controls.m_Spinbox->value() && m_UseValleyEmphasis == m_Controls.m_ValleyCheckbox->isChecked() && m_NumberOfBins == m_Controls.m_BinsSpinBox->value() ) return; if (m_OtsuTool3DTool.IsNotNull()) { try { m_NumberOfRegions = m_Controls.m_Spinbox->value(); m_UseValleyEmphasis = m_Controls.m_ValleyCheckbox->isChecked(); m_NumberOfBins = m_Controls.m_BinsSpinBox->value(); int proceed; QMessageBox* messageBox = new QMessageBox(QMessageBox::Question, NULL, "The otsu segmentation computation may take several minutes depending on the number of Regions you selected. Proceed anyway?", QMessageBox::Ok | QMessageBox::Cancel); if (m_NumberOfRegions >= 5) { proceed = messageBox->exec(); if (proceed != QMessageBox::Ok) return; } this->setCursor(Qt::WaitCursor); m_OtsuTool3DTool->RunSegmentation( m_NumberOfRegions, m_UseValleyEmphasis, m_NumberOfBins ); this->setCursor(Qt::ArrowCursor); } catch( ... ) { this->setCursor(Qt::ArrowCursor); QMessageBox* messageBox = new QMessageBox(QMessageBox::Critical, NULL, "itkOtsuFilter error: image dimension must be in {2, 3} and no RGB images can be handled."); messageBox->exec(); delete messageBox; return; } //insert regions into widget QString itemName; QListWidgetItem* item; m_Controls.m_selectionListWidget->clear(); for(int i=0; ivalue(); ++i) { itemName = QString::number(i); item = new QListWidgetItem(itemName); m_Controls.m_selectionListWidget->addItem(item); } //deactivate 'confirm segmentation'-button m_Controls.m_ConfSegButton->setEnabled(false); } } void QmitkOtsuTool3DGUI::OnVolumePreviewChecked(int state) { if (state == 1) { } }