diff --git a/.gitignore b/.gitignore index 01d49d4a75..bddf0cee41 100644 --- a/.gitignore +++ b/.gitignore @@ -1,77 +1,78 @@ CMakeLists.txt.user* .clang_complete .autosave +*.stackdump ########## Git related # Patches and similar *.patch *.diff *.rej *.orig !Utilities/qtsingleapplication/*.patch !CMakeExternals/*.patch ########## IDE specific ## Office ~$* ## vim Session.vim *.swp *.swo .vimrc ## Emacs \#*\# /.emacs.desktop /.emacs.desktop.lock .elc auto-save-list tramp .\#* ## Eclipse .cproject .project .settings/ # Org-mode .org-id-locations *_archive # Visual Studio / VS Code .vs/ out/ CMakeSettings.json ########## OS specific ## Windows files to ignore # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ ## OSX specific .DS_Store .AppleDouble .LSOverride Icon # Thumbnails ._* # Files that might appear on external disk .Spotlight-V100 .Trashes ## Linux *~ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake b/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake index d73169c874..d1857f2cda 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake @@ -1,105 +1,103 @@ set(SRC_CPP_FILES QmitkMultiLabelSegmentationPreferencePage.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkMultiLabelSegmentationView.cpp QmitkThresholdAction.cpp - QmitkAutocropAction.cpp QmitkConvertSurfaceToLabelAction.cpp QmitkConvertMaskToLabelAction.cpp QmitkConvertToMultiLabelSegmentationAction.cpp QmitkCreateMultiLabelSegmentationAction.cpp QmitkLoadMultiLabelPresetAction.cpp QmitkCreateMultiLabelPresetAction.cpp Common/QmitkDataSelectionWidget.cpp SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.cpp SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp SegmentationUtilities/ConvertToMl/QmitkConvertToMlWidget.cpp ) set(UI_FILES src/internal/QmitkMultiLabelSegmentationControls.ui src/internal/Common/QmitkDataSelectionWidgetControls.ui src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesViewControls.ui src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui src/internal/SegmentationUtilities/ConvertToMl/QmitkConvertToMlWidgetControls.ui ) set(MOC_H_FILES src/QmitkMultiLabelSegmentationPreferencePage.h src/internal/mitkPluginActivator.h src/internal/QmitkMultiLabelSegmentationView.h src/internal/QmitkThresholdAction.h - src/internal/QmitkAutocropAction.h src/internal/QmitkConvertSurfaceToLabelAction.h src/internal/QmitkLoadMultiLabelPresetAction.h src/internal/QmitkCreateMultiLabelPresetAction.h src/internal/QmitkConvertMaskToLabelAction.h src/internal/QmitkConvertToMultiLabelSegmentationAction.h src/internal/QmitkCreateMultiLabelSegmentationAction.h src/internal/Common/QmitkDataSelectionWidget.h src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.h src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h src/internal/SegmentationUtilities/ConvertToMl/QmitkConvertToMlWidget.h ) set(CACHED_RESOURCE_FILES resources/BooleanDifference_48x48.png resources/BooleanIntersection_48x48.png resources/BooleanOperations_48x48.png resources/BooleanUnion_48x48.png resources/Closing_48x48.png resources/CTKWidgets_48x48.png resources/deformablePlane.png resources/Dilate_48x48.png resources/Erode_48x48.png resources/FillHoles_48x48.png resources/Icons.svg resources/ImageMasking_48x48.png resources/MorphologicalOperations_48x48.png resources/multilabelsegmentation.svg resources/multilabelsegmentation_utilities.svg resources/NewLabel_48x48.png resources/NewSegmentationSession_48x48.png resources/Opening_48x48.png resources/SurfaceToImage_48x48.png plugin.xml ) set(QRC_FILES resources/multilabelsegmentation.qrc resources/MultiLabelSegmentationUtilities.qrc resources/MorphologicalOperationsWidget.qrc resources/BooleanOperationsWidget.qrc ) set(CPP_FILES) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) #usFunctionEmbedResources( #CPP_FILES # LIBRARY_NAME "liborg_mitk_gui_qt_multilabelsegmentation" #ROOT_DIR resources #FILES Interactions/SegmentationInteraction.xml # Interactions/ConfigSegmentation.xml #) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp deleted file mode 100644 index b04f88f974..0000000000 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -#include "QmitkAutocropAction.h" - -#include "mitkAutoCropImageFilter.h" -#include "mitkImageCast.h" -#include "mitkRenderingManager.h" -#include "mitkProgressBar.h" -#include - -#include - -//needed for qApp -#include - -QmitkAutocropAction::QmitkAutocropAction() -{ -} - -QmitkAutocropAction::~QmitkAutocropAction() -{ -} - -void QmitkAutocropAction::Run( const QList &selectedNodes ) -{ - foreach ( mitk::DataNode::Pointer node, selectedNodes ) - { - if (node) - { - mitk::Image::Pointer image = dynamic_cast( node->GetData() ); - if (image.IsNull()) return; - - mitk::ProgressBar::GetInstance()->AddStepsToDo(10); - mitk::ProgressBar::GetInstance()->Progress(2); - - qApp->processEvents(); - - mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New(); - cropFilter->SetInput( image ); - cropFilter->SetBackgroundValue( 0 ); - cropFilter->SetMarginFactor(1.5); - try - { - cropFilter->Update(); - - image = cropFilter->GetOutput(); - - if (image.IsNotNull()) - { - - if (image->GetDimension() == 4) - { - MITK_INFO << "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; - throw "4D AUTOCROP DOES NOT WORK AT THE MOMENT"; - - unsigned int timesteps = image->GetDimension(3); - for (unsigned int i = 0; i < timesteps; i++) - { - mitk::ImageTimeSelector::Pointer imageTimeSelector = mitk::ImageTimeSelector::New(); - imageTimeSelector->SetInput(image); - imageTimeSelector->SetTimeNr(i); - imageTimeSelector->UpdateLargestPossibleRegion(); - - // We split a long nested code line into separate calls for debugging: - mitk::ImageSource::OutputImageType *_3dSlice = imageTimeSelector->GetOutput(); - mitk::Image::Pointer _cropped3dSlice = this->IncreaseCroppedImageSize(_3dSlice); - - // +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ BUG +++ - { - mitk::ImageWriteAccessor writeAccess(_cropped3dSlice); - void *_data = writeAccess.GetData(); - - // - // We write some stripes into the image - if ((i & 1) == 0) - { - int depth = _cropped3dSlice->GetDimension(2); - int height = _cropped3dSlice->GetDimension(1); - int width = _cropped3dSlice->GetDimension(0); - - for (int z = 0; z < depth; ++z) - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; ++x) - reinterpret_cast(_data)[(width * height * z) + (width * y) + x] = x & 1; - } - // - - image->SetVolume(_data, i); - } - } - node->SetData( image ); // bug fix 3145 - } - else - { - node->SetData( this->IncreaseCroppedImageSize(image) ); // bug fix 3145 - } - // Reinit node - mitk::RenderingManager::GetInstance()->InitializeViews( - node->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - - } - } - catch(...) - { - MITK_ERROR << "Cropping image failed..."; - } - mitk::ProgressBar::GetInstance()->Progress(8); - } - else - { - MITK_INFO << " a nullptr node selected"; - } - } -} - -mitk::Image::Pointer QmitkAutocropAction::IncreaseCroppedImageSize( mitk::Image::Pointer image ) -{ - typedef itk::Image< short, 3 > ImageType; - typedef itk::Image< unsigned char, 3 > PADOutputImageType; - - ImageType::Pointer itkTransformImage = ImageType::New(); - mitk::CastToItkImage( image, itkTransformImage ); - - typedef itk::ConstantPadImageFilter< ImageType, PADOutputImageType > PadFilterType; - PadFilterType::Pointer padFilter = PadFilterType::New(); - - itk::SizeValueType upperPad[3]; - itk::SizeValueType lowerPad[3]; - int borderLiner = 3; - - mitk::Point3D mitkOriginPoint; - double origin[3]; - origin[0]=0; - origin[1]=0; - origin[2]=0; - itkTransformImage->SetOrigin(origin); - - lowerPad[0]=borderLiner; - lowerPad[1]=borderLiner; - lowerPad[2]=borderLiner; - - upperPad[0]=borderLiner; - upperPad[1]=borderLiner; - upperPad[2]=borderLiner; - - padFilter->SetInput(itkTransformImage); - padFilter->SetConstant(0); - padFilter->SetPadUpperBound(upperPad); - padFilter->SetPadLowerBound(lowerPad); - padFilter->UpdateLargestPossibleRegion(); - - - mitk::Image::Pointer paddedImage = mitk::Image::New(); - paddedImage->InitializeByItk(padFilter->GetOutput()); - mitk::CastToMitkImage(padFilter->GetOutput(), paddedImage); - - //calculate translation according to padding to get the new origin - mitk::Point3D paddedOrigin = image->GetGeometry()->GetOrigin(); - mitk::Vector3D spacing = image->GetGeometry()->GetSpacing(); - paddedOrigin[0] -= (borderLiner)*spacing[0]; - paddedOrigin[1] -= (borderLiner)*spacing[1]; - paddedOrigin[2] -= (borderLiner)*spacing[2]; - - paddedImage->GetGeometry()->SetOrigin( paddedOrigin ); - - return paddedImage; -} - -void QmitkAutocropAction::SetSmoothed(bool /*smoothed*/) -{ - //not needed -} - -void QmitkAutocropAction::SetDecimated(bool /*decimated*/) -{ - //not needed -} - -void QmitkAutocropAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) -{ - //not needed -} - -void QmitkAutocropAction::SetFunctionality(berry::QtViewPart* /*functionality*/) -{ - //not needed -} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.h deleted file mode 100644 index eb00262ea5..0000000000 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.h +++ /dev/null @@ -1,50 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ -#ifndef QMITK_AUTOCROPACTION_H -#define QMITK_AUTOCROPACTION_H - -#include "mitkIContextMenuAction.h" - -#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" - -#include "vector" -#include "mitkDataNode.h" -#include "mitkImage.h" - -class MITK_QT_SEGMENTATION QmitkAutocropAction : public QObject, public mitk::IContextMenuAction -{ - Q_OBJECT - Q_INTERFACES(mitk::IContextMenuAction) - -public: - - QmitkAutocropAction(); - ~QmitkAutocropAction() override; - - //interface methods - void Run( const QList& selectedNodes ) override; - void SetDataStorage(mitk::DataStorage* dataStorage) override; - void SetSmoothed(bool smoothed) override; - void SetDecimated(bool decimated) override; - void SetFunctionality(berry::QtViewPart* functionality) override; - -protected: - - mitk::Image::Pointer IncreaseCroppedImageSize( mitk::Image::Pointer image ); - -private: - - typedef QList NodeList; - -}; - -#endif // QMITK_AUTOCROPACTION_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp index 88b344ea27..24ab1cb031 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp @@ -1,1061 +1,1062 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkMultiLabelSegmentationView.h" // blueberry #include #include // mitk #include "mitkApplicationCursor.h" #include "mitkLabelSetImage.h" #include "mitkStatusBar.h" #include "mitkToolManagerProvider.h" #include "mitkInteractionEventObserver.h" #include "mitkPlanePositionManager.h" #include "mitkPluginActivator.h" #include "mitkSegTool2D.h" #include "mitkImageTimeSelector.h" #include "mitkNodePredicateSubGeometry.h" // Qmitk #include "QmitkNewSegmentationDialog.h" #include "QmitkRenderWindow.h" #include "QmitkSegmentationOrganNamesHandling.cpp" // us #include #include #include #include #include // Qt #include #include #include #include #include #include "tinyxml.h" #include #include const std::string QmitkMultiLabelSegmentationView::VIEW_ID = "org.mitk.views.multilabelsegmentation"; QmitkMultiLabelSegmentationView::QmitkMultiLabelSegmentationView() : m_Parent(nullptr), m_IRenderWindowPart(nullptr), m_ToolManager(nullptr), m_ReferenceNode(nullptr), m_WorkingNode(nullptr), m_AutoSelectionEnabled(false), m_MouseCursorSet(false) { m_SegmentationPredicate = mitk::NodePredicateAnd::New(); m_SegmentationPredicate->AddPredicate(mitk::TNodePredicateDataType::New()); m_SegmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); mitk::NodePredicateProperty::Pointer isBinary = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateAnd::Pointer isMask = mitk::NodePredicateAnd::New(isBinary, isImage); mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); mitk::NodePredicateDataType::Pointer isOdf = mitk::NodePredicateDataType::New("OdfImage"); auto isSegment = mitk::NodePredicateDataType::New("Segment"); mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); validImages->AddPredicate(mitk::NodePredicateAnd::New(isImage, mitk::NodePredicateNot::New(isSegment))); validImages->AddPredicate(isDwi); validImages->AddPredicate(isDti); validImages->AddPredicate(isOdf); m_ReferencePredicate = mitk::NodePredicateAnd::New(); m_ReferencePredicate->AddPredicate(validImages); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(m_SegmentationPredicate)); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(isMask)); m_ReferencePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); } QmitkMultiLabelSegmentationView::~QmitkMultiLabelSegmentationView() { // Loose LabelSetConnections OnLooseLabelSetConnection(); } void QmitkMultiLabelSegmentationView::CreateQtPartControl(QWidget *parent) { // setup the basic GUI of this view m_Parent = parent; m_Controls.setupUi(parent); // *------------------------ // * Shortcuts // *------------------------ QShortcut* visibilityShortcut = new QShortcut(QKeySequence("CTRL+H"), parent); connect(visibilityShortcut, &QShortcut::activated, this, &QmitkMultiLabelSegmentationView::OnVisibilityShortcutActivated); QShortcut* labelToggleShortcut = new QShortcut(QKeySequence("CTRL+L"), parent); connect(labelToggleShortcut, &QShortcut::activated, this, &QmitkMultiLabelSegmentationView::OnLabelToggleShortcutActivated); // *------------------------ // * DATA SELECTION WIDGETS // *------------------------ m_Controls.m_ReferenceNodeSelector->SetNodePredicate(m_ReferencePredicate); m_Controls.m_ReferenceNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.m_ReferenceNodeSelector->SetInvalidInfo("Select an image"); m_Controls.m_ReferenceNodeSelector->SetPopUpTitel("Select an image"); m_Controls.m_ReferenceNodeSelector->SetPopUpHint("Select an image that should be used to define the geometry and bounds of the segmentation."); m_Controls.m_WorkingNodeSelector->SetNodePredicate(m_SegmentationPredicate); m_Controls.m_WorkingNodeSelector->SetDataStorage(this->GetDataStorage()); m_Controls.m_WorkingNodeSelector->SetInvalidInfo("Select a segmentation"); m_Controls.m_WorkingNodeSelector->SetPopUpTitel("Select a segmentation"); m_Controls.m_WorkingNodeSelector->SetPopUpHint("Select a segmentation that should be modified. Only segmentation with the same geometry and within the bounds of the reference image are selected."); connect(m_Controls.m_ReferenceNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this,&QmitkMultiLabelSegmentationView::OnReferenceSelectionChanged); connect(m_Controls.m_WorkingNodeSelector, &QmitkAbstractNodeSelectionWidget::CurrentSelectionChanged, this,&QmitkMultiLabelSegmentationView::OnSegmentationSelectionChanged); // *------------------------ // * ToolManager // *------------------------ m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(mitk::ToolManagerProvider::MULTILABEL_SEGMENTATION); m_ToolManager->SetDataStorage(*(this->GetDataStorage())); m_ToolManager->InitializeTools(); m_Controls.m_ManualToolSelectionBox2D->SetToolManager(*m_ToolManager); m_Controls.m_ManualToolSelectionBox3D->SetToolManager(*m_ToolManager); // *------------------------ // * LabelSetWidget // *------------------------ m_Controls.m_LabelSetWidget->SetDataStorage(this->GetDataStorage()); m_Controls.m_LabelSetWidget->SetOrganColors(mitk::OrganNamesHandling::GetDefaultOrganColorString()); m_Controls.m_LabelSetWidget->hide(); // *------------------------ // * Interpolation // *------------------------ m_Controls.m_SurfaceBasedInterpolatorWidget->SetDataStorage(*(this->GetDataStorage())); m_Controls.m_SliceBasedInterpolatorWidget->SetDataStorage(*(this->GetDataStorage())); connect(m_Controls.m_cbInterpolation, SIGNAL(activated(int)), this, SLOT(OnInterpolationSelectionChanged(int))); m_Controls.m_cbInterpolation->setCurrentIndex(0); m_Controls.m_swInterpolation->hide(); m_Controls.m_gbInterpolation->hide(); // See T27436 QString segTools2D = tr("Add Subtract Fill Erase Paint Wipe 'Region Growing' FastMarching2D Correction 'Live Wire'"); QString segTools3D = tr("Threshold 'Two Thresholds' 'Auto Threshold' 'Multiple Otsu'"); std::regex extSegTool2DRegEx("SegTool2D$"); std::regex extSegTool3DRegEx("SegTool3D$"); auto tools = m_ToolManager->GetTools(); for (const auto &tool : tools) { if (std::regex_search(tool->GetNameOfClass(), extSegTool2DRegEx)) { segTools2D.append(QString(" '%1'").arg(tool->GetName())); } else if (std::regex_search(tool->GetNameOfClass(), extSegTool3DRegEx)) { segTools3D.append(QString(" '%1'").arg(tool->GetName())); } } // *------------------------ // * ToolSelection 2D // *------------------------ m_Controls.m_ManualToolSelectionBox2D->SetGenerateAccelerators(true); m_Controls.m_ManualToolSelectionBox2D->SetToolGUIArea(m_Controls.m_ManualToolGUIContainer2D); m_Controls.m_ManualToolSelectionBox2D->SetDisplayedToolGroups(segTools2D.toStdString()); // todo: "Correction // 'Live Wire'" m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); connect(m_Controls.m_ManualToolSelectionBox2D, SIGNAL(ToolSelected(int)), this, SLOT(OnManualTool2DSelected(int))); // *------------------------ // * ToolSelection 3D // *------------------------ m_Controls.m_ManualToolSelectionBox3D->SetGenerateAccelerators(true); m_Controls.m_ManualToolSelectionBox3D->SetToolGUIArea(m_Controls.m_ManualToolGUIContainer3D); m_Controls.m_ManualToolSelectionBox3D->SetDisplayedToolGroups(segTools3D.toStdString()); // todo add : FastMarching3D RegionGrowing Watershed m_Controls.m_ManualToolSelectionBox3D->SetLayoutColumns(2); m_Controls.m_ManualToolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); // *------------------------* // * Connect PushButtons (pb) // *------------------------* connect(m_Controls.m_pbNewLabel, SIGNAL(clicked()), this, SLOT(OnNewLabel())); connect(m_Controls.m_pbNewSegmentationSession, SIGNAL(clicked()), this, SLOT(OnNewSegmentationSession())); connect(m_Controls.m_pbShowLabelTable, SIGNAL(toggled(bool)), this, SLOT(OnShowLabelTable(bool))); // *------------------------* // * Connect LabelSetWidget // *------------------------* connect(m_Controls.m_LabelSetWidget, SIGNAL(goToLabel(const mitk::Point3D &)), this, SLOT(OnGoToLabel(const mitk::Point3D &))); connect(m_Controls.m_LabelSetWidget, SIGNAL(resetView()), this, SLOT(OnResetView())); // *------------------------* // * DATA SLECTION WIDGET // *------------------------* m_IRenderWindowPart = this->GetRenderWindowPart(); if (m_IRenderWindowPart) { QList controllers; controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); m_Controls.m_SliceBasedInterpolatorWidget->SetSliceNavigationControllers(controllers); } // this->InitializeListeners(); connect(m_Controls.m_btAddLayer, SIGNAL(clicked()), this, SLOT(OnAddLayer())); connect(m_Controls.m_btDeleteLayer, SIGNAL(clicked()), this, SLOT(OnDeleteLayer())); connect(m_Controls.m_btPreviousLayer, SIGNAL(clicked()), this, SLOT(OnPreviousLayer())); connect(m_Controls.m_btNextLayer, SIGNAL(clicked()), this, SLOT(OnNextLayer())); connect(m_Controls.m_btLockExterior, SIGNAL(toggled(bool)), this, SLOT(OnLockExteriorToggled(bool))); connect(m_Controls.m_cbActiveLayer, SIGNAL(currentIndexChanged(int)), this, SLOT(OnChangeLayer(int))); m_Controls.m_btAddLayer->setEnabled(false); m_Controls.m_btDeleteLayer->setEnabled(false); m_Controls.m_btNextLayer->setEnabled(false); m_Controls.m_btPreviousLayer->setEnabled(false); m_Controls.m_cbActiveLayer->setEnabled(false); m_Controls.m_pbNewLabel->setEnabled(false); m_Controls.m_btLockExterior->setEnabled(false); m_Controls.m_pbShowLabelTable->setEnabled(false); // Make sure the GUI notices if appropriate data is already present on creation m_Controls.m_ReferenceNodeSelector->SetAutoSelectNewNodes(true); m_Controls.m_WorkingNodeSelector->SetAutoSelectNewNodes(true); } void QmitkMultiLabelSegmentationView::Activated() { m_ToolManager->SetReferenceData(m_Controls.m_ReferenceNodeSelector->GetSelectedNode()); m_ToolManager->SetWorkingData(m_Controls.m_WorkingNodeSelector->GetSelectedNode()); } void QmitkMultiLabelSegmentationView::Deactivated() { // Not yet implemented } void QmitkMultiLabelSegmentationView::Visible() { // Not yet implemented } void QmitkMultiLabelSegmentationView::Hidden() { // Not yet implemented } int QmitkMultiLabelSegmentationView::GetSizeFlags(bool width) { if (!width) { return berry::Constants::MIN | berry::Constants::MAX | berry::Constants::FILL; } else { return 0; } } int QmitkMultiLabelSegmentationView::ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult) { if (width == false) { return 100; } else { return preferredResult; } } /************************************************************************/ /* protected slots */ /************************************************************************/ void QmitkMultiLabelSegmentationView::OnVisibilityShortcutActivated() { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); bool isVisible = false; workingNode->GetBoolProperty("visible", isVisible); workingNode->SetVisibility(!isVisible); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkMultiLabelSegmentationView::OnLabelToggleShortcutActivated() { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); WaitCursorOn(); workingImage->GetActiveLabelSet()->SetNextActiveLabel(); workingImage->Modified(); WaitCursorOff(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkMultiLabelSegmentationView::OnManualTool2DSelected(int id) { this->ResetMouseCursor(); mitk::StatusBar::GetInstance()->DisplayText(""); if (id >= 0) { std::string text = "Active Tool: \""; text += m_ToolManager->GetToolById(id)->GetName(); text += "\""; mitk::StatusBar::GetInstance()->DisplayText(text.c_str()); us::ModuleResource resource = m_ToolManager->GetToolById(id)->GetCursorIconResource(); this->SetMouseCursor(resource, 0, 0); } } void QmitkMultiLabelSegmentationView::OnNewLabel() { m_ToolManager->ActivateTool(-1); if (m_ReferenceNode.IsNull()) { QMessageBox::information( m_Parent, "New Segmentation Session", "Please load and select a patient image before starting some action."); return; } if (nullptr == m_ReferenceNode->GetData()) { QMessageBox::information( m_Parent, "New Segmentation Session", "Please load and select a patient image before starting some action."); return; } mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); if (!workingNode) { QMessageBox::information( m_Parent, "New Segmentation Session", "Please load and select a patient image before starting some action."); return; } mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); if (!workingImage) { QMessageBox::information( m_Parent, "New Segmentation Session", "Please load and select a patient image before starting some action."); return; } QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog(m_Parent); dialog->SetSuggestionList(mitk::OrganNamesHandling::GetDefaultOrganColorString()); dialog->setWindowTitle("New Label"); int dialogReturnValue = dialog->exec(); if (dialogReturnValue == QDialog::Rejected) { return; } QString segName = dialog->GetSegmentationName(); if (segName.isEmpty()) { segName = "Unnamed"; } workingImage->GetActiveLabelSet()->AddLabel(segName.toStdString(), dialog->GetColor()); UpdateControls(); m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); this->ReinitializeViews(); } void QmitkMultiLabelSegmentationView::OnShowLabelTable(bool value) { if (value) m_Controls.m_LabelSetWidget->show(); else m_Controls.m_LabelSetWidget->hide(); } void QmitkMultiLabelSegmentationView::OnNewSegmentationSession() { mitk::DataNode *referenceNode = m_Controls.m_ReferenceNodeSelector->GetSelectedNode(); if (!referenceNode) { QMessageBox::information( m_Parent, "New Segmentation Session", "Please load and select a patient image before starting some action."); return; } m_ToolManager->ActivateTool(-1); mitk::Image::ConstPointer referenceImage = dynamic_cast(referenceNode->GetData()); assert(referenceImage); const auto currentTimePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); unsigned int imageTimeStep = 0; if (referenceImage->GetTimeGeometry()->IsValidTimePoint(currentTimePoint)) { imageTimeStep = referenceImage->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint); } auto segTemplateImage = referenceImage; if (referenceImage->GetDimension() > 3) { auto result = QMessageBox::question(m_Parent, tr("Generate a static mask?"), tr("The selected image has multiple time steps. You can either generate a simple/static masks resembling the geometry of the first timestep of the image. Or you can generate a dynamic mask that equals the selected image in geometry and number of timesteps; thus a dynamic mask can change over time (e.g. according to the image)."), tr("Yes, generate a static mask"), tr("No, generate a dynamic mask"), QString(), 0, 0); if (result == 0) { auto selector = mitk::ImageTimeSelector::New(); selector->SetInput(referenceImage); selector->SetTimeNr(0); selector->Update(); const auto refTimeGeometry = referenceImage->GetTimeGeometry(); auto newTimeGeometry = mitk::ProportionalTimeGeometry::New(); newTimeGeometry->SetFirstTimePoint(refTimeGeometry->GetMinimumTimePoint()); newTimeGeometry->SetStepDuration(refTimeGeometry->GetMaximumTimePoint() - refTimeGeometry->GetMinimumTimePoint()); mitk::Image::Pointer newImage = selector->GetOutput(); newTimeGeometry->SetTimeStepGeometry(referenceImage->GetGeometry(imageTimeStep), 0); newImage->SetTimeGeometry(newTimeGeometry); segTemplateImage = newImage; } } QString newName = QString::fromStdString(referenceNode->GetName()); newName.append("-labels"); bool ok = false; newName = QInputDialog::getText(m_Parent, "New Segmentation Session", "New name:", QLineEdit::Normal, newName, &ok); if (!ok) { return; } this->WaitCursorOn(); mitk::LabelSetImage::Pointer workingImage = mitk::LabelSetImage::New(); try { workingImage->Initialize(segTemplateImage); } catch (mitk::Exception& e) { this->WaitCursorOff(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(m_Parent, "New Segmentation Session", "Could not create a new segmentation session.\n"); return; } this->WaitCursorOff(); mitk::DataNode::Pointer workingNode = mitk::DataNode::New(); workingNode->SetData(workingImage); workingNode->SetName(newName.toStdString()); workingImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(referenceNode->GetName().c_str())); workingImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New(newName.toStdString().c_str())); if (!GetDataStorage()->Exists(workingNode)) { GetDataStorage()->Add(workingNode, referenceNode); } m_Controls.m_WorkingNodeSelector->SetCurrentSelectedNode(workingNode); OnNewLabel(); } void QmitkMultiLabelSegmentationView::OnGoToLabel(const mitk::Point3D& pos) { if (m_IRenderWindowPart) m_IRenderWindowPart->SetSelectedPosition(pos); } void QmitkMultiLabelSegmentationView::OnResetView() { if (m_IRenderWindowPart) m_IRenderWindowPart->ForceImmediateUpdate(); } void QmitkMultiLabelSegmentationView::OnAddLayer() { m_ToolManager->ActivateTool(-1); mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); QString question = "Do you really want to add a layer to the current segmentation session?"; QMessageBox::StandardButton answerButton = QMessageBox::question( m_Controls.m_LabelSetWidget, "Add layer", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); if (answerButton != QMessageBox::Yes) return; try { WaitCursorOn(); workingImage->AddLayer(); WaitCursorOff(); } catch ( mitk::Exception& e ) { WaitCursorOff(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information( m_Controls.m_LabelSetWidget, "Add Layer", "Could not add a new layer. See error log for details.\n"); return; } OnNewLabel(); } void QmitkMultiLabelSegmentationView::OnDeleteLayer() { m_ToolManager->ActivateTool(-1); mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); if (workingImage->GetNumberOfLayers() < 2) return; QString question = "Do you really want to delete the current layer?"; QMessageBox::StandardButton answerButton = QMessageBox::question( m_Controls.m_LabelSetWidget, "Delete layer", question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); if (answerButton != QMessageBox::Yes) { return; } try { this->WaitCursorOn(); workingImage->RemoveLayer(); this->WaitCursorOff(); } catch (mitk::Exception& e) { this->WaitCursorOff(); MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(m_Controls.m_LabelSetWidget, "Delete Layer", "Could not delete the currently active layer. See error log for details.\n"); return; } UpdateControls(); m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); } void QmitkMultiLabelSegmentationView::OnPreviousLayer() { m_ToolManager->ActivateTool(-1); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); OnChangeLayer(workingImage->GetActiveLayer() - 1); } void QmitkMultiLabelSegmentationView::OnNextLayer() { m_ToolManager->ActivateTool(-1); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); OnChangeLayer(workingImage->GetActiveLayer() + 1); } void QmitkMultiLabelSegmentationView::OnChangeLayer(int layer) { m_ToolManager->ActivateTool(-1); mitk::DataNode *workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage *workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); this->WaitCursorOn(); workingImage->SetActiveLayer(layer); this->WaitCursorOff(); UpdateControls(); m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); } void QmitkMultiLabelSegmentationView::OnDeactivateActiveTool() { m_ToolManager->ActivateTool(-1); } void QmitkMultiLabelSegmentationView::OnLockExteriorToggled(bool checked) { mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); assert(workingNode); mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); assert(workingImage); workingImage->GetLabel(0)->SetLocked(checked); } void QmitkMultiLabelSegmentationView::OnReferenceSelectionChanged(QList /*nodes*/) { m_ToolManager->ActivateTool(-1); auto refNode = m_Controls.m_ReferenceNodeSelector->GetSelectedNode(); m_ReferenceNode = refNode; m_ToolManager->SetReferenceData(m_ReferenceNode); if (m_ReferenceNode.IsNotNull()) { auto segPredicate = mitk::NodePredicateAnd::New(m_SegmentationPredicate.GetPointer(), mitk::NodePredicateSubGeometry::New(refNode->GetData()->GetGeometry())); m_Controls.m_WorkingNodeSelector->SetNodePredicate(segPredicate); if (m_AutoSelectionEnabled) { // hide all image nodes to later show only the automatically selected ones mitk::DataStorage::SetOfObjects::ConstPointer patientNodes = GetDataStorage()->GetSubset(m_ReferencePredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = patientNodes->begin(); iter != patientNodes->end(); ++iter) { (*iter)->SetVisibility(false); } } m_ReferenceNode->SetVisibility(true); } UpdateControls(); } void QmitkMultiLabelSegmentationView::OnSegmentationSelectionChanged(QList /*nodes*/) { m_ToolManager->ActivateTool(-1); if (m_WorkingNode.IsNotNull()) OnLooseLabelSetConnection(); m_WorkingNode = m_Controls.m_WorkingNodeSelector->GetSelectedNode(); m_ToolManager->SetWorkingData(m_WorkingNode); if (m_WorkingNode.IsNotNull()) { OnEstablishLabelSetConnection(); if (m_AutoSelectionEnabled) { // hide all segmentation nodes to later show only the automatically selected ones mitk::DataStorage::SetOfObjects::ConstPointer segmentationNodes = GetDataStorage()->GetSubset(m_SegmentationPredicate); for (mitk::DataStorage::SetOfObjects::const_iterator iter = segmentationNodes->begin(); iter != segmentationNodes->end(); ++iter) { (*iter)->SetVisibility(false); } } m_WorkingNode->SetVisibility(true); } UpdateControls(); if (m_WorkingNode.IsNotNull()) { m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); this->ReinitializeViews(); } } void QmitkMultiLabelSegmentationView::OnInterpolationSelectionChanged(int index) { if (index == 1) { m_Controls.m_SurfaceBasedInterpolatorWidget->m_Controls.m_btStart->setChecked(false);//OnToggleWidgetActivation(false); m_Controls.m_swInterpolation->setCurrentIndex(0); m_Controls.m_swInterpolation->show(); } else if (index == 2) { m_Controls.m_SliceBasedInterpolatorWidget->m_Controls.m_btStart->setChecked(false); m_Controls.m_swInterpolation->setCurrentIndex(1); m_Controls.m_swInterpolation->show(); } else { m_Controls.m_SurfaceBasedInterpolatorWidget->m_Controls.m_btStart->setChecked(false); m_Controls.m_SliceBasedInterpolatorWidget->m_Controls.m_btStart->setChecked(false); m_Controls.m_swInterpolation->setCurrentIndex(2); m_Controls.m_swInterpolation->hide(); } } /************************************************************************/ /* protected */ /************************************************************************/ void QmitkMultiLabelSegmentationView::OnPreferencesChanged(const berry::IBerryPreferences* prefs) { if (m_Parent && m_WorkingNode.IsNotNull()) { m_AutoSelectionEnabled = prefs->GetBool("auto selection", false); mitk::BoolProperty::Pointer drawOutline = mitk::BoolProperty::New(prefs->GetBool("draw outline", true)); mitk::BoolProperty::Pointer volumeRendering = mitk::BoolProperty::New(prefs->GetBool("volume rendering", false)); mitk::LabelSetImage* labelSetImage; mitk::DataNode* segmentation; // iterate all segmentations (binary (single label) and LabelSetImages) mitk::NodePredicateProperty::Pointer isBinaryPredicate = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)); mitk::NodePredicateOr::Pointer allSegmentationsPredicate = mitk::NodePredicateOr::New(isBinaryPredicate, m_SegmentationPredicate); mitk::DataStorage::SetOfObjects::ConstPointer allSegmentations = GetDataStorage()->GetSubset(allSegmentationsPredicate); for (mitk::DataStorage::SetOfObjects::const_iterator it = allSegmentations->begin(); it != allSegmentations->end(); ++it) { segmentation = *it; labelSetImage = dynamic_cast(segmentation->GetData()); if (nullptr != labelSetImage) { // segmentation node is a multi label segmentation segmentation->SetProperty("labelset.contour.active", drawOutline); //segmentation->SetProperty("opacity", mitk::FloatProperty::New(drawOutline->GetValue() ? 1.0f : 0.3f)); segmentation->SetProperty("volumerendering", volumeRendering); // force render window update to show outline segmentation->GetData()->Modified(); } else if (nullptr != segmentation->GetData()) { // node is actually a 'single label' segmentation, // but its outline property can be set in the 'multi label' segmentation preference page as well bool isBinary = false; segmentation->GetBoolProperty("binary", isBinary); if (isBinary) { segmentation->SetProperty("outline binary", drawOutline); segmentation->SetProperty("outline width", mitk::FloatProperty::New(2.0)); //segmentation->SetProperty("opacity", mitk::FloatProperty::New(drawOutline->GetValue() ? 1.0f : 0.3f)); segmentation->SetProperty("volumerendering", volumeRendering); // force render window update to show outline segmentation->GetData()->Modified(); } } else { // "interpolation feedback" data nodes have binary flag but don't have a data set. So skip them for now. MITK_INFO << "DataNode " << segmentation->GetName() << " doesn't contain a base data."; } } } } void QmitkMultiLabelSegmentationView::NodeRemoved(const mitk::DataNode *node) { bool isHelperObject(false); node->GetBoolProperty("helper object", isHelperObject); if (isHelperObject) { return; } if (m_ReferenceNode.IsNotNull() && dynamic_cast(node->GetData())) { // remove all possible contour markers of the segmentation mitk::DataStorage::SetOfObjects::ConstPointer allContourMarkers = this->GetDataStorage()->GetDerivations( node, mitk::NodePredicateProperty::New("isContourMarker", mitk::BoolProperty::New(true))); ctkPluginContext *context = mitk::PluginActivator::getContext(); ctkServiceReference ppmRef = context->getServiceReference(); mitk::PlanePositionManagerService *service = context->getService(ppmRef); for (mitk::DataStorage::SetOfObjects::ConstIterator it = allContourMarkers->Begin(); it != allContourMarkers->End(); ++it) { std::string nodeName = node->GetName(); unsigned int t = nodeName.find_last_of(" "); unsigned int id = atof(nodeName.substr(t + 1).c_str()) - 1; service->RemovePlanePosition(id); this->GetDataStorage()->Remove(it->Value()); } context->ungetService(ppmRef); service = nullptr; } } void QmitkMultiLabelSegmentationView::OnEstablishLabelSetConnection() { if (m_WorkingNode.IsNull()) { return; } mitk::LabelSetImage *workingImage = dynamic_cast(m_WorkingNode->GetData()); assert(workingImage); workingImage->GetActiveLabelSet()->AddLabelEvent += mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->RemoveLabelEvent += mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->ModifyLabelEvent += mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->AllLabelsModifiedEvent += mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->ActiveLabelEvent += mitk::MessageDelegate1(m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::SelectLabelByPixelValue); workingImage->BeforeChangeLayerEvent += mitk::MessageDelegate( this, &QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); } void QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection() { if (m_WorkingNode.IsNull()) - { return; - } - mitk::LabelSetImage *workingImage = dynamic_cast(m_WorkingNode->GetData()); - assert(workingImage); + + auto* workingImage = dynamic_cast(m_WorkingNode->GetData()); + + if (nullptr == workingImage) + return; // data (type) was changed in-place, e.g. LabelSetImage -> Image // Reset LabelSetWidget Events workingImage->GetActiveLabelSet()->AddLabelEvent -= mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->RemoveLabelEvent -= mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::ResetAllTableWidgetItems); workingImage->GetActiveLabelSet()->ModifyLabelEvent -= mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->AllLabelsModifiedEvent -= mitk::MessageDelegate( m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::UpdateAllTableWidgetItems); workingImage->GetActiveLabelSet()->ActiveLabelEvent -= mitk::MessageDelegate1(m_Controls.m_LabelSetWidget, &QmitkLabelSetWidget::SelectLabelByPixelValue); workingImage->BeforeChangeLayerEvent -= mitk::MessageDelegate( this, &QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); } void QmitkMultiLabelSegmentationView::SetFocus() { } void QmitkMultiLabelSegmentationView::UpdateControls() { mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); bool hasReferenceNode = referenceNode != nullptr; mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); bool hasValidWorkingNode = workingNode != nullptr; m_Controls.m_pbNewLabel->setEnabled(false); m_Controls.m_gbInterpolation->setEnabled(false); m_Controls.m_SliceBasedInterpolatorWidget->setEnabled(false); m_Controls.m_SurfaceBasedInterpolatorWidget->setEnabled(false); m_Controls.m_LabelSetWidget->setEnabled(false); m_Controls.m_btAddLayer->setEnabled(false); m_Controls.m_btDeleteLayer->setEnabled(false); m_Controls.m_cbActiveLayer->setEnabled(false); m_Controls.m_btPreviousLayer->setEnabled(false); m_Controls.m_btNextLayer->setEnabled(false); m_Controls.m_btLockExterior->setChecked(false); m_Controls.m_btLockExterior->setEnabled(false); m_Controls.m_pbShowLabelTable->setChecked(false); m_Controls.m_pbShowLabelTable->setEnabled(false); m_Controls.m_ManualToolSelectionBox3D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); if (hasValidWorkingNode) { // TODO adapt tool manager so that this check is done there, e.g. convenience function mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); hasValidWorkingNode = workingImage != nullptr; if (hasValidWorkingNode) { m_Controls.m_pbNewLabel->setEnabled(true); m_Controls.m_btLockExterior->setEnabled(true); m_Controls.m_pbShowLabelTable->setEnabled(true); m_Controls.m_gbInterpolation->setEnabled(true); m_Controls.m_SliceBasedInterpolatorWidget->setEnabled(true); m_Controls.m_SurfaceBasedInterpolatorWidget->setEnabled(true); m_Controls.m_LabelSetWidget->setEnabled(true); m_Controls.m_btAddLayer->setEnabled(true); int activeLayer = workingImage->GetActiveLayer(); int numberOfLayers = workingImage->GetNumberOfLayers(); m_Controls.m_cbActiveLayer->blockSignals(true); m_Controls.m_cbActiveLayer->clear(); for (unsigned int lidx = 0; lidx < workingImage->GetNumberOfLayers(); ++lidx) { m_Controls.m_cbActiveLayer->addItem(QString::number(lidx)); } m_Controls.m_cbActiveLayer->setCurrentIndex(activeLayer); m_Controls.m_cbActiveLayer->blockSignals(false); m_Controls.m_cbActiveLayer->setEnabled(numberOfLayers > 1); m_Controls.m_btDeleteLayer->setEnabled(numberOfLayers > 1); m_Controls.m_btPreviousLayer->setEnabled(activeLayer > 0); m_Controls.m_btNextLayer->setEnabled(activeLayer != numberOfLayers - 1); m_Controls.m_btLockExterior->setChecked(workingImage->GetLabel(0, activeLayer)->GetLocked()); m_Controls.m_pbShowLabelTable->setChecked(workingImage->GetNumberOfLabels() > 1 /*1st is exterior*/); //MLI TODO //m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithWorkingDataVisible); } } if (hasValidWorkingNode && hasReferenceNode) { int layer = -1; referenceNode->GetIntProperty("layer", layer); workingNode->SetIntProperty("layer", layer + 1); } this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } void QmitkMultiLabelSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) { if (m_IRenderWindowPart != renderWindowPart) { m_IRenderWindowPart = renderWindowPart; m_Parent->setEnabled(true); QList controllers; controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); controllers.push_back(m_IRenderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); m_Controls.m_SliceBasedInterpolatorWidget->SetSliceNavigationControllers(controllers); } } void QmitkMultiLabelSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/) { m_ToolManager->ActivateTool(-1); m_IRenderWindowPart = nullptr; m_Parent->setEnabled(false); } void QmitkMultiLabelSegmentationView::ResetMouseCursor() { if (m_MouseCursorSet) { mitk::ApplicationCursor::GetInstance()->PopCursor(); m_MouseCursorSet = false; } } void QmitkMultiLabelSegmentationView::SetMouseCursor(const us::ModuleResource resource, int hotspotX, int hotspotY) { // Remove previously set mouse cursor if (m_MouseCursorSet) this->ResetMouseCursor(); if (resource) { us::ModuleResourceStream cursor(resource, std::ios::binary); mitk::ApplicationCursor::GetInstance()->PushCursor(cursor, hotspotX, hotspotY); m_MouseCursorSet = true; } } void QmitkMultiLabelSegmentationView::InitializeListeners() { if (m_Interactor.IsNull()) { us::Module* module = us::GetModuleContext()->GetModule(); std::vector resources = module->FindResources("/", "*", true); for (std::vector::iterator iter = resources.begin(); iter != resources.end(); ++iter) { MITK_INFO << iter->GetResourcePath(); } m_Interactor = mitk::SegmentationInteractor::New(); if (!m_Interactor->LoadStateMachine("SegmentationInteraction.xml", module)) { MITK_WARN << "Error loading state machine"; } if (!m_Interactor->SetEventConfig("ConfigSegmentation.xml", module)) { MITK_WARN << "Error loading state machine configuration"; } // Register as listener via micro services us::ServiceProperties props; props["name"] = std::string("SegmentationInteraction"); m_ServiceRegistration = us::GetModuleContext()->RegisterService(m_Interactor.GetPointer(), props); } } void QmitkMultiLabelSegmentationView::ReinitializeViews() const { if (m_ReferenceNode.IsNotNull() && nullptr != m_ReferenceNode->GetData()) { const auto currentTimePoint = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetSelectedTimePoint(); unsigned int imageTimeStep = 0; if (m_ReferenceNode->GetData()->GetTimeGeometry()->IsValidTimePoint(currentTimePoint)) { imageTimeStep = m_ReferenceNode->GetData()->GetTimeGeometry()->TimePointToTimeStep(currentTimePoint); } mitk::RenderingManager::GetInstance()->InitializeViews(m_ReferenceNode->GetData()->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(imageTimeStep); } } diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp index 422afba21c..ac1102b2a0 100644 --- a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp @@ -1,58 +1,56 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkPluginActivator.h" #include "QmitkMultiLabelSegmentationView.h" #include "QmitkThresholdAction.h" -#include "QmitkAutocropAction.h" #include "QmitkConvertSurfaceToLabelAction.h" #include "QmitkConvertMaskToLabelAction.h" #include "QmitkConvertToMultiLabelSegmentationAction.h" #include "QmitkCreateMultiLabelSegmentationAction.h" #include "QmitkMultiLabelSegmentationPreferencePage.h" #include "QmitkLoadMultiLabelPresetAction.h" #include "QmitkCreateMultiLabelPresetAction.h" #include "SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.h" #include ctkPluginContext* mitk::PluginActivator::m_Context = nullptr; //MLI TODO US_INITIALIZE_MODULE //("MultiLabelSegmentation", "liborg_mitk_gui_qt_multilabelsegmentation") void mitk::PluginActivator::start(ctkPluginContext *context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkMultiLabelSegmentationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context) - BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConvertSurfaceToLabelAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConvertMaskToLabelAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkConvertToMultiLabelSegmentationAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkCreateMultiLabelSegmentationAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkCreateMultiLabelPresetAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkLoadMultiLabelPresetAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkMultiLabelSegmentationPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkMultiLabelSegmentationUtilitiesView, context) m_Context = context; } void mitk::PluginActivator::stop(ctkPluginContext*) { } ctkPluginContext* mitk::PluginActivator::getContext() { return m_Context; } diff --git a/Plugins/org.mitk.gui.qt.segmentation/files.cmake b/Plugins/org.mitk.gui.qt.segmentation/files.cmake index 69bc5eadc3..ae0e49a418 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/files.cmake +++ b/Plugins/org.mitk.gui.qt.segmentation/files.cmake @@ -1,79 +1,81 @@ set(SRC_CPP_FILES QmitkSegmentationPreferencePage.cpp ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkSegmentationView.cpp QmitkThresholdAction.cpp QmitkCreatePolygonModelAction.cpp #QmitkStatisticsAction.cpp QmitkAutocropAction.cpp + QmitkAutocropLabelSetImageAction.cpp QmitkDeformableClippingPlaneView.cpp Common/QmitkDataSelectionWidget.cpp SegmentationUtilities/QmitkSegmentationUtilitiesView.cpp SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.cpp SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp ) set(UI_FILES src/internal/QmitkSegmentationControls.ui src/internal/QmitkDeformableClippingPlaneViewControls.ui src/internal/Common/QmitkDataSelectionWidgetControls.ui src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesViewControls.ui src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidgetControls.ui src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui ) set(MOC_H_FILES src/QmitkSegmentationPreferencePage.h src/internal/mitkPluginActivator.h src/internal/QmitkSegmentationView.h src/internal/QmitkThresholdAction.h src/internal/QmitkCreatePolygonModelAction.h #src/internal/QmitkStatisticsAction.h src/internal/QmitkAutocropAction.h + src/internal/QmitkAutocropLabelSetImageAction.h src/internal/QmitkDeformableClippingPlaneView.h src/internal/Common/QmitkDataSelectionWidget.h src/internal/SegmentationUtilities/QmitkSegmentationUtilitiesView.h src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h src/internal/SegmentationUtilities/ContourModelToImage/QmitkContourModelToImageWidget.h src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h ) set(CACHED_RESOURCE_FILES resources/segmentation.svg resources/deformablePlane.png resources/clipping_plane_translate_48x48.png resources/clipping_plane_rotate48x48.png resources/clipping_plane_deform48x48.png resources/segmentation_utilities.svg plugin.xml ) set(QRC_FILES resources/segmentation.qrc resources/SegmentationUtilities.qrc resources/BooleanOperationsWidget.qrc resources/MorphologicalOperationsWidget.qrc ) set(CPP_FILES) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.segmentation/plugin.xml b/Plugins/org.mitk.gui.qt.segmentation/plugin.xml index 56282d66a3..24f382cdeb 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/plugin.xml +++ b/Plugins/org.mitk.gui.qt.segmentation/plugin.xml @@ -1,94 +1,94 @@ Allows the segmentation of images using different tools. Allow the clipping of a volume using a deformable plane. Edit segmentations using standard operations. - + diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp new file mode 100644 index 0000000000..1861721b75 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.cpp @@ -0,0 +1,300 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include "QmitkAutocropLabelSetImageAction.h" + +#include +#include +#include +#include + +namespace +{ + // Iterate over all layers, time steps, and dimensions of a LabelSetImage to + // determine the overall minimum and maximum indices of labeled pixels. + // + // Returns false if the input image is empty, minIndex and maxIndex contain + // valid indices otherwise. + // + // Throws an mitk::Exception if read access was denied. + // + bool DetermineMinimumAndMaximumIndicesOfNonBackgroundPixels(mitk::LabelSetImage::Pointer labelSetImage, itk::Index<3>& minIndex, itk::Index<3>& maxIndex) + { + // We need a time selector to handle 3d+t images. It is not used for 3d images, though. + auto timeSelector = mitk::ImageTimeSelector::New(); + timeSelector->SetInput(labelSetImage); + + const auto background = labelSetImage->GetExteriorLabel()->GetValue(); + const auto numLayers = labelSetImage->GetNumberOfLayers(); + const auto numTimeSteps = labelSetImage->GetTimeSteps(); + + const itk::Index<3> dim = { + labelSetImage->GetDimension(0), + labelSetImage->GetDimension(1), + labelSetImage->GetDimension(2) + }; + + maxIndex = { 0, 0, 0 }; + minIndex = dim; + itk::Index<3> index; + + bool labelSetImageIsEmpty = true; + + for (std::remove_const_t layer = 0; layer < numLayers; ++layer) + { + labelSetImage->SetActiveLayer(layer); + + for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) + { + const mitk::Image* image = nullptr; + + if (numTimeSteps > 1) + { + timeSelector->SetTimeNr(timeStep); + timeSelector->Update(); + image = timeSelector->GetOutput(); + } + else + { + image = labelSetImage; + } + + mitk::ImagePixelReadAccessor pixelReader(image); + bool imageIsEmpty = true; + + for (index[2] = 0; index[2] < dim[2]; ++index[2]) + { + for (index[1] = 0; index[1] < dim[1]; ++index[1]) + { + for (index[0] = 0; index[0] < dim[0]; ++index[0]) + { + if (background != pixelReader.GetPixelByIndex(index)) + { + imageIsEmpty = false; + minIndex = { + std::min(minIndex[0], index[0]), + std::min(minIndex[1], index[1]), + std::min(minIndex[2], index[2]) + }; + break; + } + } + } + } + + if (imageIsEmpty) + continue; + + maxIndex = { + std::max(maxIndex[0], minIndex[0]), + std::max(maxIndex[1], minIndex[1]), + std::max(maxIndex[2], minIndex[2]) + }; + + for (index[2] = dim[2] - 1; index[2] >= 0; --index[2]) + { + for (index[1] = dim[1] - 1; index[1] >= 0; --index[1]) + { + for (index[0] = dim[0] - 1; index[0] >= 0; --index[0]) + { + if (background != pixelReader.GetPixelByIndex(index)) + { + maxIndex = { + std::max(maxIndex[0], index[0]), + std::max(maxIndex[1], index[1]), + std::max(maxIndex[2], index[2]) + }; + break; + } + } + } + } + + if (!imageIsEmpty) + labelSetImageIsEmpty = false; + } + } + + return !labelSetImageIsEmpty; + } + + // Crop a LabelSetImage. Labels in the cropped LabelSetImage will still have + // their original properties like names and colors. + // + // Returns a cropped LabelSetImage. + // + // Throws an mitk::Exception if read access was denied. + // + mitk::LabelSetImage::Pointer Crop(mitk::LabelSetImage::Pointer labelSetImage, const itk::Index<3>& minIndex, const itk::Index<3>& maxIndex) + { + // We need a time selector to handle 3d+t images. It is not used for 3d images, though. + auto timeSelector = mitk::ImageTimeSelector::New(); + timeSelector->SetInput(labelSetImage); + + const auto numLayers = labelSetImage->GetNumberOfLayers(); + const auto numTimeSteps = labelSetImage->GetTimeSteps(); + + const itk::Index<3> croppedDim = { + 1 + maxIndex[0] - minIndex[0], + 1 + maxIndex[1] - minIndex[1], + 1 + maxIndex[2] - minIndex[2] + }; + + const auto numPixels = croppedDim[0] * croppedDim[1] * croppedDim[2]; + + mitk::BaseGeometry::BoundsArrayType croppedBounds; + croppedBounds[0] = 0; + croppedBounds[1] = croppedDim[0]; + croppedBounds[2] = 0; + croppedBounds[3] = croppedDim[1]; + croppedBounds[4] = 0; + croppedBounds[5] = croppedDim[2]; + + // Clone and adapt the original TimeGeometry to the cropped region + + auto croppedTimeGeometry = labelSetImage->GetTimeGeometry()->Clone(); + + for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) + { + auto geometry = croppedTimeGeometry->GetGeometryForTimeStep(timeStep); + + mitk::Point3D croppedOrigin; + geometry->IndexToWorld(minIndex, croppedOrigin); + geometry->SetOrigin(croppedOrigin); + + geometry->SetBounds(croppedBounds); + } + + auto croppedLabelSetImage = mitk::LabelSetImage::New(); + croppedLabelSetImage->Initialize(mitk::MakeScalarPixelType(), *croppedTimeGeometry); + + // Create cropped image volumes for all time steps in all layers + + for (std::remove_const_t layer = 0; layer < numLayers; ++layer) + { + labelSetImage->SetActiveLayer(layer); + croppedLabelSetImage->AddLayer(); + + for (std::remove_const_t timeStep = 0; timeStep < numTimeSteps; ++timeStep) + { + const mitk::Image* image = nullptr; + + if (numTimeSteps > 1) + { + timeSelector->SetTimeNr(timeStep); + timeSelector->Update(); + image = timeSelector->GetOutput(); + } + else + { + image = labelSetImage; + } + + mitk::ImagePixelReadAccessor pixelReader(image); + auto* croppedVolume = new mitk::LabelSetImage::PixelType[numPixels]; + itk::Index<3> croppedIndex; + itk::Index<3> index; + + for (croppedIndex[2] = 0; croppedIndex[2] < croppedDim[2]; ++croppedIndex[2]) + { + for (croppedIndex[1] = 0; croppedIndex[1] < croppedDim[1]; ++croppedIndex[1]) + { + for (croppedIndex[0] = 0; croppedIndex[0] < croppedDim[0]; ++croppedIndex[0]) + { + index[0] = croppedIndex[0] + minIndex[0]; + index[1] = croppedIndex[1] + minIndex[1]; + index[2] = croppedIndex[2] + minIndex[2]; + const auto& pixel = pixelReader.GetPixelByIndex(index); + + croppedVolume[croppedIndex[2] * croppedDim[1] * croppedDim[0] + croppedIndex[1] * croppedDim[0] + croppedIndex[0]] = pixel; + } + } + } + + croppedLabelSetImage->SetVolume(croppedVolume, timeStep); + croppedLabelSetImage->AddLabelSetToLayer(layer, labelSetImage->GetLabelSet(layer)); + } + } + + return croppedLabelSetImage; + } +} + +QmitkAutocropLabelSetImageAction::QmitkAutocropLabelSetImageAction() +{ +} + +QmitkAutocropLabelSetImageAction::~QmitkAutocropLabelSetImageAction() +{ +} + +void QmitkAutocropLabelSetImageAction::Run(const QList& selectedNodes) +{ + for (const auto& dataNode : selectedNodes) + { + mitk::LabelSetImage::Pointer labelSetImage = dynamic_cast(dataNode->GetData()); + + if (labelSetImage.IsNull()) + continue; + + // Backup currently active layer as we need to restore it later + auto activeLayer = labelSetImage->GetActiveLayer(); + + mitk::LabelSetImage::Pointer croppedLabelSetImage; + itk::Index<3> minIndex; + itk::Index<3> maxIndex; + + try + { + if (!DetermineMinimumAndMaximumIndicesOfNonBackgroundPixels(labelSetImage, minIndex, maxIndex)) + { + MITK_WARN << "Autocrop was skipped: Image \"" << dataNode->GetName() << "\" is empty."; + labelSetImage->SetActiveLayer(activeLayer); // Restore the originally active layer + return; + } + + croppedLabelSetImage = Crop(labelSetImage, minIndex, maxIndex); + } + catch (const mitk::Exception&) + { + MITK_ERROR << "Autocrop was aborted: Image read access to \"" << dataNode->GetName() << "\" was denied."; + labelSetImage->SetActiveLayer(activeLayer); // Restore the originally active layer + return; + } + + // Restore the originally active layer in the cropped LabelSetImage + croppedLabelSetImage->SetActiveLayer(activeLayer); + + // Override the original LabelSetImage with the cropped LabelSetImage + dataNode->SetData(croppedLabelSetImage); + + // If we cropped a single LabelSetImage, reinit the views to give a visible feedback to the user + if (1 == selectedNodes.size()) + mitk::RenderingManager::GetInstance()->InitializeViews(croppedLabelSetImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); + } +} + +void QmitkAutocropLabelSetImageAction::SetSmoothed(bool) +{ +} + +void QmitkAutocropLabelSetImageAction::SetDecimated(bool) +{ +} + +void QmitkAutocropLabelSetImageAction::SetDataStorage(mitk::DataStorage*) +{ +} + +void QmitkAutocropLabelSetImageAction::SetFunctionality(berry::QtViewPart*) +{ +} diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h new file mode 100644 index 0000000000..e882b2903a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/QmitkAutocropLabelSetImageAction.h @@ -0,0 +1,35 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef QmitkAutocropLabelSetImageAction_h +#define QmitkAutocropLabelSetImageAction_h + +#include +#include + +class MITK_QT_SEGMENTATION QmitkAutocropLabelSetImageAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + QmitkAutocropLabelSetImageAction(); + ~QmitkAutocropLabelSetImageAction() override; + + void Run(const QList& selectedNodes) override; + void SetDataStorage(mitk::DataStorage* dataStorage) override; + void SetSmoothed(bool smoothed) override; + void SetDecimated(bool decimated) override; + void SetFunctionality(berry::QtViewPart* view) override; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp index c21a7055b0..173eff2449 100644 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.segmentation/src/internal/mitkPluginActivator.cpp @@ -1,63 +1,65 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkPluginActivator.h" #include "QmitkSegmentationView.h" #include "QmitkThresholdAction.h" #include "QmitkCreatePolygonModelAction.h" #include "QmitkAutocropAction.h" +#include "QmitkAutocropLabelSetImageAction.h" #include "QmitkSegmentationPreferencePage.h" #include "QmitkDeformableClippingPlaneView.h" #include "SegmentationUtilities/QmitkSegmentationUtilitiesView.h" using namespace mitk; ctkPluginContext* PluginActivator::m_context = nullptr; PluginActivator* PluginActivator::m_Instance = nullptr; PluginActivator::PluginActivator() { m_Instance = this; } PluginActivator::~PluginActivator() { m_Instance = nullptr; } void PluginActivator::start(ctkPluginContext *context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkAutocropLabelSetImageAction, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationPreferencePage, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkDeformableClippingPlaneView, context) BERRY_REGISTER_EXTENSION_CLASS(QmitkSegmentationUtilitiesView, context) this->m_context = context; } void PluginActivator::stop(ctkPluginContext *) { this->m_context = nullptr; } PluginActivator* PluginActivator::getDefault() { return m_Instance; } ctkPluginContext*PluginActivator::getContext() { return m_context; } diff --git a/Plugins/org.mitk.gui.qt.segmentation/src/internal/segmentation.h b/Plugins/org.mitk.gui.qt.segmentation/src/internal/segmentation.h deleted file mode 100644 index a0716fdc50..0000000000 --- a/Plugins/org.mitk.gui.qt.segmentation/src/internal/segmentation.h +++ /dev/null @@ -1,96 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef _QEMBED_1804289383 -#define _QEMBED_1804289383 -#include -#include -static const QRgb segmentation_data[] = { - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000, - 0x3000000,0x3000000,0x3000000,0x2000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x1000000,0x36000000,0x84000000,0xa3000000,0xff000000,0xff000000,0xff000000,0xb4000000,0x93000000,0x54000000,0x1a000000, - 0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xa000000,0x9b000000,0xee4b4b4a,0xffb4b2b1,0xffdfdedd, - 0xffe4e3e0,0xffe3e1dd,0xffc2beb5,0xffc1bdb4,0xffbab5ab,0xffd1cdc7,0xff919191,0xbc292929,0x69000000,0x11000000,0x1000000,0x0,0x0,0x0, - 0x0,0x1000000,0x29000000,0xff414140,0xffd9d9d7,0xfff0efef,0xffc8c7c5,0xff6d6b6a,0xff494947,0xff2b2b2b,0xff161616,0xff262522,0xff3e3d39,0xff56534e, - 0xff87837d,0xffd0ceca,0xff6f6e6d,0x71000000,0x9000000,0x1000000,0x0,0x0,0x3000000,0x18000000,0xff474544,0xffe3e2e1,0xffb9b9b8,0xe8242424, - 0xbb0a0a0a,0x76000000,0x60000000,0x50000000,0x49000000,0x6b000000,0x51000000,0x79000000,0xca000000,0xff343230,0xffb7b4ad,0xbe000000,0x1b000000,0x6000000, - 0x0,0x0,0xd000000,0xff494947,0xffd1d1d0,0xff656564,0x9a000000,0x55000000,0x36000000,0x29000000,0x20000000,0x1c000000,0x1c000000,0x1c000000, - 0x1c000000,0x1c000000,0x67000000,0xeb333333,0xffc1bfbc,0xff000000,0x2f000000,0xe000000,0x0,0x0,0xb4000000,0xffd5d5d2,0xff747371,0x7f000000, - 0x42000000,0x26000000,0x14000000,0xb000000,0x6000000,0x4000000,0x4000000,0x4000000,0x29000000,0x8b131313,0xdb6a6a6a,0xffd7d6d4,0xff969692,0xcb000000, - 0x39000000,0x14000000,0x0,0x2000000,0xff000000,0xffd8d6d2,0xff000000,0x4e000000,0x2b000000,0xe000000,0x4000000,0x1000000,0x0,0x1000000, - 0x5e000000,0xbe3d3d3d,0xe26c6c6c,0xf8d6d6d4,0xffe0dfde,0xff787774,0xff22211f,0x66000000,0x2f000000,0xe000000,0x0,0x2000000,0x91000000,0xff8b8881, - 0xff262422,0xe8201f1e,0xac000000,0x12000000,0x8000000,0x59000000,0xa2202020,0xdf727272,0xffa3a3a2,0xffe4e2df,0xffe7e5e3,0xff71706c,0xff262624,0xff000000, - 0x61000000,0x3e000000,0x1b000000,0x6000000,0x0,0x2000000,0x3b000000,0xff000000,0xffd7d7d3,0xffe2e0dc,0xffe2dfdc,0xff0b0b0b,0xff484846,0xff939291, - 0xffc4c1be,0xffd6d4ce,0xffa7a49e,0xff383735,0xf0090908,0xcc000000,0x53000000,0x48000000,0x3c000000,0x21000000,0xa000000,0x1000000,0x0,0x1000000, - 0xe5000000,0xffe0dedd,0xffcfcbc4,0xff63605c,0xffb8b5b0,0xffb2b1ad,0xff5c5b57,0xff837f79,0xff3c3a36,0xea000000,0xde000000,0x54000000,0x46000000,0x3c000000, - 0x2f000000,0x22000000,0x16000000,0x9000000,0x2000000,0x0,0x0,0x2000000,0xb7000000,0xffd0cdc6,0xff999692,0xff66645d,0xff151515,0xffa6a5a1, - 0xff000000,0xd8000000,0x60000000,0x46000000,0x3a000000,0x2f000000,0x21000000,0x16000000,0xe000000,0x7000000,0x3000000,0x1000000,0x0,0x0, - 0x0,0x2000000,0xf000000,0xff363636,0xff817f7b,0xff393633,0xff8c8884,0xff0b0b0b,0x7a000000,0x4a000000,0x34000000,0x21000000,0x16000000,0xe000000, - 0x7000000,0x3000000,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7000000,0x1d000000,0xc2000000,0xff000000, - 0xffafaca6,0xd8000000,0x4c000000,0x2a000000,0x12000000,0x7000000,0x3000000,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x2000000,0xa000000,0x1f000000,0xdc6c6965,0xffdbdad5,0xd5000000,0x3c000000,0x17000000,0x4000000,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x2000000, - 0xd40c0c0c,0xffdad7d2,0xf4212121,0x9b000000,0x2e000000,0xe000000,0x2000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0xc000000,0xd0000000,0x71000000,0x37000000,0x1a000000,0x6000000, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x6000000,0x17000000,0x24000000,0x1a000000,0x9000000,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x6000000,0xa000000,0x6000000, - 0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x1000000,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 -}; - -/* Generated by qembed */ -static struct EmbedImage { - int width, height, depth; - const unsigned char *data; - int numColors; - const QRgb *colorTable; - bool alpha; - const char *name; -} embed_image_vec[] = { - { 22, 22, 32, (const unsigned char*)segmentation_data, 0, 0, TRUE, "segmentation" }, - { 0, 0, 0, 0, 0, 0, 0, 0 } -}; - -static const QImage& qembed_findImage( const QString& name ) -{ - static QDict dict; - QImage* img = dict.find( name ); - if ( !img ) { - for ( int i = 0; embed_image_vec[i].data; i++ ) { - if ( strcmp(embed_image_vec[i].name, name.latin1()) == 0 ) { - img = new QImage((uchar*)embed_image_vec[i].data, - embed_image_vec[i].width, - embed_image_vec[i].height, - embed_image_vec[i].depth, - (QRgb*)embed_image_vec[i].colorTable, - embed_image_vec[i].numColors, - QImage::BigEndian ); - if ( embed_image_vec[i].alpha ) - img->setAlphaBuffer( TRUE ); - dict.insert( name, img ); - break; - } - } - if ( !img ) { - static QImage dummy; - return dummy; - } - } - return *img; -} - -#endif