diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index b4ff345857..6c452fede7 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,51 +1,52 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF + org.mitk.gui.qt.multilabelsegmentation:ON ) diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/CMakeLists.txt b/Plugins/org.mitk.gui.qt.multilabelsegmentation/CMakeLists.txt new file mode 100644 index 0000000000..2f2d9179b6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/CMakeLists.txt @@ -0,0 +1,9 @@ +project(org_mitk_gui_qt_multilabelsegmentation) + +include_directories(${CTK_INCLUDE_DIRS}) + +MACRO_CREATE_MITK_CTK_PLUGIN( + EXPORT_DIRECTIVE MITK_QT_SEGMENTATION + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkSegmentation MitkSegmentationUI +) diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/QmitkSegmentationTechnical.dox b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/QmitkSegmentationTechnical.dox new file mode 100644 index 0000000000..b8992e8a55 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/QmitkSegmentationTechnical.dox @@ -0,0 +1,101 @@ +/** + +\page QmitkSegmentationTechnicalPage Technical design of QmitkSegmentation + +\li \ref QmitkSegmentationTechnicalPage2 +\li \ref QmitkSegmentationTechnicalPage3 +\li \ref QmitkSegmentationTechnicalPage4 + +\section QmitkSegmentationTechnicalPage2 Introduction + +QmitkSegmentation was designed for the liver resection planning +project "ReLiver". +The goal was a stable, well-documented, extensible, and testable +re-implementation of a functionality called "ERIS", which was used for manual +segmentation in 2D slices of 3D or 3D+t images. +Re-implementation was chosen because it seemed to be easier to write +documentation and tests for newly developed code. In addition, the old code had +some design weaknesses (e.g. a monolithic class), which would be hard to +maintain in the future. + +By now Segmentation is a well tested and easily extensible vehicle for all kinds of interactive +segmentation applications. A separate page describes how you can extend Segmentation with new +tools in a shared object (DLL): \ref toolextensions. + +\section QmitkSegmentationTechnicalPage3 Overview of tasks + +We identified the following major tasks: + +
    +
  1. Management of images: what is the original patient image, what +images are the active segmentations? +
  2. Management of drawing tools: there is a set of drawing tools, one at +a time is active, that is, someone has to decide which tool will receive mouse +(and other) events. +
  3. Drawing tools: each tool can modify a segmentation in reaction to +user interaction. To do so, the tools have to know about the relevant images. +
  4. Slice manipulation: drawing tools need to have means to extract a +single slice from an image volume and to write a single slice back into an image +volume. +
  5. Interpolation of unsegmented slices: some class has to keep track of +all the segmentations in a volume and generate suggestions for missing slices. +This should be possible in all three orthogonal slice direction. +
  6. Undo: Slice manipulations should be undoable, no matter whether a +tool or the interpolation mechanism changed something. +
  7. GUI: Integration of everything. +
+ + +\section QmitkSegmentationTechnicalPage4 Classes involved + +The above blocks correspond to a number of classes. Here is an overview of all +related classes with their responsibilities and relations: + +\imageMacro{"interactive_segmentation_classes.png","html",12} + +
    +
  1. Management of images: mitk::ToolManager has a set of reference +data (original images) and a second set of working data (segmentations). +mitk::Tool objects know a ToolManager and can ask the manager for the currently +relevant images. There are two GUI elements that enable +the user to modify the set of reference and working images (QmitkToolReferenceDataSelectionBox and QmitkToolWorkingDataSelectionBox). GUI and non-GUI +classes are coupled by itk::Events (non-GUI to GUI) and direct method calls (GUI +to non-GUI). +
  2. Management of drawing tools: As a second task, ToolManager manages all available tools and makes sure that one at a time is able to receive MITK events. +The GUI for selecting tools is implemented in QmitkToolSelectionBox. +
  3. Drawing tools: Drawing tools all inherit from mitk::Tool, which is a +mitk::StateMachine. There is a number of derivations from Tool, each offering +some helper methods for specific sub-classes, like manipulation of 2D slices. +Tools are instantiated through the itk::ObjectFactory, which means that there is +also one factory for each tool (e.g. mitk::AddContourToolFactory). For the GUI representation, each tool has an +identification, consisting of a name and an icon (XPM). The actual drawing +methods are mainly implemented in mitk::SegTool2D (helper methods) and its +sub-classes for region growing, freehand drawing, etc. +
  4. Slice manipulation: There are two filters for manipulation of slices +inside a 3D image volume. mitk::ExtractImageFilter retrieves a single 2D slice +from a 3D volume. mitk::OverwriteSliceImageFilter replaces a slice inside a 3D +volume with a second slice which is a parameter to the filter. These classes are +used extensively by most of the tools to fulfill their task. +mitk::OverwriteSliceImageFilter cooperates with the interpolation classes to +inform them of single slice modifications. +
  5. Interpolation of unsegmented slices: There are two classes involved +in interpolation: mitk::SegmentationInterpolationController knows a mitk::Image (the +segmentation) and scans its contents for slices with non-zero pixels. It keeps +track of changes in the image and is always able to tell, which neighbors of a +slice (in the three orthogonal slice directions) contain segmentations. The +class also performs this interpolation for single slices on demand. +Again, we have a second class responsible for the GUI: +QmitkSlicesInterpolator enables/disables interpolation and offers to +accept interpolations for one or all slices. +
  6. Undo: Undo functionality is implemented in mitk::OverwriteSliceImageFilter, +since this is the central place where all image modifications are made. The filter stores a binary difference image +to the undo stack as a mitk::ApplyDiffImageOperation. When the user requests undo, this ApplyDiffImageOperation +will be executed by a singleton class DiffImageApplier. The operation itself observes the image, which it refers to, +for itk::DeleteEvent, so no undo operation will be executed on/for images that have already been destroyed. +
  7. GUI: The top-level GUI is the functionality +QmitkSegmentation, which is very thin in comparison to ERIS. There are +separate widgets for image and tool selection, for interpolation. Additionaly, +there are some methods to create, delete, crop, load and save segmentations. +
+ +**/ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/ToolExtensionsGeneralOverview.dox b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/ToolExtensionsGeneralOverview.dox new file mode 100644 index 0000000000..6df1762137 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/ToolExtensionsGeneralOverview.dox @@ -0,0 +1,181 @@ +/** + +\page toolextensions How to extend the Segmentation view with external tools + + + +\section ToolExtensionsGeneralOverview2 Introduction + +The application for manual segmentation in MITK (Segmentation view) comes +with a tool class framework that is extensible with new tools (description at +\ref QmitkSegmentationTechnicalPage). The usual way +to create new tools (since it is mostly used inside DKFZ) is to just add new +files to the MITK source code tree. However, this requires to be familiar with +the MITK build system and turnaround time during development might be long +(recompiling parts of MITK again and again). + +For external users who just want to use +MITK as a library and application, there is a way to create new segmentation +tools in an MITK external project, which will compile the new tools into a +shared object (DLL). Such shared objects can be loaded via the ITK object factory +and its autoload feature on application startup. This document describes +how to build such external extensions. + +Example files can be found in the MITK source code in the directory +${MITK_SOURCE_DIR}/QApplications/ToolExtensionsExample/. + +\section ToolExtensionsGeneralOverview3 What might be part of an extension + +The extension concept assumes that you want to create one or several new +interactive segmentation tools for Segmentation or another MITK +functionality that uses the tools infrastructure. In the result you +will create a shared object (DLL), which contains several tools and their GUI +counterparts, plus optional code that your extension requires. The following +sections shortly describe each of these parts. + +\subsection ToolExtensionsGeneralOverview31 Tool classes + +A tool is basically any subclass of mitk::Tool. Tools are created at runtime +through the ITK object factory (so they inherit from itk::Object). Tools +should handle the interaction part of a segmentation method, i.e. create +seed points, draw contours, etc., in order to parameterize segmentation algorithms. +Simple algorithms can even be part of a tool. A tools is identified by icon (XPM format), +name (short string) and optionally a group name (e.g. the group name for Segmentation +is "default"). + +There is a naming convention: you should put a tool called \c mitk::ExternalTool into +files called \c mitkExternalTool.h and \c mitkExternalTool.cpp. This is \e required if +you use the convenience macros described below, because there need to be ITK factories, +which names are directly derived from the file names of the tools. For the example of mitk::ExternalTool +there would be a factory called \c mitk::ExternalToolFactory in a file named \c mitkExternalToolFactory.cpp. + +\subsection ToolExtensionsGeneralOverview32 GUI classes for tools + +Tools are non-graphical classes that only implement interactions in renderwindows. However, +some tools will need a means to allow the user to set some parameters -- a graphical user interface, GUI. +In the Qt3 case, tool GUIs inherit from QmitkToolGUI, which is a mixture of QWidget and itk::Object. +Tool GUIs are also created through the ITK object factory. + +Tools inform their GUIs about state changes by messages. Tool GUIs communicate with their associated tools +via direct method calls (they know their tools). See mitk::BinaryThresholdTool for examples. + +Again a naming convention: if the convenience macros for tool extension shared objects are used, +you have to put a tool GUI called \c QmitkExternalToolGUI into a files named \c QmitkExternalToolGUI.cpp +and \c QmitkExternalToolGUI.h. The convenience macro will create a factory called \c QmitkExternalToolGUIFactory +into a file named \c QmitkExternalToolGUIFactory.cpp. + +\subsection ToolExtensionsGeneralOverview33 Additional files + +If you are writing tools MITK externally, these tools might depend on additional files, e.g. +segmentation algorithms. These can also be compiled into a tool extension shared object. + +\section ToolExtensionsGeneralOverview4 Writing a CMake file for a tool extension + +Summing up the last section, an example tool extension could comprise the following files: +\verbatim +mitkExternalTool.h \ +mitkExternalTool.xpm >--- implementing mitk::ExternalTool (header, icon, implementation) +mitkExternalTool.cpp / + +QmitkExternalToolGUI.h ,-- implementing a GUI for mitk::ExternalTool +QmitkExternalToolGUI.cpp / + +externalalgorithm.h \ +externalalgorithm.cpp \ +externalalgorithmsolver.h >-- a couple of files (not related to MITK tools) +externalalgorithmsolver.cpp / +\endverbatim + +This should all be compiled into one shared object. Just like ITK, VTK and MITK we +will use CMake for this purpose (I assume you either know or are willing to learn about +www.cmake.org) +A CMake file for the above example would look like this: + +\code +project( ExternalTool ) + +find_package(ITK) +find_package(MITK) +find_package(Qt3) + +add_definitions(${QT_DEFINITIONS}) + +set( TOOL_QT3GUI_FILES + QmitkExternalToolGUI.cpp + ) + +set( TOOL_FILES + mitkExternalTool.cpp + ) + +set( TOOL_ADDITIONAL_CPPS + externalalgorithm.cpp + externalalgorithmsolver.cpp + ) + +set( TOOL_ADDITIONAL_MOC_H +) + +MITK_GENERATE_TOOLS_LIBRARY(mitkExternalTools) +\endcode + +Basically, you only have to change the definitions of \c TOOL_FILES and, optionally, +\c TOOL_QT3GUI_FILES, \c TOOL_ADDITIONAL_CPPS and \c TOOL_ADDITIONAL_MOC_H. +For all .cpp files in \c TOOL_FILES and \c TOOL_QT3GUI_FILES there will be factories +created assuming the naming conventions described in the sections above. +Files listed in \c TOOL_ADDITIONAL_CPPS will just be compiled. Files listed in +\c TOOL_ADDITIONAL_MOC_H will be run through Qts meta object compiler \c moc -- +this is neccessary for all objects that have the Q_OBJECT macro in their declaration. +\c moc will create new files that will also be compiled into the library. + +\section ToolExtensionsGeneralOverview5 Compiling the extension + +For compiling a tool extension, you will need a compiled version of MITK. We will +assume MITK was compiled into /home/user/mitk/debug. You need to build MITK with +BUILD_SHARED_CORE turned on! + +You build the tool extension just like any other CMake based project: +\li know where your source code is (e.g. /home/user/mitk/tool-extension-src) +\li change into the directory, where you want to compile the shared object (e.g. /home/user/mitk/tool-extension-debug) +\li invoke cmake: ccmake /home/user/mitk/tool-extension-src +\li configure (press c or the "configure" button) +\li set the ITK_DIR variable to the directory, where you compiled ITK +\li set the MITK_DIR variable to the directory, where you compiled MITK: /home/user/mitk/debug +\li configure (press "c" or the "configure" button) +\li generate (press "g" or the "generate" button) + +This should do it and leave you with a or project file or Makefile that you can compile (using make or VisualStudio). + +\section ToolExtensionsGeneralOverview6 Configuring ITK autoload + +If the compile succeeds, you will get a library mitkExternalTools.dll or libmitkExternalTools.so. +This library exports a symbol \c itkLoad which is expected by the ITK object factory. + +On application startup the ITK object factory will search a list of directories from +the environment variable \c ITK_AUTOLOAD_PATH. Set this environment variable to your +binary directory (/home/user/mitk/tool-extension-debug). + +The ITK object factory will load all shared objects that it finds in the specified directories +and will test if they contain a symbol (function pointer) \c itkLoad, which is expected +to return a pointer to a itk::ObjectFactoryBase instance. If such a symbol is found, the +returned factory will be registered with the ITK object factory. + +If you successfully followed all the steps above, MITK will find your mitk::ExternalTool on +application startup, when the ITK object factory is asked to create all known instances of +mitk::Tool. Furthermore, if your mitk::ExternalTool claims to be part of the "default" group, +there will be a new icon in Segmentation, which activates your tool. + +Have fun! (And Windows users: welcome to the world of DLLs) + +**/ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.png new file mode 100644 index 0000000000..9a9a4382f7 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.xcf b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.xcf new file mode 100644 index 0000000000..6e37987eb4 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/interactive_segmentation_classes.xcf differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/multilabelsegmentation.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/multilabelsegmentation.png new file mode 100644 index 0000000000..d13c72b5b6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/multilabelsegmentation.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_multilabelsegmentation.dox b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_multilabelsegmentation.dox new file mode 100644 index 0000000000..590a1d9e9d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_multilabelsegmentation.dox @@ -0,0 +1,395 @@ +/** +\page org_mitk_views_multilabelsegmentation User Manual + +\imageMacro{"multilabelsegmentation.png", "html", 12} + +Some of the features described below are closed source additions to the open source toolkit MITK and are not +available in every application. + +Available sections: + + - \ref org_mitk_gui_qt_segmentationUserManualOverview + - \ref org_mitk_gui_qt_segmentationUserManualTechnical + - \ref org_mitk_gui_qt_segmentationUserManualCreateOpenSaveImportAdd + - \ref org_mitk_gui_qt_segmentationUserManualLabelTable + - \ref org_mitk_gui_qt_segmentationUserManualLabelCreation + - \ref org_mitk_gui_qt_segmentationUserManualLayerCreation + - \ref org_mitk_gui_qt_segmentationUserManualLabelSearch + - \ref org_mitk_gui_qt_segmentationUserManualLabelEditing + - \ref org_mitk_gui_qt_segmentationUserManualContouring + - \ref org_mitk_gui_qt_segmentationUserManualInterpolation + - \ref org_mitk_gui_qt_segmentationUserManualOrganSegmentation + - \ref org_mitk_gui_qt_segmentationUserManualOrganSegmentation1 + - \ref org_mitk_gui_qt_segmentationUserManualOrganSegmentation2 + - \ref org_mitk_gui_qt_segmentationUserManualOrganSegmentation99 + - \ref org_mitk_gui_qt_segmentationUserManualLesionSegmentation + - \ref org_mitk_gui_qt_segmentationUserManualOperationsOnLabels + - \ref org_mitk_gui_qt_segmentationUserManualOperationsOnSingleSelection + - \ref org_mitk_gui_qt_segmentationUserManualOperationsOnMultipleSelection + - \ref org_mitk_gui_qt_segmentationUserManualSegmentationUtilities + - \ref org_mitk_gui_qt_segmentationUserManualTechnicalDetail + +\section org_mitk_gui_qt_segmentationUserManualOverview Overview + +The Segmentation Perspective allows to create segmentations of structures of interest in biomedical and biological +images. Examples of such structures are an organ, a vessel or a lesion in a CT or MR image, or a cell or organelle in microscopy +images. The perspective groups a number of tools which can be used for: + + +\imageMacro{"org_mitk_gui_qt_segmentationIMGapplication.png", "Segmentation perspective consisting of the Data Manager view, the +Segmentation view and the Segmentation Utilities view.", 12} + +If you wonder what segmentations are good for, we shortly revisit the concept of a segmentation here. +A CT or MR image is made up of volume of physical measurements (volume elements are called voxels). +In CT images, for example, the gray value of each voxel corresponds to the mass absorption coefficient +for X-rays in this voxel, which is similar in many %parts of the human body. +The gray value does not contain any further information, so the computer does not know whether a given +voxel is part of the body or the background, nor can it tell a brain from a liver. +However, the distinction between voxels belonging to an object and a background structure is required when: + + +This distinction between voxels inside and object and background is called segmentation. +Since many objects might be segmented on an image, each segmentation is assigned a different label. A label +has a name, a color, and a number of properties that we will describe later. +The current implementation of the Segmentation perspective uses a voxel-based approach for segmentations, i.e. each voxel +of an image must be completely assigned to either a label or background. In a future version of the toolkit we will also enable +the generation of segmentations based on contours. In this way, the user will be able to better define the borders of the +segmented objects by taking advantage of his/her medical knowledge. Segmentations based on contours are not restricted to +the voxel size of the medical image and can be arbitrarily positioned. + +The remainder of this document will summarize the features of the Segmentation perspective and how they are used. + +\subsection org_mitk_gui_qt_segmentationUserManualTechnical Technical Issues + +The Segmentation Perspective makes a number of assumptions. To know what this view can be used for, it will help you to know that: + + +\section org_mitk_gui_qt_segmentationUserManualCreateOpenSaveImportAdd Start Segmenting + +To start using the Segmentation Perspective you will have to either create a new segmentation session or +load an existing one from disk. The Segmentation toolbar collects buttons for the these actions: + +\imageMacro{"org_mitk_gui_qt_segmentationIMGtoolbar.png", "Segmentation toolbar", 12} + + + +\section org_mitk_gui_qt_segmentationUserManualLabelTable The Label Table + +The following label properties are readily available to modify: + + + +The Label Table is shown below: + +\imageMacro{org_mitk_gui_qt_segmentationIMGlabeltable.png", "The Label Table showing all the labels in the current segmentation session", 12} + +\section org_mitk_gui_qt_segmentationUserManualLabelCreation Creating a New Label + +Click the "New Label" button to add a new label. A dialog will show-up to enter the name and color. Preset organ names and +corresponding colors are offered while you type in, but you can set any name. The new name if not known will be automatically +remembered and made available the next time you create a new label. In the current implementation of the plugin, +the maximum number of labels is restricted to 255. If you need more, you will have to create a new segmentation session. + +\section org_mitk_gui_qt_segmentationUserManualLayerCreation Creating a New Layer + +A layer is a set of labels that occupy a non-overlapping anatomical space. The best way to describe them is by a real use +case. Imagine you are working on a radiotherpay planning application. In the first layer of your segmentation +session you would like to trace the contours of the liver and neighboring organs. You can accomodate all these segmentations +in separate labels because they all occupy different anamical regions and do not overlap. Now say you would like to segment +the arteries and veins inside the liver. If you don´t trace them in a different layer, you will overwrite the previous ones. +You may also need a third layer for segmenting the different irrigation territories in the liver and a fourth layer to contain +the lession you would like to treat. + +The next figure illustrates the Layer Manager . The buttons in it contained serve for adding a new layer, selecting the +previous and the next one. The active layer is shown together with the buttons. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGlayerManager.png", "Correction Tool",12} + +\section org_mitk_gui_qt_segmentationUserManualLabelSearch Searching a Label + +It may happen that many labels (e.g. > 200) are present in a segmentation session and therefore manual searching is time consuming. +The Label Search edit box allows for quickly finding the label you want. Just start writing its name and and you will get +assitance for completing its name. If the label you were searching is found, press enter and it will became the active one. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGsearchlabel.png", "Label search", 12} + +\section org_mitk_gui_qt_segmentationUserManualLabelEditing Label Editing + +First of all, you have to select the active label by clicking on the corresponding row in the Label Table. Only one label +can be active at the time. Then you can select an editing tool in the toolbox. +The selected editing tool will be active and its corresponding button will stay pressed until you click the same button again. +Selecting a different tool also deactivates the previous one. If you are familiar with the MITK Workbench, you know that +clicking and moving the mouse in any of the 2D windows will move around the crosshair that defines the position in +the image you are standing on. Depending on the tool that you activate, this behavior may be disabled during segmenting +-- otherwise you might have a hard time concentrating on the contour you are drawing --. + +If you have to delineate a lot of images, you should try using shortcuts to switch tools. Just hit the first letter of each +tool to activate it (e.g. "A" for Add, "S" for Subtract, etc.). If you hover the cursor on a tool button you will get a tip +message reminding you this. + +\subsection org_mitk_gui_qt_segmentationUserManualManualEditingTools Manual Editing Tools + +All of the editing tools work by the same principle: you use the mouse (left button) to click anywhere in a 2D +window (any of the orientations axial, sagittal, or frontal), move the mouse while holding the mouse button and +release to finish the editing action. + +At any time you can undo or redo your past actions with corresponding buttons in the application\'s toolbar. + +\subsection org_mitk_gui_qt_segmentationUserManualContouring Manual Contouring + +The "Add" and "Subtract" tools allow for freely tracing a contour around an organ or structure in an image. +You might also use manual contouring to further enhance or correct a segmentation resulting from sub-optimal automatic methods. +The drawback of manual contouring is that you might need to define contours on many 2D slices to segment the whole structure. +However, this is moderated by the interpolation tools, which are described later. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGiconAddSubtract.png", "Add and Subtract Tools",12} + +Use the left mouse button to draw a closed contour. When releasing the mouse button, the contour will be added (Add tool) to or +removed from (Subtract tool) the current segmentation. +Hold down the CTRL / CMD key to invert the operation (this will switch tools temporarily to allow for quick corrections). + +\imageMacro{"org_mitk_gui_qt_segmentationIMGiconPaintWipe.png", "Paint and Wipe Tools", 12cm} + +Use the slider below the toolbox to change the radius of the paintbrush tool. Move the mouse +in any 2D window and press the left button to draw or erase the active label. +As the Add/Subtract tools, holding CTRL/CMD while drawing will invert the current tool's behavior. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGiconRegionGrowing.png", "Region Growing Tool", 12} + +Click with the left button at one point in a 2D window and move up or down while keeping it pressed. This action +will make your segmentation grow (up) or shrink (down). When working on an image with a high range of grey values, +the selection range can be influenced more strongly by moving the cursor at higher velocity. The region growing algorithm +tool selects all pixels around the mouse cursor that have a similar gray value as the pixel below the first clicked position. +This enables you to quickly create segmentations of structures that have a good contrast to surrounding tissue, e.g. the lungs. + +A common issue with region growing is the so called "leakage" which happens when the structure of interest is connected to +other pixels, of similar gray values, through a narrow "bridge" at the border of the structure. +The Region Growing tool comes with a "leakage detection/removal" feature. If leakage happens, you can left-click into the +leakage region and the tool will try to automatically remove this region (see illustration below). + +\imageMacro{"org_mitk_gui_qt_segmentationIMGleakage.png", "Leakage correction feature of the Region Growing tool", 12} +
+\imageMacro{"org_mitk_gui_qt_segmentationIMGiconCorrection.png", "Correction Tool", 12} + +The corrector tool is used to perform small corrective changes. The following figure illustrates its use: + + +\imageMacro{"org_mitk_gui_qt_segmentationIMGcorrectionActions.png", "Actions of the Correction tool illustrated.", 12} +
+\imageMacro{"org_mitk_gui_qt_segmentationIMGiconFillErase.png", "Fill and Erase Tools", 12} + +The Fill Tool works by filling a hole surrounded by the active label, at the clicked position. If you click outside the +hole (but yet inside the label) all holes found surrounded by the active label will be filled. + +The Erase Tool removes a connected region of the active label around the clicked position. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGiconLiveWire.png", "LiveWire Tool", 12} + +The LiveWire tool acts as a magnetic lasso with a contour snapping to edges of objects. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGLiveWireUsage.png", "Steps for using LiveWire Tool", 12} + + + +The contour will be transferred to the active label when the tool is deactivated. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGiconFastMarching2D.png", "FastMarching Tool", 12} + +The FastMarching tool ... + +\subsection org_mitk_gui_qt_segmentationUserManualInterpolation Interpolation + +Segmenting modern CT and MR volumes is very time-consuming, because structures of interest can easily +cover a range of 50 or more slices. The Segmentation plugin offers two helpful features for these cases: + + +
+ +The 3D interpolation is activated by default when using the manual segmentation tools. That means if you start +contouring, from the second contour onwards, the surface of the segmented area will be interpolated based on the available contours. +The interpolation works with all available manual tools. Please note that this is currently a pure geometrical interpolation, +i.e. image intensity information is not taken into account. With each new contour that the user traces, the interpolation result +will improve, but the more contours you provide the longer the recalculation will take. To optimize the interpolation result you +should try to provide sparse contours in arbitrary oriented planes. Generating parallel contours along a given direction is not +a good approach. During interpolation recalculation, the generated surface blinks in yellow/white. When the interpolation +has finished the surface is shown yellow with a small opacity. Additional to the surface, black contours are shown in the 3D render +window. They mark the positions of all the drawn contours which were used for the interpolation. You can navigate between the drawn +contours by clicking on the „Position“ - Nodes in the Data Manager which are located below the active segmentation. If you don't +want to see these nodes just unckeck the „Show Position Nodes“ Checkbox and these nodes will +be hidden. If you want to delete a drawn contour we recommend to use the Erase-Tool since Redo/Undo is not yet working for 3D +interpolation. + +\imageMacro{"org_mitk_gui_qt_segmentation3DInterpolationWrongRight.png", "3D Interpolation HowTo", 12} + +Finally, you can accept the interpolation result by clicking the "Accept" - button below the toolbox. The region inside the surface is +assigned to the active label. + +
+The 2D Interpolation creates suggestions for extending the active label into neighboring slices provided + + +Interpolated suggestions are displayed as contours with the same color as the active label. To accept an interpolation suggestion +in a single slice, click the "Accept" button. You can also accept all interpolated suggestions at once in a +given window, by pressing the "Accept All" button. + +\imageMacro{"org_mitk_gui_qt_segmentation2DInterpolation.png", "2D Interpolation", 12} + +\section org_mitk_gui_qt_segmentationUserManualOrganSegmentation Organ Segmentation + +\note This feature is only available in our 3M3 Demo Application (http://www.mint-medical.de/productssolutions/mitk3m3/mitk3m3/#downloads) but not in the open source part of MITK + +The manual contouring described above is a fallback option that will work for any kind of images and structures of interest. +However, manual contouring is very time-consuming and tedious. +This is why a major part of image analysis research is working towards automatic segmentation methods. +The Segmentation View comprises a number of easy-to-use tools for segmentation of CT images (Liver) and MR image (left ventricle and wall, left and right lung). + +\subsection org_mitk_gui_qt_segmentationUserManualOrganSegmentation1 Liver on CT Images + +On CT image volumes, preferably with a contrast agent in the portal venous phase, the Liver tool will fully automatically analyze and segment the image. +All you have to do is to load and select the image, then click the "Liver" button. +During the process, which takes a minute or two, you will get visual progress feedback by means of a contour that moves closer and closer to the real liver boundaries. + +\subsection org_mitk_gui_qt_segmentationUserManualOrganSegmentation2 Heart, Lung, and Hippocampus on MRI + +While liver segmentation is performed fully automatic, the following tools for segmentation of the heart, the lungs, and the hippocampus need a minimum amount of guidance. +Click one of the buttons on the "Organ segmentation" page to add an average %model of the respective organ to the image. +This %model can be dragged to the right position by using the left mouse button while holding down the CTRL key. +You can also use CTRL + middle mouse button to rotate or CTRL + right mouse button to scale the %model. + +Before starting the automatic segmentation process by clicking the "Start segmentation" button, try placing the %model closely to the organ in the MR image +(in most cases, you do not need to rotate or scale the %model). +During the segmentation process, a green contour that moves closer and closer to the real liver boundaries will provide you with visual feedback of the segmentation progress. + +The algorithms used for segmentation of the heart and lung are method which need training by a number of example images. +They will not work well with other kind of images, so here is a list of the image types that were used for training: + + +\subsection org_mitk_gui_qt_segmentationUserManualOrganSegmentation99 Other Organs + +As mentioned in the Heart/Lung section, most of the underlying methods are based on "training". +The basic algorithm is versatile and can be applied on all kinds of segmentation problems where the structure of interest is topologically like a sphere (and not like a torus etc.). +If you are interested in other organs than those offered by the current version of the Segmentation view, +please contact our research team. + +\subsection org_mitk_gui_qt_segmentationUserManualLesionSegmentation Lesion Segmentation + +\note This feature is only available in our 3M3 Demo Application (http://www.mint-medical.de/productssolutions/mitk3m3/mitk3m3/#downloads) but not in the open source part of MITK + +Lesion segmentation is a little different from organ segmentation. Since lesions are not part of the healthy body, they sometimes have a diffused border, +and are often found in varying places all over the body. +The tools in this section offer efficient ways to create 3D segmentations of such lesions. + +The Segmentation View currently offers support for enlarged lymph nodes. + +To segment an enlarged lymph node, find a more or less central slice of it, activate the "Lymph Node" tool and draw a rough contour on the inside of the lymph node. +When releasing the mouse button, a segmentation algorithm is started in a background task. The result will become visible after a couple of seconds, but you do not have to wait for it. +If you need to segment several lymph nodes, you can continue to inspect the image right after closing the drawn contour. + +If the lymph node segmentation is not to your content, you can select the "Lymph Node Correction" tool and drag %parts of the lymph node surface towards the right position (works in 3D, not slice-by-slice). +This kind of correction helps in many cases. +If nothing else helps, you can still use the pure manual tools as a fallback. + +\section org_mitk_gui_qt_segmentationUserManualOperationsOnLabels Operations on Labels + +Depending on your selection in the Label Table , several actions are offered: + +\subsection org_mitk_gui_qt_segmentationUserManualOperationsOnSingleSelection Single Label Selection + +If you right click on any label in the table, a menu will pop-up offering the following actions to be performed on the selected label: + + + +\imageMacro{"org_mitk_gui_qt_segmentationIMGLabelTableSingleSelectionContextMenu.png", "Context menu for single label selection", 12} + +\subsection org_mitk_gui_qt_segmentationUserManualOperationsOnMultipleSelection Multiple Label Selection + +If more than one label is selected, a different menu will show up: + +\imageMacro{"org_mitk_gui_qt_segmentationIMGLabelTableMultipleSelectionContextMenu.png", "Context menu for multiple label selection", 12} + + + +\section org_mitk_gui_qt_segmentationUserManualSegmentationUtilities Segmentation Utilities + +The Segmentation Utilities view ... + +One is the surface masking utility. It is used for create a new label from a surface. The surface is used as a "mask": the region inside +the surface is assigned a new label. + +\imageMacro{"org_mitk_gui_qt_segmentationIMGsurfacemask.png", "Surface masking utility", 12} + +Select the image and the surface in the corresponding drop-down boxes (both are selected automatically if there is just one image and one surface) + +\section org_mitk_gui_qt_segmentationUserManualTechnicalDetail Technical Information for Developers + +For technical specifications see : \subpage QmitkSegmentationTechnicalPage and for information on the extensions of the tools system : \subpage toolextensions. + +*/ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation2DInterpolation.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation2DInterpolation.png new file mode 100644 index 0000000000..09ed1e4f17 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation2DInterpolation.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation3DInterpolationWrongRight.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation3DInterpolationWrongRight.png new file mode 100644 index 0000000000..d2e65a8600 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentation3DInterpolationWrongRight.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableMultipleSelectionContextMenu.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableMultipleSelectionContextMenu.png new file mode 100644 index 0000000000..ac71514fe9 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableMultipleSelectionContextMenu.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableSingleSelectionContextMenu.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableSingleSelectionContextMenu.png new file mode 100644 index 0000000000..13f648df2a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLabelTableSingleSelectionContextMenu.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLiveWireUsage.PNG b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLiveWireUsage.PNG new file mode 100644 index 0000000000..3e963ce632 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGLiveWireUsage.PNG differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGapplication.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGapplication.png new file mode 100644 index 0000000000..7d01cb32bc Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGapplication.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGcorrectionActions.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGcorrectionActions.png new file mode 100644 index 0000000000..dc8dc8ce03 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGcorrectionActions.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGdatamanagerview.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGdatamanagerview.png new file mode 100644 index 0000000000..abf6e7f638 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGdatamanagerview.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconAddSubtract.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconAddSubtract.png new file mode 100644 index 0000000000..53927a9ec2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconAddSubtract.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconCorrection.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconCorrection.png new file mode 100644 index 0000000000..41f21628e6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconCorrection.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFastMarching2D.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFastMarching2D.png new file mode 100644 index 0000000000..ac6c4eddc8 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFastMarching2D.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFill.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFill.png new file mode 100644 index 0000000000..33b9498598 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFill.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFillErase.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFillErase.png new file mode 100644 index 0000000000..6acdb3acdc Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconFillErase.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconLiveWire.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconLiveWire.png new file mode 100644 index 0000000000..8c28ce7bf6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconLiveWire.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconPaintWipe.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconPaintWipe.png new file mode 100644 index 0000000000..c034048640 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconPaintWipe.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconRegionGrowing.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconRegionGrowing.png new file mode 100644 index 0000000000..4479918187 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGiconRegionGrowing.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlabeltable.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlabeltable.png new file mode 100644 index 0000000000..351020c950 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlabeltable.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlayerManager.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlayerManager.png new file mode 100644 index 0000000000..8bfd980219 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGlayerManager.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGleakage.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGleakage.png new file mode 100644 index 0000000000..a2e27f3df1 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGleakage.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsearchlabel.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsearchlabel.png new file mode 100644 index 0000000000..5beb87e00e Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsearchlabel.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGselection.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGselection.png new file mode 100644 index 0000000000..25db6192cb Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGselection.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsurfacemask.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsurfacemask.png new file mode 100644 index 0000000000..cb81d900a8 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGsurfacemask.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGtoolbar.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGtoolbar.png new file mode 100644 index 0000000000..ddb08b0449 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/org_mitk_gui_qt_segmentationIMGtoolbar.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/segmentationFromSurfaceBefore.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/segmentationFromSurfaceBefore.png new file mode 100644 index 0000000000..d12d44fb9f Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/UserManual/segmentationFromSurfaceBefore.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/doxygen/MultiLabelSegmentationProperties.dox b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/doxygen/MultiLabelSegmentationProperties.dox new file mode 100644 index 0000000000..e4d8347623 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/documentation/doxygen/MultiLabelSegmentationProperties.dox @@ -0,0 +1,10 @@ +/** +\page MultiLabelSegmentationPropertiesPage The Segmentation properties + +These properties control how a segmentation is rendered: + + +*/ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake b/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake new file mode 100644 index 0000000000..d9c8851988 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/files.cmake @@ -0,0 +1,90 @@ +set(SRC_CPP_FILES + QmitkMultiLabelSegmentationPreferencePage.cpp + QmitkLabelSetWidget.cpp +) + +set(INTERNAL_CPP_FILES + mitkPluginActivator.cpp + QmitkMultiLabelSegmentationView.cpp + QmitkThresholdAction.cpp + QmitkCreatePolygonModelAction.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 +) + +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/QmitkLabelSetWidgetControls.ui +) + +set(MOC_H_FILES + src/QmitkMultiLabelSegmentationPreferencePage.h + src/QmitkLabelSetWidget.h + src/internal/mitkPluginActivator.h + src/internal/QmitkMultiLabelSegmentationView.h + src/internal/QmitkThresholdAction.h + src/internal/QmitkCreatePolygonModelAction.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 +) + +set(CACHED_RESOURCE_FILES + resources/multilabelsegmentation.png + resources/MultiLabelSegmentationUtilities_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/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.multilabelsegmentation/manifest_headers.cmake new file mode 100644 index 0000000000..ca346536b9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "MITK MultiLabelSegmentation") +set(Plugin-Version "1.0.0") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.datamanager) diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/plugin.xml b/Plugins/org.mitk.gui.qt.multilabelsegmentation/plugin.xml new file mode 100644 index 0000000000..312edde71f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/plugin.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanDifference_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanDifference_48x48.png new file mode 100644 index 0000000000..424faa7fe5 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanDifference_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanIntersection_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanIntersection_48x48.png new file mode 100644 index 0000000000..2db4c0dc89 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanIntersection_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperationsWidget.qrc b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperationsWidget.qrc new file mode 100644 index 0000000000..ef0eab4b45 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperationsWidget.qrc @@ -0,0 +1,7 @@ + + + BooleanDifference_48x48.png + BooleanIntersection_48x48.png + BooleanUnion_48x48.png + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperations_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperations_48x48.png new file mode 100644 index 0000000000..27d28f9926 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanOperations_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanUnion_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanUnion_48x48.png new file mode 100644 index 0000000000..891740c7c1 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/BooleanUnion_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/CTKWidgets_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/CTKWidgets_48x48.png new file mode 100644 index 0000000000..ed7caf5cad Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/CTKWidgets_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Closing_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Closing_48x48.png new file mode 100644 index 0000000000..2d998a55cf Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Closing_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Dilate_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Dilate_48x48.png new file mode 100644 index 0000000000..669f95d156 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Dilate_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Erode_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Erode_48x48.png new file mode 100644 index 0000000000..eaa6f4884e Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Erode_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/FillHoles_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/FillHoles_48x48.png new file mode 100644 index 0000000000..30ea751927 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/FillHoles_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Icons.svg b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Icons.svg new file mode 100644 index 0000000000..2fd004fb64 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Icons.svg @@ -0,0 +1,3069 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AND + OR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/ImageMasking_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/ImageMasking_48x48.png new file mode 100644 index 0000000000..9c05e9fb20 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/ImageMasking_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/ConfigSegmentation.xml b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/ConfigSegmentation.xml new file mode 100644 index 0000000000..11d05617e4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/ConfigSegmentation.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/SegmentationInteraction.xml b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/SegmentationInteraction.xml new file mode 100644 index 0000000000..3f55840cd2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Interactions/SegmentationInteraction.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperationsWidget.qrc b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperationsWidget.qrc new file mode 100644 index 0000000000..3fe0afc1f8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperationsWidget.qrc @@ -0,0 +1,9 @@ + + + Dilate_48x48.png + Erode_48x48.png + Closing_48x48.png + Opening_48x48.png + FillHoles_48x48.png + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperations_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperations_48x48.png new file mode 100644 index 0000000000..f19c6714e3 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MorphologicalOperations_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities.qrc b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities.qrc new file mode 100644 index 0000000000..0ba8817c3d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities.qrc @@ -0,0 +1,10 @@ + + + BooleanOperations_48x48.png + ImageMasking_48x48.png + MorphologicalOperations_48x48.png + SurfaceToImage_48x48.png + MultiLabelSegmentationUtilities_48x48.png + CTKWidgets_48x48.png + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities_48x48.png new file mode 100644 index 0000000000..d441187899 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/MultiLabelSegmentationUtilities_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewLabel_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewLabel_48x48.png new file mode 100644 index 0000000000..c98380621e Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewLabel_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewSegmentationSession_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewSegmentationSession_48x48.png new file mode 100644 index 0000000000..6818f12b4a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/NewSegmentationSession_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Opening_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Opening_48x48.png new file mode 100644 index 0000000000..14095dfdd2 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/Opening_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/SurfaceToImage_48x48.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/SurfaceToImage_48x48.png new file mode 100644 index 0000000000..6ad6070caa Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/SurfaceToImage_48x48.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/deformablePlane.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/deformablePlane.png new file mode 100644 index 0000000000..28c5fb54e8 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/deformablePlane.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.png b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.png new file mode 100644 index 0000000000..d13c72b5b6 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.png differ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.qrc b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.qrc new file mode 100644 index 0000000000..5a5003c555 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/resources/multilabelsegmentation.qrc @@ -0,0 +1,7 @@ + + + multilabelsegmentation.png + NewLabel_48x48.png + NewSegmentationSession_48x48.png + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.cpp new file mode 100644 index 0000000000..07f4512cd4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.cpp @@ -0,0 +1,1249 @@ +/*=================================================================== + +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 "QmitkLabelSetWidget.h" + +// mitk +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Qmitk +#include +#include +#include + +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + +// itk +#include + +// todo: +// berry +//#include + +QmitkLabelSetWidget::QmitkLabelSetWidget(QWidget* parent) +: QWidget(parent) +, m_ToolManager(NULL) +, m_DataStorage(NULL) +, m_Completer(NULL) +{ + m_Controls.setupUi(this); + + m_ColorSequenceRainbow.GoToBegin(); + + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + assert(m_ToolManager); + + m_Controls.m_LabelSearchBox->setAlwaysShowClearIcon(true); + m_Controls.m_LabelSearchBox->setShowSearchIcon(true); + + QStringList completionList; + completionList << ""; + m_Completer = new QCompleter(completionList, this); + m_Completer->setCaseSensitivity(Qt::CaseInsensitive); + m_Controls.m_LabelSearchBox->setCompleter(m_Completer); + + connect( m_Controls.m_LabelSearchBox, SIGNAL(returnPressed()), this, SLOT(OnSearchLabel()) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(labelListModified(const QStringList&)), this, SLOT( OnLabelListModified(const QStringList&)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(mergeLabel(int)), this, SLOT( OnMergeLabel(int)) ); + + QStringListModel* completeModel = static_cast (m_Completer->model()); + completeModel->setStringList(GetLabelStringList()); + + m_Controls.m_LabelSearchBox->setEnabled(false); + + + m_Controls.m_lblCaption->setText(""); + + InitializeTableWidget(); + +} + +QmitkLabelSetWidget::~QmitkLabelSetWidget() +{ +} + + +void QmitkLabelSetWidget::OnTableViewContextMenuRequested(const QPoint& pos) +{ + QTableWidgetItem *itemAt = m_Controls.m_LabelSetTableWidget->itemAt(pos); + + //OnItemClicked(itemAt); + + if (!itemAt) return; + int pixelValue = itemAt->data(Qt::UserRole).toInt(); + QMenu* menu = new QMenu(m_Controls.m_LabelSetTableWidget); + + if (m_Controls.m_LabelSetTableWidget->selectedItems().size()>1) + { + QAction* mergeAction = new QAction(QIcon(":/Qmitk/MergeLabels.png"), "Merge selection on current label", this ); + mergeAction->setEnabled(true); + QObject::connect( mergeAction, SIGNAL( triggered(bool) ), this, SLOT( OnMergeLabels(bool) ) ); + menu->addAction(mergeAction); + + QAction* removeLabelsAction = new QAction(QIcon(":/Qmitk/RemoveLabel.png"), "Remove selected labels", this ); + removeLabelsAction->setEnabled(true); + QObject::connect( removeLabelsAction, SIGNAL( triggered(bool) ), this, SLOT( OnRemoveLabels(bool) ) ); + menu->addAction(removeLabelsAction); + + QAction* eraseLabelsAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "Erase selected labels", this ); + eraseLabelsAction->setEnabled(true); + QObject::connect( eraseLabelsAction, SIGNAL( triggered(bool) ), this, SLOT( OnEraseLabels(bool) ) ); + menu->addAction(eraseLabelsAction); + + QAction* combineAndCreateSurfaceAction = new QAction(QIcon(":/Qmitk/CreateSurface.png"), "Combine and create a surface", this ); + combineAndCreateSurfaceAction->setEnabled(true); + QObject::connect( combineAndCreateSurfaceAction, SIGNAL( triggered(bool) ), this, SLOT( OnCombineAndCreateSurface(bool) ) ); + menu->addAction(combineAndCreateSurfaceAction); + + QAction* createMasksAction = new QAction(QIcon(":/Qmitk/CreateMask.png"), "Create a mask for each selected label", this ); + createMasksAction->setEnabled(true); + QObject::connect( createMasksAction, SIGNAL( triggered(bool) ), this, SLOT( OnCreateMasks(bool) ) ); + menu->addAction(createMasksAction); + + QAction* combineAndCreateMaskAction = new QAction(QIcon(":/Qmitk/CreateMask.png"), "Combine and create a mask", this ); + combineAndCreateMaskAction->setEnabled(true); + QObject::connect( combineAndCreateMaskAction, SIGNAL( triggered(bool) ), this, SLOT( OnCombineAndCreateMask(bool) ) ); + menu->addAction(combineAndCreateMaskAction); + } + else + { + QAction* renameAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "Rename...", this ); + renameAction->setEnabled(true); + QObject::connect( renameAction, SIGNAL( triggered(bool) ), this, SLOT( OnRenameLabel(bool) ) ); + menu->addAction(renameAction); + + QAction* removeAction = new QAction(QIcon(":/Qmitk/RemoveLabel.png"), "Remove...", this ); + removeAction->setEnabled(true); + QObject::connect( removeAction, SIGNAL( triggered(bool) ), this, SLOT( OnRemoveLabel(bool) ) ); + menu->addAction(removeAction); + + QAction* eraseAction = new QAction(QIcon(":/Qmitk/EraseLabel.png"), "Erase...", this ); + eraseAction->setEnabled(true); + QObject::connect( eraseAction, SIGNAL( triggered(bool) ), this, SLOT( OnEraseLabel(bool) ) ); + menu->addAction(eraseAction); + + QAction* mergeAction = new QAction(QIcon(":/Qmitk/MergeLabels.png"), "Merge...", this ); + mergeAction->setEnabled(true); + QObject::connect( mergeAction, SIGNAL( triggered(bool) ), this, SLOT( OnMergeLabel(bool) ) ); + menu->addAction(mergeAction); + + QAction* randomColorAction = new QAction(QIcon(":/Qmitk/RandomColor.png"), "Random color", this ); + randomColorAction->setEnabled(true); + QObject::connect( randomColorAction, SIGNAL( triggered(bool) ), this, SLOT( OnRandomColor(bool) ) ); + menu->addAction(randomColorAction); + + QAction* viewOnlyAction = new QAction(QIcon(":/Qmitk/visible.png"), "View only", this ); + viewOnlyAction->setEnabled(true); + QObject::connect( viewOnlyAction, SIGNAL( triggered(bool) ), this, SLOT( OnSetOnlyActiveLabelVisible(bool) ) ); + menu->addAction(viewOnlyAction); + + QAction* viewAllAction = new QAction(QIcon(":/Qmitk/visible.png"), "View all", this ); + viewAllAction->setEnabled(true); + QObject::connect( viewAllAction, SIGNAL( triggered(bool) ), this, SLOT( OnSetAllLabelsVisible(bool) ) ); + menu->addAction(viewAllAction); + + QAction* hideAllAction = new QAction(QIcon(":/Qmitk/invisible.png"), "Hide all", this ); + hideAllAction->setEnabled(true); + QObject::connect( hideAllAction, SIGNAL( triggered(bool) ), this, SLOT( OnSetAllLabelsInvisible(bool) ) ); + menu->addAction(hideAllAction); + + QAction* lockAllAction = new QAction(QIcon(":/Qmitk/lock.png"), "Lock all", this ); + lockAllAction->setEnabled(true); + QObject::connect( lockAllAction, SIGNAL( triggered(bool) ), this, SLOT( OnLockAllLabels(bool) ) ); + menu->addAction(lockAllAction); + + QAction* unlockAllAction = new QAction(QIcon(":/Qmitk/unlock.png"), "Unlock all", this ); + unlockAllAction->setEnabled(true); + QObject::connect( unlockAllAction, SIGNAL( triggered(bool) ), this, SLOT( OnUnlockAllLabels(bool) ) ); + menu->addAction(unlockAllAction); + + QAction* createSurfaceAction = new QAction(QIcon(":/Qmitk/CreateSurface.png"), "Create surface", this ); + createSurfaceAction->setEnabled(true); + createSurfaceAction->setMenu(new QMenu()); + + QAction* tmp1 = createSurfaceAction->menu()->addAction(QString("Detailed")); + QAction* tmp2 = createSurfaceAction->menu()->addAction(QString("Smoothed")); + + QObject::connect( tmp1, SIGNAL( triggered(bool) ), this, SLOT( OnCreateDetailedSurface(bool) ) ); + QObject::connect( tmp2, SIGNAL( triggered(bool) ), this, SLOT( OnCreateSmoothedSurface(bool) ) ); + + menu->addAction(createSurfaceAction); + + QAction* createMaskAction = new QAction(QIcon(":/Qmitk/CreateMask.png"), "Create mask", this ); + createMaskAction->setEnabled(true); + QObject::connect( createMaskAction, SIGNAL( triggered(bool) ), this, SLOT( OnCreateMask(bool) ) ); + + menu->addAction(createMaskAction); + + QAction* createCroppedMaskAction = new QAction(QIcon(":/Qmitk/CreateMask.png"), "Create cropped mask", this ); + createCroppedMaskAction->setEnabled(true); + QObject::connect( createCroppedMaskAction, SIGNAL( triggered(bool) ), this, SLOT( OnCreateCroppedMask(bool) ) ); + +// QAction* importAction = new QAction(QIcon(":/Qmitk/RenameLabel.png"), "Import...", this ); +// importAction->setEnabled(true); +// QObject::connect( importAction, SIGNAL( triggered(bool) ), this, SLOT( OnImportSegmentationSession(bool) ) ); +// menu->addAction(importAction); + + menu->addAction(createCroppedMaskAction); + + QSlider * opacitySlider = new QSlider; + opacitySlider->setMinimum(0); + opacitySlider->setMaximum(100); + opacitySlider->setOrientation(Qt::Horizontal); + QObject::connect( opacitySlider, SIGNAL( valueChanged(int) ), this, SLOT( OnOpacityChanged(int) ) ); + + QLabel* _OpacityLabel = new QLabel("Opacity: "); + QVBoxLayout* _OpacityWidgetLayout = new QVBoxLayout; + _OpacityWidgetLayout->setContentsMargins(4,4,4,4); + _OpacityWidgetLayout->addWidget(_OpacityLabel); + _OpacityWidgetLayout->addWidget(opacitySlider); + QWidget* _OpacityWidget = new QWidget; + _OpacityWidget->setLayout(_OpacityWidgetLayout); + + QWidgetAction * OpacityAction = new QWidgetAction(this); + OpacityAction->setDefaultWidget(_OpacityWidget); + // QObject::connect( m_OpacityAction, SIGNAL( changed() ), this, SLOT( OpacityActionChanged() ) ); + opacitySlider->setValue(static_cast(GetWorkingImage()->GetLabel(pixelValue)->GetOpacity()*100)); + + menu->addAction(OpacityAction); + } + menu->popup(QCursor::pos()); +} + +void QmitkLabelSetWidget::OnUnlockAllLabels(bool /*value*/) +{ + GetWorkingImage()->GetLabelSet()->SetAllLabelsLocked(false); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnLockAllLabels(bool /*value*/) +{ + GetWorkingImage()->GetLabelSet()->SetAllLabelsLocked(true); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnSetAllLabelsVisible(bool /*value*/) +{ + GetWorkingImage()->GetLabelSet()->SetAllLabelsVisible(true); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + UpdateAllTableWidgetItems(); +} + +void QmitkLabelSetWidget::OnSetAllLabelsInvisible(bool /*value*/) +{ + GetWorkingImage()->GetLabelSet()->SetAllLabelsVisible(false); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + UpdateAllTableWidgetItems(); +} + +void QmitkLabelSetWidget::OnSetOnlyActiveLabelVisible(bool /*value*/) +{ + mitk::LabelSetImage * workingImage = GetWorkingImage(); + int pixelValue = GetPixelValueOfSelectedItem(); + + workingImage->GetActiveLabelSet()->SetAllLabelsVisible(false); + workingImage->GetLabel(pixelValue)->SetVisible(true); + + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); + + this->WaitCursorOn(); + const mitk::Point3D& pos = workingImage->GetLabel(pixelValue)->GetCenterOfMassCoordinates(); + this->WaitCursorOff(); + if (pos.GetVnlVector().max_value() > 0.0) + emit goToLabel(pos); + + UpdateAllTableWidgetItems(); +} + + +void QmitkLabelSetWidget::OnMergeLabel(bool /*value*/) +{ + QmitkSearchLabelDialog dialog(this); + dialog.setWindowTitle("Select a second label.."); + dialog.SetLabelSuggestionList(GetLabelStringList()); + int dialogReturnValue = dialog.exec(); + if ( dialogReturnValue == QDialog::Rejected ) return; + + int pixelValue = -1; + for(int i = 0 ; i < m_Controls.m_LabelSetTableWidget->columnCount();i++) + { + if( dialog.GetLabelSetWidgetTableCompleteWord() == QString( m_Controls.m_LabelSetTableWidget->item( i ,0)->text() ) ) + pixelValue = m_Controls.m_LabelSetTableWidget->item(i ,0)->data(Qt::UserRole).toInt(); + } + + if(pixelValue == -1 ) + { + MITK_INFO << "unknown label";; + return; + } + + GetWorkingImage()->MergeLabel(pixelValue); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnEraseLabel(bool /*value*/) +{ + int pixelValue = GetPixelValueOfSelectedItem(); + QString question = "Do you really want to erase the contents of label \""; + question.append(QString::fromStdString(GetWorkingImage()->GetLabel(pixelValue)->GetName())); + question.append("\"?"); + + QMessageBox::StandardButton answerButton = QMessageBox::question( this, "Erase label", + question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); + + if (answerButton == QMessageBox::Yes) + { + this->WaitCursorOn(); + GetWorkingImage()->EraseLabel(pixelValue); + this->WaitCursorOff(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void QmitkLabelSetWidget::OnRemoveLabel(bool /*value*/) +{ + int pixelValue = GetPixelValueOfSelectedItem(); + QString question = "Do you really want to remove label \""; + question.append(QString::fromStdString(GetWorkingImage()->GetLabel(pixelValue)->GetName())); + question.append("\"?"); + + QMessageBox::StandardButton answerButton = QMessageBox::question( this, "Remove label", + question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); + + if (answerButton == QMessageBox::Yes) + { + this->WaitCursorOn(); + GetWorkingImage()->GetActiveLabelSet()->RemoveLabel(pixelValue); + GetWorkingImage()->EraseLabel(pixelValue); + this->WaitCursorOff(); + } + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnRenameLabel(bool /*value*/) +{ + + QmitkNewSegmentationDialog dialog(this); + dialog.setWindowTitle("Rename Label"); + dialog.SetSuggestionList( m_OrganColors ); + dialog.SetColor(GetWorkingImage()->GetActiveLabel()->GetColor()); + dialog.SetSegmentationName(GetWorkingImage()->GetActiveLabel()->GetName()); + + if ( dialog.exec() == QDialog::Rejected ) return; + int pixelValue = GetWorkingImage()->GetActiveLabel()->GetValue(); + + GetWorkingImage()->GetLabel(pixelValue)->SetColor(dialog.GetColor()); + GetWorkingImage()->GetLabel(pixelValue)->SetName(dialog.GetSegmentationName().toStdString()); + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); +} + +void QmitkLabelSetWidget::OnCombineAndCreateMask( bool /*value*/ ) +{ + m_Controls.m_LabelSetTableWidget->selectedRanges(); + // ...to do... // +} + +void QmitkLabelSetWidget::OnCreateMasks(bool /*value*/) +{ + m_Controls.m_LabelSetTableWidget->selectedRanges(); + // ..to do.. // +} + +void QmitkLabelSetWidget::OnCombineAndCreateSurface(bool /*value*/) +{ + m_Controls.m_LabelSetTableWidget->selectedRanges(); + // ..to do.. // +} + +void QmitkLabelSetWidget::OnEraseLabels(bool /*value*/) +{ + QString question = "Do you really want to erase the selected labels?"; + + QMessageBox::StandardButton answerButton = QMessageBox::question( this, "Erase selected labels", + question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); + + if (answerButton == QMessageBox::Yes) + { + QList ranges = m_Controls.m_LabelSetTableWidget->selectedRanges(); + if ( ranges.isEmpty() ) + return; + + std::vector VectorOfLablePixelValues; + foreach (QTableWidgetSelectionRange a, ranges) + for(int i = a.topRow(); i <= a.bottomRow(); i++) + VectorOfLablePixelValues.push_back(m_Controls.m_LabelSetTableWidget->item(i,0)->data(Qt::UserRole).toInt()); + + this->WaitCursorOn(); + GetWorkingImage()->EraseLabels(VectorOfLablePixelValues); + this->WaitCursorOff(); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void QmitkLabelSetWidget::OnRemoveLabels(bool /*value*/) +{ + QString question = "Do you really want to remove selected labels?"; + QMessageBox::StandardButton answerButton = QMessageBox::question( this, "Remove selected labels", + question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); + + if (answerButton == QMessageBox::Yes) + { + QList ranges = m_Controls.m_LabelSetTableWidget->selectedRanges(); + if ( ranges.isEmpty() ) + return; + + std::vector VectorOfLablePixelValues; + foreach (QTableWidgetSelectionRange a, ranges) + for(int i = a.topRow(); i <= a.bottomRow(); i++) + VectorOfLablePixelValues.push_back(m_Controls.m_LabelSetTableWidget->item(i,0)->data(Qt::UserRole).toInt()); + + this->WaitCursorOn(); + GetWorkingImage()->RemoveLabels(VectorOfLablePixelValues); + this->WaitCursorOff(); + } + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnMergeLabels(bool /*value*/) +{ + int pixelValue = GetPixelValueOfSelectedItem(); + QString question = "Do you really want to merge selected labels into \""; + question.append(QString::fromStdString(GetWorkingImage()->GetLabel(pixelValue)->GetName())); + question.append("\"?"); + + QMessageBox::StandardButton answerButton = QMessageBox::question( this, "Merge selected label", + question, QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes); + + if (answerButton == QMessageBox::Yes) + { + QList ranges = m_Controls.m_LabelSetTableWidget->selectedRanges(); + if ( ranges.isEmpty() ) + return; + + std::vector VectorOfLablePixelValues; + foreach (QTableWidgetSelectionRange a, ranges) + for(int i = a.topRow(); i <= a.bottomRow(); i++) + VectorOfLablePixelValues.push_back(m_Controls.m_LabelSetTableWidget->item(i,0)->data(Qt::UserRole).toInt()); + + this->WaitCursorOn(); + int pixelValue = m_Controls.m_LabelSetTableWidget->item(m_Controls.m_LabelSetTableWidget->currentRow(),0)->data(Qt::UserRole).toInt(); + GetWorkingImage()->MergeLabels(VectorOfLablePixelValues,pixelValue); + this->WaitCursorOff(); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void QmitkLabelSetWidget::OnLockedButtonClicked() +{ + int row; + for(int i=0; irowCount(); i++) + { + if (sender() == m_Controls.m_LabelSetTableWidget->cellWidget(i,LOCKED_COL)) + { + row = i; + } + } + if (row >= 0 && row < m_Controls.m_LabelSetTableWidget->rowCount()) + { + int pixelValue = m_Controls.m_LabelSetTableWidget->item(row,0)->data(Qt::UserRole).toInt(); + GetWorkingImage()->GetLabel(pixelValue)->SetLocked(!GetWorkingImage()->GetLabel(pixelValue)->GetLocked() ); + } +} + +void QmitkLabelSetWidget::OnVisibleButtonClicked() +{ + int row; + for(int i=0; irowCount(); i++) + { + if (sender() == m_Controls.m_LabelSetTableWidget->cellWidget(i,VISIBLE_COL)) + { + row = i; + break; + } + } + + if (row >= 0 && row < m_Controls.m_LabelSetTableWidget->rowCount()) + { + QTableWidgetItem * item = m_Controls.m_LabelSetTableWidget->item(row,0); + OnItemClicked(item); + int pixelValue = item->data(Qt::UserRole).toInt(); + GetWorkingImage()->GetLabel(pixelValue)->SetVisible(!GetWorkingImage()->GetLabel(pixelValue)->GetVisible() ); + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } +} + +void QmitkLabelSetWidget::OnColorButtonClicked() +{ + int row; + for(int i=0; irowCount(); i++) + { + if (sender() == m_Controls.m_LabelSetTableWidget->cellWidget(i,COLOR_COL)) + { + row = i; + } + } + + if (row >= 0 && row < m_Controls.m_LabelSetTableWidget->rowCount()) + { + int pixelValue = m_Controls.m_LabelSetTableWidget->item(row,0)->data(Qt::UserRole).toInt(); + const mitk::Color& color = GetWorkingImage()->GetLabel(pixelValue)->GetColor(); + QColor initial(color.GetRed()*255,color.GetGreen()*255,color.GetBlue()*255); + QColor qcolor = QColorDialog::getColor(initial,0,QString("Change color")); + if (!qcolor.isValid()) + return; + + QPushButton* button = (QPushButton*) m_Controls.m_LabelSetTableWidget->cellWidget(row,COLOR_COL); + if (!button) return; + + button->setAutoFillBackground(true); + + QString styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(qcolor.red())); + styleSheet.append(","); + styleSheet.append(QString::number(qcolor.green())); + styleSheet.append(","); + styleSheet.append(QString::number(qcolor.blue())); + styleSheet.append(")"); + button->setStyleSheet(styleSheet); + + mitk::Color newColor; + newColor.SetRed(qcolor.red()/255.0); + newColor.SetGreen(qcolor.green()/255.0); + newColor.SetBlue(qcolor.blue()/255.0); + + GetWorkingImage()->GetLabel(pixelValue)->SetColor(newColor); + + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); + } +} + +void QmitkLabelSetWidget::OnRandomColor(bool /*value*/) +{ + int pixelValue = GetPixelValueOfSelectedItem(); + GetWorkingImage()->GetLabel(pixelValue)->SetColor(m_ColorSequenceRainbow.GetNextColor() ); + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); +} + +void QmitkLabelSetWidget::SetOrganColors(const QStringList& organColors) +{ + m_OrganColors = organColors; +} + +void QmitkLabelSetWidget::OnActiveLabelChanged(int pixelValue) +{ + mitk::LabelSetImage* workingImage = GetWorkingImage(); + assert(workingImage); + workingImage->GetActiveLabelSet()->SetActiveLabel(pixelValue); + //MITK_INFO << "Active Label set to << " << pixelValue; + + mitk::SurfaceBasedInterpolationController* interpolator = mitk::SurfaceBasedInterpolationController::GetInstance(); + if (interpolator) + interpolator->SetActiveLabel(pixelValue); +} + +void QmitkLabelSetWidget::OnItemClicked(QTableWidgetItem *item) +{ + if (!item) return; + + int pixelValue = item->data(Qt::UserRole).toInt(); + + QList ranges = m_Controls.m_LabelSetTableWidget->selectedRanges(); + if(!ranges.empty() && ranges.back().rowCount() == 1) + { + SelectLabelByPixelValue(pixelValue); + OnActiveLabelChanged(pixelValue); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + +} + +void QmitkLabelSetWidget::OnItemDoubleClicked(QTableWidgetItem *item) +{ + if (!item) return; + int pixelValue = item->data(Qt::UserRole).toInt(); + //OnItemClicked(item); <<-- Double click first call OnItemClicked + WaitCursorOn(); + mitk::LabelSetImage * workingImage = GetWorkingImage(); + workingImage->UpdateCenterOfMass(pixelValue); + const mitk::Point3D& pos = workingImage->GetLabel(pixelValue)->GetCenterOfMassCoordinates(); + WaitCursorOff(); + if (pos.GetVnlVector().max_value() > 0.0) emit goToLabel(pos); +} + +void QmitkLabelSetWidget::SelectLabelByPixelValue(int pixelValue) +{ + + //MITK_INFO << "QmitkLabelSetWidget::SelectLabelByPixelValue " << pixelValue; + + if(!GetWorkingImage()->ExistLabel(pixelValue)) return; + for(int row = 0 ; row < m_Controls.m_LabelSetTableWidget->rowCount(); row++) + { + if(m_Controls.m_LabelSetTableWidget->item(row,0)->data(Qt::UserRole).toInt() == pixelValue) + { + m_Controls.m_LabelSetTableWidget->clearSelection(); + m_Controls.m_LabelSetTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_Controls.m_LabelSetTableWidget->selectRow(row); + m_Controls.m_LabelSetTableWidget->scrollToItem(m_Controls.m_LabelSetTableWidget->item(row,0)); + m_Controls.m_LabelSetTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + //SelectTableWidgetItem(m_Controls.m_LabelSetTableWidget->item(i,0)); + //emit resetView(); + //GetWorkingImage()->Modified(); + return; + } + } +} + +void QmitkLabelSetWidget::InsertTableWidgetItem(mitk::Label * label) +{ + const mitk::Color& color = label->GetColor(); + + QTableWidget * tableWidget = m_Controls.m_LabelSetTableWidget; + + QString styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(color[0]*255)); + styleSheet.append(","); + styleSheet.append(QString::number(color[1]*255)); + styleSheet.append(","); + styleSheet.append(QString::number(color[2]*255)); + styleSheet.append(")"); + + int colWidth = (tableWidget->columnWidth(NAME_COL) < 180) ? 180 : tableWidget->columnWidth(NAME_COL)-2; + QString text = fontMetrics().elidedText(label->GetName().c_str(), Qt::ElideMiddle, colWidth); + QTableWidgetItem *nameItem = new QTableWidgetItem(text); + nameItem->setTextAlignment(Qt::AlignCenter | Qt::AlignLeft); + // ---!--- + // IMPORTANT: ADD PIXELVALUE TO TABLEWIDGETITEM.DATA + nameItem->setData(Qt::UserRole,QVariant(label->GetValue())); + // ---!--- + + QPushButton * pbColor = new QPushButton(tableWidget); + pbColor->setFixedSize(24,24); + pbColor->setCheckable(false); + pbColor->setAutoFillBackground(true); + pbColor->setToolTip("Change label color"); + pbColor->setStyleSheet(styleSheet); + + connect( pbColor, SIGNAL(clicked()), this, SLOT(OnColorButtonClicked()) ); + + QPushButton * pbLocked = new QPushButton(tableWidget); + pbLocked->setFixedSize(24,24); + QIcon * iconLocked = new QIcon(); + iconLocked->addFile(QString::fromUtf8(":/Qmitk/lock.png"), QSize(), QIcon::Normal, QIcon::Off); + iconLocked->addFile(QString::fromUtf8(":/Qmitk/unlock.png"), QSize(), QIcon::Normal, QIcon::On); + pbLocked->setIcon(*iconLocked); + pbLocked->setIconSize(QSize(24,24)); + pbLocked->setCheckable(true); + pbLocked->setToolTip("Lock/unlock label"); + pbLocked->setChecked(!label->GetLocked()); + connect( pbLocked, SIGNAL(clicked()), this, SLOT(OnLockedButtonClicked()) ); + + QPushButton * pbVisible = new QPushButton(tableWidget); + pbVisible->setFixedSize(24,24); + pbVisible->setAutoRepeat(false); + QIcon * iconVisible = new QIcon(); + iconVisible->addFile(QString::fromUtf8(":/Qmitk/visible.png"), QSize(), QIcon::Normal, QIcon::Off); + iconVisible->addFile(QString::fromUtf8(":/Qmitk/invisible.png"), QSize(), QIcon::Normal, QIcon::On); + pbVisible->setIcon(*iconVisible); + pbVisible->setIconSize(QSize(24,24)); + pbVisible->setCheckable(true); + pbVisible->setToolTip("Show/hide label"); + pbVisible->setChecked(!label->GetVisible()); + + connect( pbVisible, SIGNAL(clicked()), this, SLOT(OnVisibleButtonClicked()) ); + + int row = tableWidget->rowCount(); + tableWidget->insertRow(row); + tableWidget->setRowHeight(row,24); + tableWidget->setItem(row, 0, nameItem ); + tableWidget->setCellWidget(row, 1, pbLocked); + tableWidget->setCellWidget(row, 2, pbColor); + tableWidget->setCellWidget(row, 3, pbVisible); + tableWidget->selectRow(row); + + //m_LabelSetImage->SetActiveLabel(label->GetPixelValue()); + //m_ToolManager->WorkingDataModified.Send(); + //emit activeLabelChanged(label->GetPixelValue()); + + if (row == 0) + tableWidget->hideRow(row); // hide exterior label + + mitk::LabelSetImage * workingImage; + if((workingImage = GetWorkingImage()) == NULL) return; + +} + +void QmitkLabelSetWidget::UpdateAllTableWidgetItems() +{ + QTableWidget * tableWidget = m_Controls.m_LabelSetTableWidget; + + mitk::LabelSetImage * workingImage = GetWorkingImage(); + if(!workingImage) return; + + // add all labels + m_LabelStringList.clear(); + for(int i = 0 ; i < tableWidget->rowCount(); i++) + { + UpdateTableWidgetItem(tableWidget->item(i,0)); + m_LabelStringList.append( tableWidget->item(i,0)->text() ); + } + + OnLabelListModified(m_LabelStringList); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::UpdateTableWidgetItem(QTableWidgetItem *item) +{ + mitk::LabelSetImage * workingImage = GetWorkingImage(); + mitk::Label * label = workingImage->GetLabel(item->data(Qt::UserRole).toInt()); + + const mitk::Color& color = label->GetColor(); + + QTableWidget * tableWidget = m_Controls.m_LabelSetTableWidget; + + QString styleSheet = "background-color:rgb("; + styleSheet.append(QString::number(color[0]*255)); + styleSheet.append(","); + styleSheet.append(QString::number(color[1]*255)); + styleSheet.append(","); + styleSheet.append(QString::number(color[2]*255)); + styleSheet.append(")"); + + // Update text Label tableWdget->item(row,0) + int colWidth = (tableWidget->columnWidth(NAME_COL) < 180) ? 180 : tableWidget->columnWidth(NAME_COL)-2; + QString text = fontMetrics().elidedText(label->GetName().c_str(), Qt::ElideMiddle, colWidth); + item->setText(text); + + QPushButton * pbLocked = dynamic_cast(tableWidget->cellWidget(item->row(),1)); + pbLocked->setChecked(!label->GetLocked()); + + QPushButton * pbColor = dynamic_cast(tableWidget->cellWidget(item->row(),2)); + pbColor->setStyleSheet(styleSheet); + + QPushButton * pbVisible = dynamic_cast(tableWidget->cellWidget(item->row(),3)); + pbVisible->setChecked(!label->GetVisible()); + + if (item->row() == 0)tableWidget->hideRow(item->row()); // hide exterior label +} + + +void QmitkLabelSetWidget::ResetAllTableWidgetItems() +{ + QTableWidget * tableWidget = m_Controls.m_LabelSetTableWidget; + // remove all rows + while (tableWidget->rowCount()) + tableWidget->removeRow( 0 ); + + mitk::LabelSetImage * workingImage = GetWorkingImage(); + if(!workingImage) return; + + // add all labels + m_LabelStringList.clear(); + + mitk::LabelSet::LabelContainerConstIteratorType it = workingImage->GetActiveLabelSet()->IteratorConstBegin(); + mitk::LabelSet::LabelContainerConstIteratorType end = workingImage->GetActiveLabelSet()->IteratorConstEnd(); + + int pixelValue =-1; + while (it != end) + { + InsertTableWidgetItem(it->second); + if(GetWorkingImage()->GetActiveLabel() == it->second) // get active + pixelValue = it->first; + m_LabelStringList.append( QString(it->second->GetName().c_str()) ); + it++; + } + + SelectLabelByPixelValue(pixelValue); + + OnLabelListModified(m_LabelStringList); + + std::stringstream captionText; + captionText << "Number of labels: " << workingImage->GetNumberOfLabels() - 1; + m_Controls.m_lblCaption->setText(captionText.str().c_str()); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +int QmitkLabelSetWidget::GetPixelValueOfSelectedItem() +{ + if(m_Controls.m_LabelSetTableWidget->currentItem()) + return m_Controls.m_LabelSetTableWidget->currentItem()->data(Qt::UserRole).toInt(); + return -1; +} + +QStringList & QmitkLabelSetWidget::GetLabelStringList() +{ + return m_LabelStringList; +} + +void QmitkLabelSetWidget::InitializeTableWidget() +{ + QTableWidget * tableWidged = m_Controls.m_LabelSetTableWidget; + + tableWidged->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum); + tableWidged->setTabKeyNavigation(false); + tableWidged->setAlternatingRowColors(false); + tableWidged->setFocusPolicy(Qt::NoFocus); + tableWidged->setColumnCount(4); + tableWidged->resizeColumnToContents(NAME_COL); + tableWidged->setColumnWidth(LOCKED_COL,25); + tableWidged->setColumnWidth(COLOR_COL,25); + tableWidged->setColumnWidth(VISIBLE_COL,25); + tableWidged->horizontalHeader()->setResizeMode( 0, QHeaderView::Stretch ); + tableWidged->setContextMenuPolicy(Qt::CustomContextMenu); + tableWidged->horizontalHeader()->hide(); + tableWidged->setSortingEnabled ( false ); + tableWidged->verticalHeader()->hide(); + tableWidged->setEditTriggers(QAbstractItemView::NoEditTriggers); + tableWidged->setSelectionMode(QAbstractItemView::ExtendedSelection); + tableWidged->setSelectionBehavior(QAbstractItemView::SelectRows); + + connect(tableWidged, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(OnItemClicked(QTableWidgetItem *))); + connect(tableWidged, SIGNAL(itemDoubleClicked(QTableWidgetItem *)), this, SLOT(OnItemDoubleClicked(QTableWidgetItem *))); + connect(tableWidged, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnTableViewContextMenuRequested(const QPoint&)) ); + + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(activeLabelChanged(int)), this, SLOT(OnActiveLabelChanged(int)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(importSegmentation()), this, SLOT( OnImportSegmentation()) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(importLabeledImage()), this, SLOT( OnImportLabeledImage()) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(renameLabel(int, const mitk::Color&, const std::string&)), this, SLOT(OnRenameLabel(int, const mitk::Color&, const std::string&)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(createSurface(int, bool)), this, SLOT(OnCreateSurface(int, bool)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(toggleOutline(bool)), this, SLOT(OnToggleOutline(bool)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(goToLabel(const mitk::Point3D&)), this, SIGNAL(goToLabel(const mitk::Point3D&)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(combineAndCreateSurface( const QList& )), + // this, SLOT(OnCombineAndCreateSurface( const QList&)) ); + + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(createMask(int)), this, SLOT(OnCreateMask(int)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(createCroppedMask(int)), this, SLOT(OnCreateCroppedMask(int)) ); + //connect( m_Controls.m_LabelSetTableWidget, SIGNAL(combineAndCreateMask( const QList& )), + // this, SLOT(OnCombineAndCreateMask( const QList&)) ); +} + +void QmitkLabelSetWidget::OnOpacityChanged(int value) +{ + int pixelValue = m_Controls.m_LabelSetTableWidget->currentItem()->data(Qt::UserRole).toInt(); + float opacity = static_cast(value)/100.0f; + GetWorkingImage()->GetLabel(pixelValue)->SetOpacity(opacity); + GetWorkingImage()->GetActiveLabelSet()->UpdateLookupTable(pixelValue); +} + +void QmitkLabelSetWidget::setEnabled(bool enabled) +{ + QWidget::setEnabled(enabled); + UpdateControls(); +} + +void QmitkLabelSetWidget::SetDataStorage( mitk::DataStorage* storage ) +{ + m_DataStorage = storage; +} + +void QmitkLabelSetWidget::OnSearchLabel() +{ + std::string text = m_Controls.m_LabelSearchBox->text().toStdString(); + int pixelValue = -1; + int row = -1; + for(int i = 0; i < m_Controls.m_LabelSetTableWidget->rowCount(); i++){ + if( m_Controls.m_LabelSetTableWidget->item(i,0)->text().toStdString().compare(text) == 0) + { + pixelValue = m_Controls.m_LabelSetTableWidget->item(i,0)->data(Qt::UserRole).toInt(); + row = i; + break; + } + } + if(pixelValue == -1) return; + GetWorkingImage()->GetActiveLabelSet()->SetActiveLabel(pixelValue); + + QTableWidgetItem* nameItem = m_Controls.m_LabelSetTableWidget->item(row,NAME_COL); + if (!nameItem) return; + + m_Controls.m_LabelSetTableWidget->clearSelection(); + m_Controls.m_LabelSetTableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + m_Controls.m_LabelSetTableWidget->selectRow(row); + m_Controls.m_LabelSetTableWidget->scrollToItem(nameItem); + m_Controls.m_LabelSetTableWidget->setSelectionMode(QAbstractItemView::ExtendedSelection); + + this->WaitCursorOn(); + mitk::Point3D pos = GetWorkingImage()->GetLabel(pixelValue)->GetCenterOfMassCoordinates(); + + m_ToolManager->WorkingDataModified.Send(); + + if (pos.GetVnlVector().max_value() > 0.0) + emit goToLabel(pos); + else + { + GetWorkingImage()->UpdateCenterOfMass(pixelValue); + mitk::Point3D pos = GetWorkingImage()->GetLabel(pixelValue)->GetCenterOfMassCoordinates(); + emit goToLabel(pos); + } + + this->WaitCursorOff(); +} + +void QmitkLabelSetWidget::OnLabelListModified(const QStringList& list) +{ + QStringListModel* completeModel = static_cast (m_Completer->model()); + completeModel->setStringList(list); +} + +mitk::LabelSetImage * QmitkLabelSetWidget::GetWorkingImage() +{ + mitk::DataNode* workingNode = GetWorkingNode(); + mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); + assert(workingImage); + return workingImage; +} + +mitk::DataNode * QmitkLabelSetWidget::GetWorkingNode() +{ + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + assert(workingNode); + return workingNode; +} + + +void QmitkLabelSetWidget::UpdateControls() +{ + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + bool hasWorkingData = (workingNode != NULL); + + m_Controls.m_LabelSetTableWidget->setEnabled(hasWorkingData); + m_Controls.m_LabelSearchBox->setEnabled(hasWorkingData); + + if (!hasWorkingData) return; + + QStringListModel* completeModel = static_cast (m_Completer->model()); + completeModel->setStringList(GetLabelStringList()); + +} + + + +void QmitkLabelSetWidget::OnCreateCroppedMask(bool) +{ + m_ToolManager->ActivateTool(-1); + + mitk::DataNode* workingNode = GetWorkingNode(); + mitk::LabelSetImage* workingImage = GetWorkingImage(); + + mitk::Image::Pointer maskImage; + + int pixelValue = GetPixelValueOfSelectedItem(); + try + { + this->WaitCursorOn(); + + mitk::AutoCropImageFilter::Pointer cropFilter = mitk::AutoCropImageFilter::New(); + cropFilter->SetInput( workingImage->CreateLabelMask(pixelValue) ); + cropFilter->SetBackgroundValue( 0 ); + cropFilter->SetMarginFactor(1.15); + cropFilter->Update(); + + maskImage = cropFilter->GetOutput(); + + this->WaitCursorOff(); + } + catch ( mitk::Exception& e ) + { + this->WaitCursorOff(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n"); + return; + } + + if (maskImage.IsNull()) + { + QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n"); + return; + } + + mitk::DataNode::Pointer maskNode = mitk::DataNode::New(); + std::string name = workingImage->GetLabel(pixelValue, workingImage->GetActiveLayer())->GetName(); + name += "-mask"; + maskNode->SetName(name); + maskNode->SetData(maskImage); + maskNode->SetBoolProperty("binary", true); + maskNode->SetBoolProperty("outline binary", true); + maskNode->SetBoolProperty("outline binary shadow", true); + maskNode->SetFloatProperty("outline width", 2.0); + maskNode->SetColor(workingImage->GetLabel(pixelValue)->GetColor()); + maskNode->SetOpacity(1.0); + + m_DataStorage->Add(maskNode, workingNode); +} + +void QmitkLabelSetWidget::OnCreateMask(bool /*triggered*/) +{ + m_ToolManager->ActivateTool(-1); + + mitk::DataNode* workingNode = GetWorkingNode(); + mitk::LabelSetImage* workingImage = GetWorkingImage(); + + mitk::Image::Pointer maskImage; + + int pixelValue = GetPixelValueOfSelectedItem(); + + try + { + this->WaitCursorOn(); + maskImage = workingImage->CreateLabelMask(pixelValue); + this->WaitCursorOff(); + } + catch ( mitk::Exception& e ) + { + this->WaitCursorOff(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n"); + return; + } + + if (maskImage.IsNull()) + { + QMessageBox::information(this, "Create Mask", "Could not create a mask out of the selected label.\n"); + return; + } + + mitk::DataNode::Pointer maskNode = mitk::DataNode::New(); + std::string name = workingImage->GetLabel(pixelValue, workingImage->GetActiveLayer())->GetName(); + name += "-mask"; + maskNode->SetName(name); + maskNode->SetData(maskImage); + maskNode->SetBoolProperty("binary", true); + maskNode->SetBoolProperty("outline binary", true); + maskNode->SetBoolProperty("outline binary shadow", true); + maskNode->SetFloatProperty("outline width", 2.0); + maskNode->SetColor(workingImage->GetLabel(pixelValue)->GetColor()); + maskNode->SetOpacity(1.0); + + m_DataStorage->Add(maskNode, workingNode); +} + +void QmitkLabelSetWidget::OnToggleOutline(bool value) +{ + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + assert(workingNode); + + workingNode->SetBoolProperty( "labelset.contour.all", value); + workingNode->GetData()->Modified(); // fixme: workaround to force data-type rendering (and not only property-type) + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::OnCreateSmoothedSurface(bool /*triggered*/) +{ + m_ToolManager->ActivateTool(-1); + + mitk::DataNode::Pointer workingNode = GetWorkingNode(); + mitk::LabelSetImage* workingImage = GetWorkingImage(); + int pixelValue = GetPixelValueOfSelectedItem(); + + mitk::LabelSetImageToSurfaceThreadedFilter::Pointer surfaceFilter = mitk::LabelSetImageToSurfaceThreadedFilter::New(); + + itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); + successCommand->SetCallbackFunction(this, &QmitkLabelSetWidget::OnThreadedCalculationDone); + surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand); + + itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); + errorCommand->SetCallbackFunction(this, &QmitkLabelSetWidget::OnThreadedCalculationDone); + surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand); + + mitk::DataNode::Pointer groupNode = workingNode; + surfaceFilter->SetPointerParameter("Group node", groupNode); + surfaceFilter->SetPointerParameter("Input", workingImage); + surfaceFilter->SetParameter("RequestedLabel", pixelValue); + surfaceFilter->SetParameter("Smooth", true); + surfaceFilter->SetDataStorage( *m_DataStorage ); + + mitk::StatusBar::GetInstance()->DisplayText("Surface creation is running in background..."); + + try + { + surfaceFilter->StartAlgorithm(); + } + catch ( mitk::Exception & e ) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Create Surface", "Could not create a surface mesh out of the selected label. See error log for details.\n"); + } + +} + +void QmitkLabelSetWidget::OnCreateDetailedSurface(bool /*triggered*/) +{ + m_ToolManager->ActivateTool(-1); + + mitk::DataNode::Pointer workingNode = GetWorkingNode(); + mitk::LabelSetImage* workingImage = GetWorkingImage(); + int pixelValue = GetPixelValueOfSelectedItem(); + + mitk::LabelSetImageToSurfaceThreadedFilter::Pointer surfaceFilter = mitk::LabelSetImageToSurfaceThreadedFilter::New(); + + itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); + successCommand->SetCallbackFunction(this, &QmitkLabelSetWidget::OnThreadedCalculationDone); + surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand); + + itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); + errorCommand->SetCallbackFunction(this, &QmitkLabelSetWidget::OnThreadedCalculationDone); + surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand); + + mitk::DataNode::Pointer groupNode = workingNode; + surfaceFilter->SetPointerParameter("Group node", groupNode); + surfaceFilter->SetPointerParameter("Input", workingImage); + surfaceFilter->SetParameter("RequestedLabel", pixelValue); + surfaceFilter->SetParameter("Smooth", false); + surfaceFilter->SetDataStorage( *m_DataStorage ); + + mitk::StatusBar::GetInstance()->DisplayText("Surface creation is running in background..."); + + try + { + surfaceFilter->StartAlgorithm(); + } + catch ( mitk::Exception & e ) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Create Surface", "Could not create a surface mesh out of the selected label. See error log for details.\n"); + } + +} + +void QmitkLabelSetWidget::OnImportLabeledImage() +{ +/* + m_ToolManager->ActivateTool(-1); + + mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); + assert(referenceNode); + + // Ask the user for a list of files to open + QStringList fileNames = QFileDialog::getOpenFileNames( this, "Open Image", m_LastFileOpenPath, + mitk::CoreObjectFactory::GetInstance()->GetFileExtensions()); + + if (fileNames.empty()) + return; + + try + { + this->WaitCursorOn(); + mitk::Image::Pointer image = mitk::IOUtil::LoadImage( fileNames.front().toStdString() ); + if (image.IsNull()) + { + this->WaitCursorOff(); + QMessageBox::information(this, "Import Labeled Image", "Could not load the selected segmentation.\n"); + return; + } + + mitk::LabelSetImage::Pointer newImage = mitk::LabelSetImage::New(); + newImage->InitializeByLabeledImage(image); + this->WaitCursorOff(); + + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + std::string newName = referenceNode->GetName(); + newName += "-labels"; + newNode->SetName(newName); + newNode->SetData(newImage); + m_DataStorage->Add(newNode, referenceNode); + } + catch (mitk::Exception & e) + { + this->WaitCursorOff(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Import Labeled Image", "Could not load the selected segmentation. See error log for details.\n"); + return; + } + + this->UpdateControls(); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + */ +} + +void QmitkLabelSetWidget::OnImportSegmentation() +{ +/* + m_ToolManager->ActivateTool(-1); + + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + assert(workingNode); + + mitk::LabelSetImage* workingImage = dynamic_cast( workingNode->GetData() ); + assert(workingImage); + + std::string fileExtensions("Segmentation files (*.lset);;"); + QString qfileName = QFileDialog::getOpenFileName(this, "Import Segmentation", m_LastFileOpenPath, fileExtensions.c_str() ); + if (qfileName.isEmpty() ) return; + + mitk::NrrdLabelSetImageReader::Pointer reader = mitk::NrrdLabelSetImageReader::New(); + reader->SetFileName(qfileName.toLatin1()); + + try + { + this->WaitCursorOn(); + reader->Update(); + mitk::LabelSetImage::Pointer newImage = reader->GetOutput(); + workingImage->Concatenate(newImage); + this->WaitCursorOff(); + } + catch ( mitk::Exception& e ) + { + this->WaitCursorOff(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(this, "Import Segmentation", "Could not import the selected segmentation session.\n See error log for details.\n"); + } +*/ + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} + +void QmitkLabelSetWidget::WaitCursorOn() +{ + QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); +} + +void QmitkLabelSetWidget::WaitCursorOff() +{ + this->RestoreOverrideCursor(); +} + +void QmitkLabelSetWidget::RestoreOverrideCursor() +{ + QApplication::restoreOverrideCursor(); +} + +void QmitkLabelSetWidget::OnThreadedCalculationDone() +{ + mitk::StatusBar::GetInstance()->Clear(); +} + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.h new file mode 100644 index 0000000000..262a5ab860 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidget.h @@ -0,0 +1,158 @@ +/*=================================================================== + +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 QmitkLabelSetWidget_h +#define QmitkLabelSetWidget_h + +#include "MitkSegmentationUIExports.h" + +#include +#include "mitkColorSequenceRainbow.h" +#include "mitkVector.h" + + +class QmitkDataStorageComboBox; +class QCompleter; + +namespace mitk { + class LabelSetImage; + class LabelSet; + class Label; + class DataStorage; + class ToolManager; + class DataNode; +} + +class MitkSegmentationUI_EXPORT QmitkLabelSetWidget : public QWidget +{ + Q_OBJECT + +public: + + explicit QmitkLabelSetWidget(QWidget* parent = NULL); + ~QmitkLabelSetWidget(); + + void SetDataStorage( mitk::DataStorage* storage ); + + void SetOrganColors(const QStringList& organColors); + + void UpdateControls(); + + virtual void setEnabled(bool enabled); + + QStringList &GetLabelStringList(); + + +signals: + + /// \brief Send a signal when it was requested to go to a label. + void goToLabel(const mitk::Point3D&); + void resetView(); + +public slots: + + void ResetAllTableWidgetItems(); + void UpdateAllTableWidgetItems(); + void SelectLabelByPixelValue(int pixelValue); + +private slots: + + // Label Set Dependend + void OnOpacityChanged(int); + void OnUnlockAllLabels(bool); + void OnLockAllLabels(bool); + void OnSetAllLabelsVisible(bool); + void OnSetAllLabelsInvisible(bool); + void OnSetOnlyActiveLabelVisible(bool); + void OnRandomColor(bool); + void OnRemoveLabel(bool); + void OnRemoveLabels(bool); + void OnRenameLabel(bool); + void OnLockedButtonClicked(); + void OnVisibleButtonClicked(); + void OnColorButtonClicked(); + void OnItemClicked(QTableWidgetItem *item); + void OnItemDoubleClicked(QTableWidgetItem *item); + void OnTableViewContextMenuRequested(const QPoint&); + void InsertTableWidgetItem(mitk::Label * label); + void UpdateTableWidgetItem(QTableWidgetItem *item); + // reaction to "returnPressed" signal from ... + void OnSearchLabel(); + // reaction to the button "Change Label" + void OnActiveLabelChanged(int pixelValue); + + //LabelSetImage Dependet + void OnCreateDetailedSurface(bool); + void OnCreateSmoothedSurface(bool); + // reaction to the signal "createMask" from QmitkLabelSetTableWidget + void OnCreateMask(bool); + void OnCreateMasks(bool); + // reaction to the signal "createCroppedMask" from QmitkLabelSetTableWidget + void OnCreateCroppedMask(bool); + void OnCombineAndCreateMask(bool); + void OnCombineAndCreateSurface(bool); + void OnEraseLabel(bool); + void OnEraseLabels(bool); + // reaction to signal "mergeLabel" from QmitkLabelSetTableWidget + void OnMergeLabel(bool); + void OnMergeLabels(bool); + // reaction to the button "Import Segmentation" + void OnImportSegmentation(); + // reaction to the button "Import Labeled Image" + void OnImportLabeledImage(); + + // reaction to signal "labelListModified" from QmitkLabelSetTableWidget + void OnLabelListModified(const QStringList& list); + // reaction to the signal "toggleOutline" from QmitkLabelSetTableWidget + void OnToggleOutline(bool); + +private: + + enum TableColumns { NAME_COL=0, LOCKED_COL, COLOR_COL, VISIBLE_COL }; + + void WaitCursorOn(); + + void WaitCursorOff(); + + void RestoreOverrideCursor(); + + void OnThreadedCalculationDone(); + + void InitializeTableWidget(); + + int GetPixelValueOfSelectedItem(); + + mitk::LabelSetImage * GetWorkingImage(); + + mitk::DataNode * GetWorkingNode(); + + Ui::QmitkLabelSetWidgetControls m_Controls; + + mitk::ColorSequenceRainbow m_ColorSequenceRainbow; + + QCompleter* m_Completer; + + mitk::DataStorage* m_DataStorage; + + mitk::ToolManager* m_ToolManager; + + QStringList m_OrganColors; + + QStringList m_LabelStringList; + +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidgetControls.ui new file mode 100644 index 0000000000..a9b4c069a3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkLabelSetWidgetControls.ui @@ -0,0 +1,66 @@ + + + QmitkLabelSetWidgetControls + + + + 0 + 0 + 312 + 366 + + + + + 0 + 0 + + + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Caption + + + + + + + + + + + 0 + 0 + + + + + + + + + ctkSearchBox + QLineEdit +
ctkSearchBox.h
+
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.cpp new file mode 100644 index 0000000000..ee96ac78ca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.cpp @@ -0,0 +1,171 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkMultiLabelSegmentationPreferencePage.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +QmitkMultiLabelSegmentationPreferencePage::QmitkMultiLabelSegmentationPreferencePage() +: m_MainControl(0) +, m_Initializing(false) +{ + +} + +QmitkMultiLabelSegmentationPreferencePage::~QmitkMultiLabelSegmentationPreferencePage() +{ + +} + +void QmitkMultiLabelSegmentationPreferencePage::Init(berry::IWorkbench::Pointer ) +{ + +} + +void QmitkMultiLabelSegmentationPreferencePage::CreateQtControl(QWidget* parent) +{ + m_Initializing = true; + berry::IPreferencesService::Pointer prefService + = berry::Platform::GetServiceRegistry() + .GetServiceById(berry::IPreferencesService::ID); + + m_SegmentationPreferencesNode = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); + + m_MainControl = new QWidget(parent); + + QVBoxLayout* displayOptionsLayout = new QVBoxLayout; + m_RadioOutline = new QRadioButton( "Draw as outline", m_MainControl); + displayOptionsLayout->addWidget( m_RadioOutline ); + m_RadioOverlay = new QRadioButton( "Draw as transparent overlay", m_MainControl); + displayOptionsLayout->addWidget( m_RadioOverlay ); + + QFormLayout *formLayout = new QFormLayout; + formLayout->setHorizontalSpacing(8); + formLayout->setVerticalSpacing(24); + formLayout->addRow( "2D display", displayOptionsLayout ); + + m_VolumeRenderingCheckBox = new QCheckBox( "Show as volume rendering", m_MainControl ); + formLayout->addRow( "3D display", m_VolumeRenderingCheckBox ); + connect( m_VolumeRenderingCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnVolumeRenderingCheckboxChecked(int)) ); + + QFormLayout* surfaceLayout = new QFormLayout; + surfaceLayout->setSpacing(8); + + m_SmoothingSpinBox = new QDoubleSpinBox(m_MainControl); + m_SmoothingSpinBox->setMinimum(0.0); + m_SmoothingSpinBox->setSingleStep(0.5); + m_SmoothingSpinBox->setValue(0.1); + m_SmoothingSpinBox->setToolTip("The Smoothing value is used as Sigma for a gaussian blur."); + surfaceLayout->addRow("Smoothing value (mm)", m_SmoothingSpinBox); + + m_DecimationSpinBox = new QDoubleSpinBox(m_MainControl); + m_DecimationSpinBox->setMinimum(0.0); + m_DecimationSpinBox->setMaximum(0.99); + m_DecimationSpinBox->setSingleStep(0.1); + m_DecimationSpinBox->setValue(0.5); + m_DecimationSpinBox->setToolTip("Valid range is [0, 1). High values increase decimation, especially when very close to 1. A value of 0 disables decimation."); + surfaceLayout->addRow("Decimation rate", m_DecimationSpinBox); + + m_SelectionModeCheckBox = new QCheckBox("Enable auto-selection mode", m_MainControl); + m_SelectionModeCheckBox->setToolTip("If checked the segmentation plugin ensures that only one segmentation and the according greyvalue image are visible at one time."); + formLayout->addRow("Data node selection mode",m_SelectionModeCheckBox); + + formLayout->addRow("Smoothed surface creation", surfaceLayout); + + m_MainControl->setLayout(formLayout); + this->Update(); + m_Initializing = false; +} + +QWidget* QmitkMultiLabelSegmentationPreferencePage::GetQtControl() const +{ + return m_MainControl; +} + +bool QmitkMultiLabelSegmentationPreferencePage::PerformOk() +{ + m_SegmentationPreferencesNode->PutBool("draw outline", m_RadioOutline->isChecked()); + m_SegmentationPreferencesNode->PutBool("volume rendering", m_VolumeRenderingCheckBox->isChecked()); + m_SegmentationPreferencesNode->PutDouble("smoothing value", m_SmoothingSpinBox->value()); + m_SegmentationPreferencesNode->PutDouble("decimation rate", m_DecimationSpinBox->value()); + m_SegmentationPreferencesNode->PutBool("auto selection", m_SelectionModeCheckBox->isChecked()); + return true; +} + +void QmitkMultiLabelSegmentationPreferencePage::PerformCancel() +{ + +} + +void QmitkMultiLabelSegmentationPreferencePage::Update() +{ + //m_EnableSingleEditing->setChecked(m_SegmentationPreferencesNode->GetBool("Single click property editing", true)); + if (m_SegmentationPreferencesNode->GetBool("draw outline", true) ) + { + m_RadioOutline->setChecked( true ); + } + else + { + m_RadioOverlay->setChecked( true ); + } + + m_VolumeRenderingCheckBox->setChecked( m_SegmentationPreferencesNode->GetBool("volume rendering", false) ); + + if (m_SegmentationPreferencesNode->GetBool("smoothing hint", true)) + { + m_SmoothingSpinBox->setDisabled(true); + } + else + { + m_SmoothingSpinBox->setEnabled(true); + } + + m_SelectionModeCheckBox->setChecked( m_SegmentationPreferencesNode->GetBool("auto selection", true) ); + + m_SmoothingSpinBox->setValue(m_SegmentationPreferencesNode->GetDouble("smoothing value", 0.1)); + m_DecimationSpinBox->setValue(m_SegmentationPreferencesNode->GetDouble("decimation rate", 0.5)); +} + +void QmitkMultiLabelSegmentationPreferencePage::OnVolumeRenderingCheckboxChecked(int state) +{ + if (m_Initializing) return; + + if ( state != Qt::Unchecked ) + { + QMessageBox::information(NULL, + "Memory warning", + "Turning on volume rendering of segmentations will make the application more memory intensive (and potentially prone to crashes).\n\n" + "If you encounter out-of-memory problems, try turning off volume rendering again."); + } +} + +void QmitkMultiLabelSegmentationPreferencePage::OnSmoothingCheckboxChecked(int state) +{ + if (state != Qt::Unchecked) + m_SmoothingSpinBox->setDisabled(true); + else + m_SmoothingSpinBox->setEnabled(true); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.h new file mode 100644 index 0000000000..95cb8c74c4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/QmitkMultiLabelSegmentationPreferencePage.h @@ -0,0 +1,81 @@ +/*=================================================================== + +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 QmitkMultiLabelSegmentationPreferencePage_h_included +#define QmitkMultiLabelSegmentationPreferencePage_h_included + +#include "berryIQtPreferencePage.h" +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" +#include + +class QWidget; +class QCheckBox; +class QRadioButton; +class QDoubleSpinBox; + +class MITK_QT_SEGMENTATION QmitkMultiLabelSegmentationPreferencePage : public QObject, public berry::IQtPreferencePage +{ + Q_OBJECT + Q_INTERFACES(berry::IPreferencePage) + +public: + + QmitkMultiLabelSegmentationPreferencePage(); + ~QmitkMultiLabelSegmentationPreferencePage(); + + void Init(berry::IWorkbench::Pointer workbench); + + void CreateQtControl(QWidget* widget); + + QWidget* GetQtControl() const; + + /// + /// \see IPreferencePage::PerformOk() + /// + virtual bool PerformOk(); + + /// + /// \see IPreferencePage::PerformCancel() + /// + virtual void PerformCancel(); + + /// + /// \see IPreferencePage::Update() + /// + virtual void Update(); + +protected slots: + + void OnVolumeRenderingCheckboxChecked(int); + void OnSmoothingCheckboxChecked(int); + +protected: + + QWidget* m_MainControl; + QRadioButton* m_RadioOutline; + QRadioButton* m_RadioOverlay; + QCheckBox* m_VolumeRenderingCheckBox; + QDoubleSpinBox* m_SmoothingSpinBox; + QDoubleSpinBox* m_DecimationSpinBox; + QCheckBox* m_SelectionModeCheckBox; + + bool m_Initializing; + + berry::IPreferences::Pointer m_SegmentationPreferencesNode; +}; + +#endif /* QMITKDATAMANAGERPREFERENCEPAGE_H_ */ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.cpp new file mode 100644 index 0000000000..e4e7147c83 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.cpp @@ -0,0 +1,181 @@ +/*=================================================================== + +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 "QmitkDataSelectionWidget.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static mitk::NodePredicateBase::Pointer CreatePredicate(QmitkDataSelectionWidget::PredicateType predicateType) +{ + + mitk::NodePredicateAnd::Pointer segmentationPredicate = mitk::NodePredicateAnd::New(); + segmentationPredicate->AddPredicate(mitk::TNodePredicateDataType::New()); + segmentationPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object"))); + + mitk::NodePredicateAnd::Pointer maskPredicate = mitk::NodePredicateAnd::New(); + maskPredicate->AddPredicate(mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true))); + maskPredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)))); + + mitk::NodePredicateDataType::Pointer isDwi = mitk::NodePredicateDataType::New("DiffusionImage"); + mitk::NodePredicateDataType::Pointer isDti = mitk::NodePredicateDataType::New("TensorImage"); + mitk::NodePredicateDataType::Pointer isQbi = mitk::NodePredicateDataType::New("QBallImage"); + mitk::TNodePredicateDataType::Pointer isImage = mitk::TNodePredicateDataType::New(); + + mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); + validImages->AddPredicate(isImage); + validImages->AddPredicate(isDwi); + validImages->AddPredicate(isDti); + validImages->AddPredicate(isQbi); + + mitk::NodePredicateAnd::Pointer imagePredicate = mitk::NodePredicateAnd::New(); + imagePredicate->AddPredicate(validImages); + imagePredicate->AddPredicate(mitk::NodePredicateNot::New(segmentationPredicate)); + imagePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true)))); + imagePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)))); + + mitk::NodePredicateAnd::Pointer surfacePredicate = mitk::NodePredicateAnd::New(); + surfacePredicate->AddPredicate(mitk::TNodePredicateDataType::New()); + surfacePredicate->AddPredicate(mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("helper object", mitk::BoolProperty::New(true)))); + + switch(predicateType) + { + case QmitkDataSelectionWidget::ImagePredicate: + return imagePredicate.GetPointer(); + + case QmitkDataSelectionWidget::MaskPredicate: + return maskPredicate.GetPointer(); + + case QmitkDataSelectionWidget::SegmentationPredicate: + return segmentationPredicate.GetPointer(); + + case QmitkDataSelectionWidget::SurfacePredicate: + return surfacePredicate.GetPointer(); + + default: + assert(false && "Unknown predefined predicate!"); + return NULL; + } +} + +QmitkDataSelectionWidget::QmitkDataSelectionWidget(QWidget* parent) + : QWidget(parent) +{ + m_Controls.setupUi(this); + m_Controls.helpLabel->hide(); +} + +QmitkDataSelectionWidget::~QmitkDataSelectionWidget() +{ +} + +unsigned int QmitkDataSelectionWidget::AddDataStorageComboBox(QmitkDataSelectionWidget::PredicateType predicate) +{ + return this->AddDataStorageComboBox("", predicate); +} + +unsigned int QmitkDataSelectionWidget::AddDataStorageComboBox(mitk::NodePredicateBase* predicate) +{ + return this->AddDataStorageComboBox("", predicate); +} + +unsigned int QmitkDataSelectionWidget::AddDataStorageComboBox(const QString &labelText, QmitkDataSelectionWidget::PredicateType predicate) +{ + return this->AddDataStorageComboBox(labelText, CreatePredicate(predicate)); +} + +unsigned int QmitkDataSelectionWidget::AddDataStorageComboBox(const QString &labelText, mitk::NodePredicateBase* predicate) +{ + int row = m_Controls.gridLayout->rowCount(); + + if (!labelText.isEmpty()) + { + QLabel* label = new QLabel(labelText, m_Controls.dataSelectionWidget); + label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + m_Controls.gridLayout->addWidget(label, row, 0); + } + + QmitkDataStorageComboBox* comboBox = new QmitkDataStorageComboBox(this->GetDataStorage(), predicate, m_Controls.dataSelectionWidget); + connect(comboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode *)), this, SLOT(OnSelectionChanged(const mitk::DataNode *))); + comboBox->SetAutoSelectNewItems(true); + m_Controls.gridLayout->addWidget(comboBox, row, 1); + + m_DataStorageComboBoxes.push_back(comboBox); + return static_cast(m_DataStorageComboBoxes.size() - 1); +} + +mitk::DataStorage::Pointer QmitkDataSelectionWidget::GetDataStorage() const +{ + mitk::IDataStorageService::Pointer service = + berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); + + assert(service.IsNotNull()); + + return service->GetDefaultDataStorage()->GetDataStorage(); +} + +mitk::DataNode::Pointer QmitkDataSelectionWidget::GetSelection(unsigned int index) +{ + assert(index < m_DataStorageComboBoxes.size()); + return m_DataStorageComboBoxes[index]->GetSelectedNode(); +} + +void QmitkDataSelectionWidget::SetPredicate(unsigned int index, PredicateType predicate) +{ + this->SetPredicate(index, CreatePredicate(predicate)); +} + +void QmitkDataSelectionWidget::SetPredicate(unsigned int index, mitk::NodePredicateBase* predicate) +{ + assert(index < m_DataStorageComboBoxes.size()); + m_DataStorageComboBoxes[index]->SetPredicate(predicate); +} + +void QmitkDataSelectionWidget::SetHelpText(const QString& text) +{ + if (!text.isEmpty()) + { + m_Controls.helpLabel->setText(text); + + if (!m_Controls.helpLabel->isVisible()) + m_Controls.helpLabel->show(); + } + else + { + m_Controls.helpLabel->hide(); + } +} + +void QmitkDataSelectionWidget::OnSelectionChanged(const mitk::DataNode* selection) +{ + std::vector::iterator it = std::find(m_DataStorageComboBoxes.begin(), m_DataStorageComboBoxes.end(), sender()); + assert(it != m_DataStorageComboBoxes.end()); + + emit SelectionChanged(std::distance(m_DataStorageComboBoxes.begin(), it), selection); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.h new file mode 100644 index 0000000000..3ccd830c98 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidget.h @@ -0,0 +1,70 @@ +/*=================================================================== + +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 QmitkDataSelectionWidget_h +#define QmitkDataSelectionWidget_h + +#include +#include +#include +#include + +namespace mitk +{ + class NodePredicateBase; +} + +class QmitkDataStorageComboBox; + +class QmitkDataSelectionWidget : public QWidget +{ + Q_OBJECT + +public: + enum PredicateType + { + ImagePredicate, + MaskPredicate, + SegmentationPredicate, + SurfacePredicate + }; + + explicit QmitkDataSelectionWidget(QWidget* parent = NULL); + ~QmitkDataSelectionWidget(); + + unsigned int AddDataStorageComboBox(PredicateType predicate); + unsigned int AddDataStorageComboBox(mitk::NodePredicateBase* predicate = NULL); + unsigned int AddDataStorageComboBox(const QString &labelText, PredicateType predicate); + unsigned int AddDataStorageComboBox(const QString &labelText, mitk::NodePredicateBase* predicate = NULL); + + mitk::DataStorage::Pointer GetDataStorage() const; + mitk::DataNode::Pointer GetSelection(unsigned int index); + void SetPredicate(unsigned int index, PredicateType predicate); + void SetPredicate(unsigned int index, mitk::NodePredicateBase* predicate); + void SetHelpText(const QString& text); + +signals: + void SelectionChanged(unsigned int index, const mitk::DataNode* selection); + +private slots: + void OnSelectionChanged(const mitk::DataNode* selection); + +private: + Ui::QmitkDataSelectionWidgetControls m_Controls; + std::vector m_DataStorageComboBoxes; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidgetControls.ui new file mode 100644 index 0000000000..1849a496d9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/Common/QmitkDataSelectionWidgetControls.ui @@ -0,0 +1,64 @@ + + + QmitkDataSelectionWidgetControls + + + + 0 + 0 + 333 + 191 + + + + + + + + 0 + + + + + + + + Data Selection + + + + + + + 0 + + + + + + + + + 0 + 0 + + + + color: red + + + + + + true + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp new file mode 100644 index 0000000000..c15ae4f6e0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.cpp @@ -0,0 +1,197 @@ +/*=================================================================== + +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 "QmitkAutocropAction.h" + +#include "mitkAutoCropImageFilter.h" +#include "mitkImageCast.h" +#include "mitkRenderingManager.h" +#include "mitkProgressBar.h" + +#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 +++ + void *_data = _cropped3dSlice->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()->GetTimeSlicedGeometry(), 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 NULL 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(); + + unsigned long upperPad[3]; + unsigned long 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 new file mode 100644 index 0000000000..acb9ae57d9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkAutocropAction.h @@ -0,0 +1,56 @@ +/*=================================================================== + +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 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 QmitkStdMultiWidget; + +class MITK_QT_SEGMENTATION QmitkAutocropAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkAutocropAction(); + virtual ~QmitkAutocropAction(); + + //interface methods + void Run( const QList& selectedNodes ); + void SetDataStorage(mitk::DataStorage* dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart* functionality); + +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/QmitkConvertMaskToLabelAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp new file mode 100644 index 0000000000..4d4dfd16b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.cpp @@ -0,0 +1,102 @@ +/*=================================================================== + +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 "QmitkConvertMaskToLabelAction.h" + +#include "mitkRenderingManager.h" +#include "mitkLabelSetImage.h" +#include "mitkToolManagerProvider.h" + +//needed for qApp +#include + +QmitkConvertMaskToLabelAction::QmitkConvertMaskToLabelAction() +{ +} + +QmitkConvertMaskToLabelAction::~QmitkConvertMaskToLabelAction() +{ +} + +void QmitkConvertMaskToLabelAction::Run( const QList &selectedNodes ) +{ + mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + assert(toolManager); + + mitk::DataNode* workingNode = toolManager->GetWorkingData(0); + if (!workingNode) + { + MITK_INFO << "There is no available segmentation. Please load or create one before using this tool."; + return; + } + + mitk::LabelSetImage* workingImage = dynamic_cast( workingNode->GetData() ); + assert(workingImage); + + foreach ( mitk::DataNode::Pointer maskNode, selectedNodes ) + { + if (maskNode) + { + mitk::Image* mask = dynamic_cast(maskNode->GetData() ); + if (!mask) continue; + + std::string name = maskNode->GetName(); + mitk::Color color; + mitk::ColorProperty::Pointer colorProp; + maskNode->GetProperty(colorProp,"color"); + if (colorProp.IsNull()) continue; + color = colorProp->GetValue(); + workingImage->GetLabelSet()->AddLabel(name,color); + //workingImage->AddLabelEvent.Send(); + + try + { + workingImage->MaskStamp( mask, false ); + } + catch ( mitk::Exception& e ) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + return; + } + + maskNode->SetVisibility(false); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + else + { + MITK_INFO << " a NULL node was selected"; + } + } +} + +void QmitkConvertMaskToLabelAction::SetSmoothed(bool /*smoothed*/) +{ + //not needed +} + +void QmitkConvertMaskToLabelAction::SetDecimated(bool /*decimated*/) +{ + //not needed +} + +void QmitkConvertMaskToLabelAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) +{ + //not needed +} + +void QmitkConvertMaskToLabelAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.h new file mode 100644 index 0000000000..cc89d03990 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertMaskToLabelAction.h @@ -0,0 +1,54 @@ +/*=================================================================== + +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 __QmitkConvertMaskToLabelAction_H_ +#define __QmitkConvertMaskToLabelAction_H_ + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" +#include "mitkImage.h" + +class QmitkStdMultiWidget; + +class MITK_QT_SEGMENTATION QmitkConvertMaskToLabelAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkConvertMaskToLabelAction(); + virtual ~QmitkConvertMaskToLabelAction(); + + //interface methods + void Run( const QList& selectedNodes ); + void SetDataStorage(mitk::DataStorage* dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart* functionality); + +protected: + +private: + + typedef QList NodeList; + +}; + +#endif // __QmitkConvertMaskToLabelAction_H_ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp new file mode 100644 index 0000000000..386189a80f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.cpp @@ -0,0 +1,106 @@ +/*=================================================================== + +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 "QmitkConvertSurfaceToLabelAction.h" + +#include "mitkRenderingManager.h" +#include "mitkLabelSetImage.h" +#include "mitkToolManagerProvider.h" + +//needed for qApp +#include +#include + +QmitkConvertSurfaceToLabelAction::QmitkConvertSurfaceToLabelAction() +{ +} + +QmitkConvertSurfaceToLabelAction::~QmitkConvertSurfaceToLabelAction() +{ +} + +void QmitkConvertSurfaceToLabelAction::Run( const QList &selectedNodes ) +{ + mitk::ToolManager::Pointer toolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + assert(toolManager); + + mitk::DataNode* workingNode = toolManager->GetWorkingData(0); + if (!workingNode) + { + MITK_INFO << "There is no available segmentation. Please load or create one before using this tool."; + return; + } + + mitk::LabelSetImage* workingImage = dynamic_cast( workingNode->GetData() ); + assert(workingImage); + + foreach ( mitk::DataNode::Pointer surfaceNode, selectedNodes ) + { + if (surfaceNode) + { + mitk::Surface* surface = dynamic_cast(surfaceNode->GetData() ); + if (!surface) continue; + + std::string name = surfaceNode->GetName(); + mitk::Color color; + mitk::ColorProperty::Pointer colorProp; + surfaceNode->GetProperty(colorProp,"color"); + if (colorProp.IsNull()) continue; + color = colorProp->GetValue(); + workingImage->GetLabelSet()->AddLabel(name,color); + //workingImage->AddLabelEvent.Send(); + + try + { + QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); + workingImage->SurfaceStamp( surface, false ); + QApplication::restoreOverrideCursor(); + } + catch ( mitk::Exception& e ) + { + QApplication::restoreOverrideCursor(); + MITK_ERROR << "Exception caught: " << e.GetDescription(); + return; + } + + surfaceNode->SetVisibility(false); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + } + else + { + MITK_INFO << " a NULL node was selected"; + } + } +} + +void QmitkConvertSurfaceToLabelAction::SetSmoothed(bool /*smoothed*/) +{ + //not needed +} + +void QmitkConvertSurfaceToLabelAction::SetDecimated(bool /*decimated*/) +{ + //not needed +} + +void QmitkConvertSurfaceToLabelAction::SetDataStorage(mitk::DataStorage* /*dataStorage*/) +{ + //not needed +} + +void QmitkConvertSurfaceToLabelAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.h new file mode 100644 index 0000000000..5cbde8ed99 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertSurfaceToLabelAction.h @@ -0,0 +1,54 @@ +/*=================================================================== + +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 __QmitkConvertSurfaceToLabelAction_H_ +#define __QmitkConvertSurfaceToLabelAction_H_ + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" +#include "mitkImage.h" + +class QmitkStdMultiWidget; + +class MITK_QT_SEGMENTATION QmitkConvertSurfaceToLabelAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkConvertSurfaceToLabelAction(); + virtual ~QmitkConvertSurfaceToLabelAction(); + + //interface methods + void Run( const QList& selectedNodes ); + void SetDataStorage(mitk::DataStorage* dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart* functionality); + +protected: + +private: + + typedef QList NodeList; + +}; + +#endif // __QmitkConvertSurfaceToLabelAction_H_ diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.cpp new file mode 100644 index 0000000000..d256668004 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.cpp @@ -0,0 +1,83 @@ +/*=================================================================== + +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 "QmitkConvertToMultiLabelSegmentationAction.h" + +#include "mitkLabelSetImage.h" +#include "mitkRenderingManager.h" + +//needed for qApp +#include + +QmitkConvertToMultiLabelSegmentationAction::QmitkConvertToMultiLabelSegmentationAction() +{ +} + +QmitkConvertToMultiLabelSegmentationAction::~QmitkConvertToMultiLabelSegmentationAction() +{ +} + +void QmitkConvertToMultiLabelSegmentationAction::Run( const QList &selectedNodes ) +{ + foreach ( mitk::DataNode::Pointer referenceNode, selectedNodes ) + { + if (referenceNode.IsNotNull()) + { + mitk::Image::Pointer referenceImage = dynamic_cast( referenceNode->GetData() ); + if (referenceImage.IsNull()) return; + + mitk::LabelSetImage::Pointer lsImage = mitk::LabelSetImage::New(); + try + { + lsImage->InitializeByLabeledImage(referenceImage); + } + catch (mitk::Exception &e) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + return; + } + if (m_DataStorage.IsNotNull()) + { + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + std::string newName = referenceNode->GetName(); + newName += "-labels"; + newNode->SetName(newName); + newNode->SetData(lsImage); + m_DataStorage->Add(newNode,referenceNode); + } + lsImage->Modified(); + } + } +} + +void QmitkConvertToMultiLabelSegmentationAction::SetDataStorage(mitk::DataStorage* dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkConvertToMultiLabelSegmentationAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} + +void QmitkConvertToMultiLabelSegmentationAction::SetSmoothed(bool smoothed) +{ + //not needed +} + +void QmitkConvertToMultiLabelSegmentationAction::SetDecimated(bool decimated) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.h new file mode 100644 index 0000000000..72fc44ca80 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkConvertToMultiLabelSegmentationAction.h @@ -0,0 +1,51 @@ +/*=================================================================== + +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 QMITK_ConvertToMultiLabelSegmentation_H +#define QMITK_ConvertToMultiLabelSegmentation_H + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" +//#include "mitkImage.h" + +class MITK_QT_SEGMENTATION QmitkConvertToMultiLabelSegmentationAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkConvertToMultiLabelSegmentationAction(); + virtual ~QmitkConvertToMultiLabelSegmentationAction(); + + //interface methods + virtual void Run( const QList& selectedNodes ); + virtual void SetDataStorage(mitk::DataStorage* dataStorage); + virtual void SetFunctionality(berry::QtViewPart* functionality); + virtual void SetSmoothed(bool smoothed); + virtual void SetDecimated(bool decimated); + +private: + + typedef QList NodeList; + + mitk::DataStorage::Pointer m_DataStorage; +}; + +#endif // QMITK_ConvertToMultiLabelSegmentation_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.cpp new file mode 100644 index 0000000000..bf09d77e7c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.cpp @@ -0,0 +1,84 @@ +/*=================================================================== + +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 "QmitkCreateMultiLabelPresetAction.h" +#include "mitkLabelSetImage.h" +#include "QMessageBox" +#include +#include "QFileDialog" +#include "mitkLabelSetImageWriter.h" +#include "tinyxml.h" + +QmitkCreateMultiLabelPresetAction::QmitkCreateMultiLabelPresetAction() +{ +} + +QmitkCreateMultiLabelPresetAction::~QmitkCreateMultiLabelPresetAction() +{ +} + +void QmitkCreateMultiLabelPresetAction::Run( const QList &selectedNodes ) +{ + foreach ( mitk::DataNode::Pointer referenceNode, selectedNodes ) + { + if (referenceNode.IsNotNull()) + { + + mitk::LabelSetImage::Pointer referenceImage = dynamic_cast( referenceNode->GetData() ); + assert(referenceImage); + + if(referenceImage->GetNumberOfLabels() <= 1) + { + QMessageBox::information(NULL, "Create LabelSetImage Preset", "Could not create a LabelSetImage preset.\nNo Labels defined!\n");\ + return; + } + + std::string sName = referenceNode->GetName(); + QString qName; + qName.sprintf("%s.lsetp",sName.c_str()); + QString filename = QFileDialog::getSaveFileName( NULL,"save file dialog",QString(),"LabelSet Preset(*.lsetp)"); + if ( filename.isEmpty() ) + return; + + bool wasSaved = mitk::LabelSetImageWriter::SaveLabelSetImagePreset(filename.toStdString(),referenceImage); + + if(!wasSaved) + { + QMessageBox::information(NULL, "Create LabelSetImage Preset", "Could not save a LabelSetImage preset as Xml.\n");\ + return; + } + } + } +} + +void QmitkCreateMultiLabelPresetAction::SetDataStorage(mitk::DataStorage* dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkCreateMultiLabelPresetAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} + +void QmitkCreateMultiLabelPresetAction::SetSmoothed(bool smoothed) +{ + //not needed +} + +void QmitkCreateMultiLabelPresetAction::SetDecimated(bool decimated) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.h new file mode 100644 index 0000000000..a9d9849c51 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelPresetAction.h @@ -0,0 +1,50 @@ +/*=================================================================== + +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 QMITK_QmitkCreateMultiLabelPresetAction_H +#define QMITK_QmitkCreateMultiLabelPresetAction_H + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" + +class MITK_QT_SEGMENTATION QmitkCreateMultiLabelPresetAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkCreateMultiLabelPresetAction(); + virtual ~QmitkCreateMultiLabelPresetAction(); + + //interface methods + virtual void Run( const QList& selectedNodes ); + virtual void SetDataStorage(mitk::DataStorage* dataStorage); + virtual void SetFunctionality(berry::QtViewPart* functionality); + virtual void SetSmoothed(bool smoothed); + virtual void SetDecimated(bool decimated); + +private: + + typedef QList NodeList; + + mitk::DataStorage::Pointer m_DataStorage; +}; + +#endif // QMITK_CreateMultiLabelSegmentation_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp new file mode 100644 index 0000000000..578c9699cb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.cpp @@ -0,0 +1,113 @@ +/*=================================================================== + +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 "QmitkCreateMultiLabelSegmentationAction.h" + +#include "mitkLabelSetImage.h" +#include "mitkRenderingManager.h" + +#include "QInputDialog" +#include "QMessageBox" + +#include "QmitkNewSegmentationDialog.h" +#include "QmitkMultiLabelSegmentationView.h" +#include "QmitkMultiLabelSegmentationOrganNamesHandling.cpp" +//needed for qApp +#include + +QmitkCreateMultiLabelSegmentationAction::QmitkCreateMultiLabelSegmentationAction() +{ +} + +QmitkCreateMultiLabelSegmentationAction::~QmitkCreateMultiLabelSegmentationAction() +{ +} + +void QmitkCreateMultiLabelSegmentationAction::Run( const QList &selectedNodes ) +{ + foreach ( mitk::DataNode::Pointer referenceNode, selectedNodes ) + { + if (referenceNode.IsNotNull()) + { + + mitk::Image* referenceImage = dynamic_cast( referenceNode->GetData() ); + assert(referenceImage); + + QString newName = QString::fromStdString(referenceNode->GetName()); + newName.append("-labels"); + + bool ok = false; + newName = QInputDialog::getText(NULL, "New Segmentation Session", "New name:", QLineEdit::Normal, newName, &ok); + if(!ok) return; + + mitk::LabelSetImage::Pointer workingImage = mitk::LabelSetImage::New(); + + try + { + workingImage->Initialize(referenceImage); + } + catch ( mitk::Exception& e ) + { + MITK_ERROR << "Exception caught: " << e.GetDescription(); + QMessageBox::information(NULL, "New Segmentation Session", "Could not create a new segmentation session.\n"); + return; + } + + mitk::DataNode::Pointer workingNode = mitk::DataNode::New(); + workingNode->SetData(workingImage); + workingNode->SetName(newName.toStdString()); + + // set additional image information + 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 (!m_DataStorage->Exists(workingNode)) + m_DataStorage->Add(workingNode, referenceNode); + + QmitkNewSegmentationDialog* dialog = new QmitkNewSegmentationDialog( ); + 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()); + + } + } +} + +void QmitkCreateMultiLabelSegmentationAction::SetDataStorage(mitk::DataStorage* dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkCreateMultiLabelSegmentationAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} + +void QmitkCreateMultiLabelSegmentationAction::SetSmoothed(bool smoothed) +{ + //not needed +} + +void QmitkCreateMultiLabelSegmentationAction::SetDecimated(bool decimated) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.h new file mode 100644 index 0000000000..7cc8b4e1d6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreateMultiLabelSegmentationAction.h @@ -0,0 +1,50 @@ +/*=================================================================== + +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 QMITK_CreateMultiLabelSegmentation_H +#define QMITK_CreateMultiLabelSegmentation_H + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" + +class MITK_QT_SEGMENTATION QmitkCreateMultiLabelSegmentationAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkCreateMultiLabelSegmentationAction(); + virtual ~QmitkCreateMultiLabelSegmentationAction(); + + //interface methods + virtual void Run( const QList& selectedNodes ); + virtual void SetDataStorage(mitk::DataStorage* dataStorage); + virtual void SetFunctionality(berry::QtViewPart* functionality); + virtual void SetSmoothed(bool smoothed); + virtual void SetDecimated(bool decimated); + +private: + + typedef QList NodeList; + + mitk::DataStorage::Pointer m_DataStorage; +}; + +#endif // QMITK_CreateMultiLabelSegmentation_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.cpp new file mode 100644 index 0000000000..3aa73a17b5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.cpp @@ -0,0 +1,171 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include "QmitkCreatePolygonModelAction.h" + +// MITK +#include +#include +#include +#include +#include + +#include +#include + +// Blueberry +#include +#include +#include + +using namespace berry; +using namespace mitk; +using namespace std; + +QmitkCreatePolygonModelAction::QmitkCreatePolygonModelAction() +{ +} + +QmitkCreatePolygonModelAction::~QmitkCreatePolygonModelAction() +{ +} + +void QmitkCreatePolygonModelAction::Run(const QList &selectedNodes) +{ + DataNode::Pointer selectedNode = selectedNodes[0]; + Image::Pointer image = dynamic_cast(selectedNode->GetData()); + + if (image.IsNull()) + return; + + try + { + if (!m_IsSmoothed) + { + ShowSegmentationAsSurface::Pointer surfaceFilter = ShowSegmentationAsSurface::New(); + + itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); + successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); + surfaceFilter->AddObserver(ResultAvailable(), successCommand); + + itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); + errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); + surfaceFilter->AddObserver(ProcessingError(), errorCommand); + + surfaceFilter->SetDataStorage(*m_DataStorage); + surfaceFilter->SetPointerParameter("Input", image); + surfaceFilter->SetPointerParameter("Group node", selectedNode); + surfaceFilter->SetParameter("Show result", true); + surfaceFilter->SetParameter("Sync visibility", false); + surfaceFilter->SetParameter("Smooth", false); + surfaceFilter->SetParameter("Apply median", false); + surfaceFilter->SetParameter("Median kernel size", 3u); + surfaceFilter->SetParameter("Gaussian SD", 1.5f); + surfaceFilter->SetParameter("Decimate mesh", m_IsDecimated); + surfaceFilter->SetParameter("Decimation rate", 0.8f); + + StatusBar::GetInstance()->DisplayText("Surface creation started in background..."); + + surfaceFilter->StartAlgorithm(); + } + else + { + ShowSegmentationAsSmoothedSurface::Pointer surfaceFilter = ShowSegmentationAsSmoothedSurface::New(); + + itk::SimpleMemberCommand::Pointer successCommand = itk::SimpleMemberCommand::New(); + successCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); + surfaceFilter->AddObserver(mitk::ResultAvailable(), successCommand); + + itk::SimpleMemberCommand::Pointer errorCommand = itk::SimpleMemberCommand::New(); + errorCommand->SetCallbackFunction(this, &QmitkCreatePolygonModelAction::OnSurfaceCalculationDone); + surfaceFilter->AddObserver(mitk::ProcessingError(), errorCommand); + + surfaceFilter->SetDataStorage(*m_DataStorage); + surfaceFilter->SetPointerParameter("Input", image); + surfaceFilter->SetPointerParameter("Group node", selectedNode); + + berry::IWorkbenchPart::Pointer activePart = + berry::PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage()->GetActivePart(); + mitk::IRenderWindowPart* renderPart = dynamic_cast(activePart.GetPointer()); + mitk::SliceNavigationController* timeNavController = 0; + if (renderPart != 0) + { + timeNavController = renderPart->GetRenderingManager()->GetTimeNavigationController(); + } + + int timeNr = timeNavController != 0 ? timeNavController->GetTime()->GetPos() : 0; + surfaceFilter->SetParameter("TimeNr", timeNr); + + IPreferencesService::Pointer prefService = Platform::GetServiceRegistry().GetServiceById(IPreferencesService::ID); + IPreferences::Pointer segPref = prefService->GetSystemPreferences()->Node("/org.mitk.views.segmentation"); + + bool smoothingHint = segPref->GetBool("smoothing hint", true); + ScalarType smoothing = segPref->GetDouble("smoothing value", 1.0); + ScalarType decimation = segPref->GetDouble("decimation rate", 0.5); + ScalarType closing = segPref->GetDouble("closing ratio", 0.0); + + if (smoothingHint) + { + smoothing = 0.0; + Vector3D spacing = image->GetGeometry()->GetSpacing(); + + for (Vector3D::Iterator iter = spacing.Begin(); iter != spacing.End(); ++iter) + smoothing = max(smoothing, *iter); + } + + surfaceFilter->SetParameter("Smoothing", smoothing); + surfaceFilter->SetParameter("Decimation", decimation); + surfaceFilter->SetParameter("Closing", closing); + + ProgressBar::GetInstance()->AddStepsToDo(8); + StatusBar::GetInstance()->DisplayText("Smoothed surface creation started in background..."); + + try { + surfaceFilter->StartAlgorithm(); + } catch (...) + { + MITK_ERROR<<"Error creating smoothed polygon model: Not enough memory!"; + } + } + } + catch(...) + { + MITK_ERROR << "Surface creation failed!"; + } +} + +void QmitkCreatePolygonModelAction::OnSurfaceCalculationDone() +{ + StatusBar::GetInstance()->Clear(); +} + +void QmitkCreatePolygonModelAction::SetDataStorage(DataStorage *dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkCreatePolygonModelAction::SetSmoothed(bool smoothed) +{ + m_IsSmoothed = smoothed; +} + +void QmitkCreatePolygonModelAction::SetDecimated(bool decimated) +{ + m_IsDecimated = decimated; +} + +void QmitkCreatePolygonModelAction::SetFunctionality(QtViewPart *) +{ +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.h new file mode 100644 index 0000000000..b7adfaaed8 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkCreatePolygonModelAction.h @@ -0,0 +1,57 @@ +/*=================================================================== + +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 QMITKCREATEPOLYGONMODELACTION_H +#define QMITKCREATEPOLYGONMODELACTION_H + +#include + +// Parent classes +#include +#include + +// Data members +#include + +class QmitkStdMultiWidget; + +class MITK_QT_SEGMENTATION QmitkCreatePolygonModelAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + QmitkCreatePolygonModelAction(); + ~QmitkCreatePolygonModelAction(); + + // IContextMenuAction + void Run(const QList &selectedNodes); + void SetDataStorage(mitk::DataStorage *dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart *functionality); + + void OnSurfaceCalculationDone(); + +private: + QmitkCreatePolygonModelAction(const QmitkCreatePolygonModelAction &); + QmitkCreatePolygonModelAction & operator=(const QmitkCreatePolygonModelAction &); + + mitk::DataStorage::Pointer m_DataStorage; + bool m_IsSmoothed; + bool m_IsDecimated; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.cpp new file mode 100644 index 0000000000..010f83431f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +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 "QmitkLoadMultiLabelPresetAction.h" + +#include "mitkLabelSetImage.h" +#include "mitkRenderingManager.h" +#include "mitkLabelSetImageIO.h" + +#include "QInputDialog" +#include "QMessageBox" +#include "QFileDialog" +#include "tinyxml.h" + +QmitkLoadMultiLabelPresetAction::QmitkLoadMultiLabelPresetAction() +{ +} + +QmitkLoadMultiLabelPresetAction::~QmitkLoadMultiLabelPresetAction() +{ +} + +void QmitkLoadMultiLabelPresetAction::Run( const QList &selectedNodes ) +{ + foreach ( mitk::DataNode::Pointer referenceNode, selectedNodes ) + { + + if (referenceNode.IsNull()) return; + + mitk::LabelSetImage::Pointer referenceImage = dynamic_cast( referenceNode->GetData() ); + assert(referenceImage); + + std::string sName = referenceNode->GetName(); + QString qName; + qName.sprintf("%s.lsetp",sName.c_str()); + QString filename = QFileDialog::getOpenFileName(NULL,"Load file",QString(),"LabelSet Preset(*.lsetp)"); + if ( filename.isEmpty() ) + return; + + mitk::LabelSetImageIO::LoadLabelSetImagePreset(filename.toStdString(), referenceImage); + } +} + +void QmitkLoadMultiLabelPresetAction::SetDataStorage(mitk::DataStorage* dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkLoadMultiLabelPresetAction::SetFunctionality(berry::QtViewPart* /*functionality*/) +{ + //not needed +} + +void QmitkLoadMultiLabelPresetAction::SetSmoothed(bool smoothed) +{ + //not needed +} + +void QmitkLoadMultiLabelPresetAction::SetDecimated(bool decimated) +{ + //not needed +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.h new file mode 100644 index 0000000000..eb888d6a6d --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkLoadMultiLabelPresetAction.h @@ -0,0 +1,50 @@ +/*=================================================================== + +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 QMITK_QmitkLoadMultiLabelPresetAction_H +#define QMITK_QmitkLoadMultiLabelPresetAction_H + +#include "mitkIContextMenuAction.h" + +#include "org_mitk_gui_qt_multilabelsegmentation_Export.h" + +#include "vector" +#include "mitkDataNode.h" + +class MITK_QT_SEGMENTATION QmitkLoadMultiLabelPresetAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + + QmitkLoadMultiLabelPresetAction(); + virtual ~QmitkLoadMultiLabelPresetAction(); + + //interface methods + virtual void Run( const QList& selectedNodes ); + virtual void SetDataStorage(mitk::DataStorage* dataStorage); + virtual void SetFunctionality(berry::QtViewPart* functionality); + virtual void SetSmoothed(bool smoothed); + virtual void SetDecimated(bool decimated); + +private: + + typedef QList NodeList; + + mitk::DataStorage::Pointer m_DataStorage; +}; + +#endif // QMITK_CreateMultiLabelSegmentation_H diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationControls.ui new file mode 100644 index 0000000000..138b48b36a --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationControls.ui @@ -0,0 +1,810 @@ + + + QmitkMultiLabelSegmentationControls + + + + 0 + 0 + 191 + 454 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + MS Shell Dlg 2 + 8 + 50 + false + false + false + false + + + + QmitkSegmentation + + + + + + + 0 + 0 + + + + Patient Image + + + + 2 + + + 4 + + + 2 + + + 4 + + + 2 + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + Segmentation + + + + 2 + + + 4 + + + 2 + + + 4 + + + 2 + + + + + + 0 + 0 + + + + + + + + + + + 3 + + + 4 + + + + + Create a new segmentation session + + + ... + + + + :/multilabelsegmentation/NewSegmentationSession_48x48.png:/multilabelsegmentation/NewSegmentationSession_48x48.png + + + + 28 + 28 + + + + N + + + true + + + + + + + Add a new label to the current segmentation session + + + ... + + + + :/multilabelsegmentation/NewLabel_48x48.png:/multilabelsegmentation/NewLabel_48x48.png + + + + 28 + 28 + + + + N + + + true + + + + + + + Qt::Horizontal + + + + 5 + 20 + + + + + + + + + 0 + 34 + + + + Show a table with all labels in the current segmentation session + + + >> + + + + 28 + 28 + + + + true + + + false + + + Qt::NoArrow + + + + + + + + + + 0 + 0 + + + + + 0 + 20 + + + + + + + + 2 + + + QLayout::SetDefaultConstraint + + + + + Disable the active tool + + + ... + + + + :/Qmitk/SegmentationInteractor_48x48.png:/Qmitk/SegmentationInteractor_48x48.png + + + + 28 + 28 + + + + false + + + true + + + + + + + Lock/Unlock exterior + + + ... + + + + :/Qmitk/UnlockExterior_48x48.png + :/Qmitk/LockExterior_48x48.png:/Qmitk/UnlockExterior_48x48.png + + + + 28 + 28 + + + + true + + + true + + + + + + + Add a layer to the current segmentation session + + + ... + + + + :/Qmitk/AddLayer_48x48.png:/Qmitk/AddLayer_48x48.png + + + + 28 + 28 + + + + true + + + + + + + Delete the active layer + + + ... + + + + :/Qmitk/DeleteLayer_48x48.png:/Qmitk/DeleteLayer_48x48.png + + + + 28 + 28 + + + + true + + + + + + + Change to the previous available layer + + + ... + + + + :/Qmitk/PreviousLayer_48x48.png:/Qmitk/PreviousLayer_48x48.png + + + + 28 + 28 + + + + true + + + + + + + + 0 + 0 + + + + + 50 + 30 + + + + + 40 + 30 + + + + + 12 + + + + Switch to a layer + + + + 0 + + + + + + + + Change to the next available layer + + + ... + + + + :/Qmitk/NextLayer_48x48.png:/Qmitk/NextLayer_48x48.png + + + + 28 + 28 + + + + true + + + + + + + Qt::Horizontal + + + + 0 + 20 + + + + + + + + + + + 0 + 0 + + + + QTabWidget::tab-bar { alignment: middle; } + + + 0 + + + true + + + false + + + + 2D Tools + + + + + + + 0 + 0 + + + + + 50 + false + + + + + + + + + 0 + 0 + + + + + 50 + false + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 3D Tools + + + + + + + 0 + 0 + + + + + 50 + false + + + + + + + + + 0 + 0 + + + + + 50 + false + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + 0 + 0 + + + + Interpolation + + + + 2 + + + QLayout::SetMinimumSize + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + Disabled + + + + + 2D Interpolation + + + + + 3D Interpolation + + + + + + + + + 0 + 0 + + + + 1 + + + + + 0 + 0 + + + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + false + + + + + + + + + + 0 + 0 + + + + + QLayout::SetMinimumSize + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + 50 + false + + + + + + + + + + 0 + 0 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + groupBox_4 + m_LabelSetWidget + groupBox + m_tw2DTools + m_gbInterpolation + verticalSpacer + + + + + QmitkDataStorageComboBox + QComboBox +
QmitkDataStorageComboBox.h
+
+ + QmitkToolSelectionBox + QWidget +
QmitkToolSelectionBox.h
+
+ + QmitkToolGUIArea + QWidget +
QmitkToolGUIArea.h
+
+ + QmitkLabelSetWidget + QWidget +
Qmitk/QmitkLabelSetWidget.h
+ 1 +
+ + QmitkSliceBasedInterpolatorWidget + QWidget +
QmitkSliceBasedInterpolatorWidget.h
+ 1 +
+ + QmitkSurfaceBasedInterpolatorWidget + QWidget +
QmitkSurfaceBasedInterpolatorWidget.h
+ 1 +
+
+ + QmitkToolReferenceDataSelectionBox.h + QmitkToolGUIArea.h + QmitkToolSelectionBox.h + + + + + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationOrganNamesHandling.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationOrganNamesHandling.cpp new file mode 100644 index 0000000000..574320c919 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationOrganNamesHandling.cpp @@ -0,0 +1,105 @@ +/*=================================================================== + +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 + +namespace mitk +{ +struct OrganNamesHandling +{ + static QStringList GetDefaultOrganColorString() + { + QStringList organColors; + + AppendToOrganList(organColors, "Ankle", 255, 255, 153); + AppendToOrganList(organColors, "Appendix", 161, 107, 54); + AppendToOrganList(organColors, "Blood vessels", 255, 49, 49); + AppendToOrganList(organColors, "Bone", 255, 255, 153); + AppendToOrganList(organColors, "Brain", 255, 156, 202); + AppendToOrganList(organColors, "Bronchial tree", 0, 160, 209); + AppendToOrganList(organColors, "Coccyx", 255, 255, 153); + AppendToOrganList(organColors, "Colon", 161, 107, 54); + AppendToOrganList(organColors, "Cyst", 150, 189, 228); + AppendToOrganList(organColors, "Elbow", 255, 255, 153); + AppendToOrganList(organColors, "Eye", 18, 7, 161); + AppendToOrganList(organColors, "Fallopian tube", 161, 19, 39); + AppendToOrganList(organColors, "Fat", 237, 255, 41); + AppendToOrganList(organColors, "Gall Bladder", 86, 127, 24); + AppendToOrganList(organColors, "Hand", 255, 222, 199); + AppendToOrganList(organColors, "Heart", 153, 0, 0); + AppendToOrganList(organColors, "Hip", 255, 255, 153); + AppendToOrganList(organColors, "Kidney", 250, 89, 0); + AppendToOrganList(organColors, "Knee", 255, 255, 153); + AppendToOrganList(organColors, "Larynx", 102, 0, 0); + AppendToOrganList(organColors, "Liver", 194, 142, 0); + AppendToOrganList(organColors, "Lung", 107, 220, 255); + AppendToOrganList(organColors, "Lymph node", 10, 250, 56); + AppendToOrganList(organColors, "Muscle", 102, 0, 0); + AppendToOrganList(organColors, "Nerve", 255, 234, 79); + AppendToOrganList(organColors, "Nose", 255, 222, 199); + AppendToOrganList(organColors, "Oesophagus", 102, 0, 0); + AppendToOrganList(organColors, "Ovaries", 234, 0, 117); + AppendToOrganList(organColors, "Pancreas", 249, 171, 61); + AppendToOrganList(organColors, "Pelvis", 255, 255, 153); + AppendToOrganList(organColors, "Penis", 255, 222, 199); + AppendToOrganList(organColors, "Pharynx", 102, 0, 0); + AppendToOrganList(organColors, "Prostate", 209, 163, 117); + AppendToOrganList(organColors, "Rectum", 161, 107, 54); + AppendToOrganList(organColors, "Sacrum", 255, 255, 153); + AppendToOrganList(organColors, "Seminal vesicle", 199, 232, 255); + AppendToOrganList(organColors, "Shoulder", 255, 255, 153); + AppendToOrganList(organColors, "Spinal cord", 255, 234, 79); + AppendToOrganList(organColors, "Spleen", 249, 108, 61); + AppendToOrganList(organColors, "Stomach", 161, 107, 54); + AppendToOrganList(organColors, "Teeth", 255, 252, 216); + AppendToOrganList(organColors, "Testicles", 199, 232, 255); + AppendToOrganList(organColors, "Thyroid", 255, 179, 184); + AppendToOrganList(organColors, "Tongue", 102, 0, 0); + AppendToOrganList(organColors, "Tumor", 147, 112, 17); + AppendToOrganList(organColors, "Urethra", 197, 204, 0); + AppendToOrganList(organColors, "Urinary bladder", 197, 204, 0); + AppendToOrganList(organColors, "Uterus", 161, 19, 39); + AppendToOrganList(organColors, "Vagina", 161, 19, 39); + AppendToOrganList(organColors, "Vertebra", 255, 255, 153); + AppendToOrganList(organColors, "Wrist", 255, 255, 153); + return organColors; + } + + static void UpdateOrganList(QStringList& organColors, const QString& organname, mitk::Color color) + { + QString listElement( organname + QColor(color.GetRed() * 255 , color.GetGreen() * 255 , color.GetBlue() * 255).name() ); + + // remove previous definition if necessary + int oldIndex = organColors.indexOf( QRegExp(QRegExp::escape(organname) + "#......", Qt::CaseInsensitive)); + if (oldIndex < 0 || organColors.at(oldIndex) != listElement ) + { + if (oldIndex >= 0) + { + organColors.removeAt( oldIndex ); + } + + // add colored organ name AND sort list + organColors.append( listElement ); + organColors.sort(); + } + } + + static void AppendToOrganList(QStringList& organColors, const QString& organname, int r, int g, int b) + { + organColors.append( organname + QColor(r, g, b).name() ); + } +}; +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp new file mode 100644 index 0000000000..62a81db415 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.cpp @@ -0,0 +1,895 @@ +/*=================================================================== + +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 "QmitkMultiLabelSegmentationView.h" + +// blueberry +#include +#include + +// mitk +#include "mitkLabelSetImage.h" +#include "mitkStatusBar.h" +#include "mitkApplicationCursor.h" +#include "mitkToolManagerProvider.h" +//#include "mitkSegmentationObjectFactory.h" +#include "mitkSegTool2D.h" +#include "mitkPlanePositionManager.h" +#include "mitkPluginActivator.h" +#include "mitkInteractionEventObserver.h" + +// Qmitk +#include "QmitkMultiLabelSegmentationOrganNamesHandling.cpp" +#include "QmitkRenderWindow.h" +#include "QmitkNewSegmentationDialog.h" + +// us +#include +#include +#include +#include +#include + +// Qt +#include +#include +#include +#include + +#include "tinyxml.h" + +#include + +const std::string QmitkMultiLabelSegmentationView::VIEW_ID = "org.mitk.views.multilabelsegmentation"; + +QmitkMultiLabelSegmentationView::QmitkMultiLabelSegmentationView() : + m_Parent(NULL), + m_IRenderWindowPart(NULL), + m_ReferenceNode(NULL), + m_WorkingNode(NULL), + m_ToolManager(NULL), + 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"))); + m_SegmentationPredicate->AddPredicate(mitk::NodePredicateProperty::New("visible", mitk::BoolProperty::New(true))); + + 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 isQbi = mitk::NodePredicateDataType::New("QBallImage"); + + mitk::NodePredicateOr::Pointer validImages = mitk::NodePredicateOr::New(); + validImages->AddPredicate(isImage); + validImages->AddPredicate(isDwi); + validImages->AddPredicate(isDti); + validImages->AddPredicate(isQbi); + + 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() +{ + m_ToolManager->ActivateTool(-1); + /* + todo: check this + m_Controls.m_SliceBasedInterpolatorWidget->EnableInterpolation(false); + ctkPluginContext* context = mitk::PluginActivator::getContext(); + ctkServiceReference ppmRef = context->getServiceReference(); + mitk::PlanePositionManagerService* service = context->getService(ppmRef); + service->RemoveAllPlanePositions(); + context->ungetService(ppmRef); +*/ + m_ToolManager->SetReferenceData(NULL); + m_ToolManager->SetWorkingData(NULL); + + m_ServiceRegistration.Unregister(); +} + +void QmitkMultiLabelSegmentationView::CreateQtPartControl(QWidget* parent) +{ + // setup the basic GUI of this view + m_Parent = parent; + m_Controls.setupUi(parent); + + m_Controls.m_cbReferenceNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.m_cbReferenceNodeSelector->SetPredicate(m_ReferencePredicate); + m_Controls.m_cbReferenceNodeSelector->SetAutoSelectNewItems(true); + + m_Controls.m_cbWorkingNodeSelector->SetDataStorage(this->GetDataStorage()); + m_Controls.m_cbWorkingNodeSelector->SetPredicate(m_SegmentationPredicate); + m_Controls.m_cbWorkingNodeSelector->SetAutoSelectNewItems(true); + + m_ToolManager = mitk::ToolManagerProvider::GetInstance()->GetToolManager(); + assert(m_ToolManager); + + m_ToolManager->SetDataStorage( *(this->GetDataStorage()) ); + m_ToolManager->InitializeTools(); + + //use the same ToolManager instance for our 3D Tools + m_Controls.m_ManualToolSelectionBox3D->SetToolManager(*m_ToolManager); + + m_Controls.m_LabelSetWidget->SetDataStorage(this->GetDataStorage()); + m_Controls.m_LabelSetWidget->SetOrganColors(mitk::OrganNamesHandling::GetDefaultOrganColorString()); + m_Controls.m_LabelSetWidget->hide(); + + m_Controls.m_SurfaceBasedInterpolatorWidget->SetDataStorage( *(this->GetDataStorage()) ); + m_Controls.m_SliceBasedInterpolatorWidget->SetDataStorage( *(this->GetDataStorage()) ); + + // all part of open source MITK + m_Controls.m_ManualToolSelectionBox2D->SetGenerateAccelerators(true); + m_Controls.m_ManualToolSelectionBox2D->SetToolGUIArea( m_Controls.m_ManualToolGUIContainer2D ); + //m_Controls.m_ManualToolSelectionBox2D->SetDisplayedToolGroups(); + m_Controls.m_ManualToolSelectionBox2D->SetDisplayedToolGroups("Add Subtract Fill Erase Paint Wipe 'Region Growing' FastMarching2D Correction 'Live Wire'");// todo: "Correction 'Live Wire'" + m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); + connect( m_Controls.m_ManualToolSelectionBox2D, SIGNAL(ToolSelected(int)), this, SLOT(OnManualTool2DSelected(int)) ); + + //setup 3D Tools + m_Controls.m_ManualToolSelectionBox3D->SetGenerateAccelerators(true); + m_Controls.m_ManualToolSelectionBox3D->SetToolGUIArea( m_Controls.m_ManualToolGUIContainer3D ); + //specify tools to be added to 3D Tool area + m_Controls.m_ManualToolSelectionBox3D->SetDisplayedToolGroups("Threshold 'Two Thresholds' 'Auto Threshold' 'Multiple Otsu'"); // todo add : FastMarching3D RegionGrowing Watershed + + m_Controls.m_ManualToolSelectionBox3D->SetLayoutColumns(2); + m_Controls.m_ManualToolSelectionBox3D->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); + + connect( m_Controls.m_cbReferenceNodeSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), + this, SLOT( OnReferenceSelectionChanged( const mitk::DataNode* ) ) ); + + connect( m_Controls.m_cbWorkingNodeSelector, SIGNAL( OnSelectionChanged( const mitk::DataNode* ) ), + this, SLOT( OnSegmentationSelectionChanged( const mitk::DataNode* ) ) ); + + 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(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()) ); + + connect( m_Controls.m_cbInterpolation, SIGNAL( activated (int) ), this, SLOT( OnInterpolationSelectionChanged(int) ) ); + + m_Controls.m_cbInterpolation->setCurrentIndex(0); + m_Controls.m_swInterpolation->hide(); + + this->OnReferenceSelectionChanged( m_Controls.m_cbReferenceNodeSelector->GetSelectedNode() ); + + 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); + // m_Controls.m_LabelSetWidget->SetRenderWindowPart(this->m_IRenderWindowPart); + } + + 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_btDeactivateTool, SIGNAL(clicked()), this, SLOT( OnDeactivateActiveTool()) ); + connect( m_Controls.m_cbActiveLayer, SIGNAL(currentIndexChanged(int)), this, SLOT( OnChangeLayer(int)) ); + + m_Controls.m_btAddLayer->hide(); + m_Controls.m_btDeactivateTool->hide(); + m_Controls.m_btDeleteLayer->hide(); + m_Controls.m_btLockExterior->hide(); + m_Controls.m_btNextLayer->hide(); + m_Controls.m_btPreviousLayer->hide(); + m_Controls.m_cbActiveLayer->hide(); + +} + +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::SetFocus () +{ +} + +bool QmitkMultiLabelSegmentationView::CheckForSameGeometry(const mitk::Image *image1, const mitk::Image *image2) const +{ + bool isSameGeometry(true); + + if (image1 && image2) + { + mitk::Geometry3D* geo1 = image1->GetGeometry(); + mitk::Geometry3D* geo2 = image2->GetGeometry(); + + isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetOrigin(), geo2->GetOrigin()); + isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(0), geo2->GetExtent(0)); + isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(1), geo2->GetExtent(1)); + isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetExtent(2), geo2->GetExtent(2)); + isSameGeometry = isSameGeometry && mitk::Equal(geo1->GetSpacing(), geo2->GetSpacing()); + isSameGeometry = isSameGeometry && mitk::MatrixEqualElementWise(geo1->GetIndexToWorldTransform()->GetMatrix(), geo2->GetIndexToWorldTransform()->GetMatrix()); + + return isSameGeometry; + } + else + { + return false; + } +} + +void QmitkMultiLabelSegmentationView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) +{ + if (m_IRenderWindowPart != renderWindowPart) + { + m_IRenderWindowPart = renderWindowPart; + m_Parent->setEnabled(true); + + QList controllers; + controllers.push_back(renderWindowPart->GetQmitkRenderWindow("axial")->GetSliceNavigationController()); + controllers.push_back(renderWindowPart->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()); + controllers.push_back(renderWindowPart->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()); + m_Controls.m_SliceBasedInterpolatorWidget->SetSliceNavigationControllers(controllers); + } +} + +void QmitkMultiLabelSegmentationView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* /*renderWindowPart*/) +{ + m_ToolManager->ActivateTool(-1); + m_IRenderWindowPart = 0; + m_Parent->setEnabled(false); +} + +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; + } +} + +void QmitkMultiLabelSegmentationView::UpdateControls() +{ + mitk::DataNode* referenceNode = m_ToolManager->GetReferenceData(0); + bool hasReferenceNode = referenceNode != NULL; + + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + bool hasWorkingNode = workingNode != NULL; + + m_Controls.m_pbNewSegmentationSession->setEnabled(false); + 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_btDeactivateTool->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_pbShowLabelTable->setChecked(false); + + m_Controls.m_ManualToolSelectionBox3D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); + m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible); + + if(hasReferenceNode) + { + m_Controls.m_pbNewSegmentationSession->setEnabled(true); + } + + if(hasWorkingNode) + { + m_Controls.m_pbNewLabel->setEnabled(true); + m_Controls.m_gbInterpolation->setEnabled(true); + m_Controls.m_SliceBasedInterpolatorWidget->setEnabled(true); + m_Controls.m_SurfaceBasedInterpolatorWidget->setEnabled(true); + m_Controls.m_btDeactivateTool->setEnabled(true); + m_Controls.m_LabelSetWidget->setEnabled(true); + m_Controls.m_btAddLayer->setEnabled(true); + + mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); + + int activeLayer = workingImage->GetActiveLayer(); + int numberOfLayers = workingImage->GetNumberOfLayers(); + + m_Controls.m_cbActiveLayer->blockSignals(true); + m_Controls.m_cbActiveLayer->clear(); + for (int lidx=0; lidxGetNumberOfLayers(); ++lidx) + m_Controls.m_cbActiveLayer->addItem(QString::number(lidx)); + m_Controls.m_cbActiveLayer->setCurrentIndex(activeLayer); + m_Controls.m_cbActiveLayer->blockSignals(false); + + m_Controls.m_btDeleteLayer->setEnabled(numberOfLayers>1); + m_Controls.m_cbActiveLayer->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)->GetLocked()); + + m_Controls.m_pbShowLabelTable->setChecked(workingImage->GetNumberOfLabels() > 1 /*1st is exterior*/); + + m_Controls.m_ManualToolSelectionBox2D->SetEnabledMode(QmitkToolSelectionBox::EnabledWithWorkingDataVisible); + } + + if(hasWorkingNode && hasReferenceNode) + { + int layer = -1; + referenceNode->GetIntProperty("layer", layer); + workingNode->SetIntProperty("layer", layer+1); + } + + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); +} + +void QmitkMultiLabelSegmentationView::OnNewSegmentationSession() +{ + mitk::DataNode* referenceNode = m_Controls.m_cbReferenceNodeSelector->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* referenceImage = dynamic_cast( referenceNode->GetData() ); + assert(referenceImage); + + 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(referenceImage); + } + 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 (!this->GetDataStorage()->Exists(workingNode)) + this->GetDataStorage()->Add(workingNode, referenceNode); + + m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); + + OnNewLabel(); + + m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); +} + +void QmitkMultiLabelSegmentationView::OnNewLabel() +{ + m_ToolManager->ActivateTool(-1); + + mitk::DataNode* workingNode = m_ToolManager->GetWorkingData(0); + assert(workingNode); + + mitk::LabelSetImage* workingImage = dynamic_cast(workingNode->GetData()); + assert(workingImage); + + 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(); +} + +void QmitkMultiLabelSegmentationView::OnShowLabelTable(bool value) +{ + if (value) + { + m_Controls.m_LabelSetWidget->show(); + m_Controls.m_btAddLayer->show(); + m_Controls.m_btDeactivateTool->show(); + m_Controls.m_btDeleteLayer->show(); + m_Controls.m_btLockExterior->show(); + m_Controls.m_btNextLayer->show(); + m_Controls.m_btPreviousLayer->show(); + m_Controls.m_cbActiveLayer->show(); + } + else + { + m_Controls.m_LabelSetWidget->hide(); + m_Controls.m_btAddLayer->hide(); + m_Controls.m_btDeactivateTool->hide(); + m_Controls.m_btDeleteLayer->hide(); + m_Controls.m_btLockExterior->hide(); + m_Controls.m_btNextLayer->hide(); + m_Controls.m_btPreviousLayer->hide(); + m_Controls.m_cbActiveLayer->hide(); + } +} + +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::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::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::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::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; + + int newLabelSetId = -1; + try + { + WaitCursorOn(); + newLabelSetId = 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; + } + + // Update controls and label set list for direct response + m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); + OnNewLabel(); + UpdateControls(); +} + +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::NodeAdded(const mitk::DataNode* node) +{ + /* + bool isHelperObject(false); + node->GetBoolProperty("helper object", isHelperObject); + if (isHelperObject) return; + + if (m_ReferenceNode.IsNotNull() && dynamic_cast(node->GetData())) + { + mitk::LabelSetImage* workingImage = dynamic_cast(node->GetData()); + + if (workingImage->GetNumberOfLabels() > 2) + m_Controls.m_LabelSetWidget->show(); + else + m_Controls.m_LabelSetWidget->hide(); + } + */ +} + +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 = NULL; + } +} + +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(); + } +} + +void QmitkMultiLabelSegmentationView::OnReferenceSelectionChanged( const mitk::DataNode* node ) +{ + m_ToolManager->ActivateTool(-1); + + m_ReferenceNode = const_cast(node); + + m_ToolManager->SetReferenceData(m_ReferenceNode); + + //check match of segmentation and reference image geometries + if (node && m_WorkingNode.IsNotNull()) + { + mitk::Image* workingImage = dynamic_cast(m_WorkingNode->GetData()); + assert(workingImage); + + mitk::Image* refImage = dynamic_cast(node->GetData()); + assert(refImage); + + if (!this->CheckForSameGeometry(refImage, workingImage)) + return; + } + + this->UpdateControls(); + //m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); +} + +void QmitkMultiLabelSegmentationView::OnEstablishLabelSetConnection() +{ + MITK_INFO << "Connection Established"; + 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); +} + + +void QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection() +{ + MITK_INFO << "Connection Lost"; + mitk::LabelSetImage* workingImage = dynamic_cast(m_WorkingNode->GetData()); + assert(workingImage); + + // 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); + +} + +void QmitkMultiLabelSegmentationView::OnSegmentationSelectionChanged(const mitk::DataNode *node) +{ + m_ToolManager->ActivateTool(-1); + + if(m_WorkingNode.IsNotNull()) + { + mitk::LabelSetImage* workingImage = dynamic_cast(m_WorkingNode->GetData()); + assert(workingImage); + + //Loose LabelSetConnections + OnLooseLabelSetConnection(); + + workingImage->BeforeChangeLayerEvent + -= mitk::MessageDelegate(this,&QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); + workingImage->AfterchangeLayerEvent + -= mitk::MessageDelegate(this,&QmitkMultiLabelSegmentationView::OnEstablishLabelSetConnection); + } + + m_WorkingNode = const_cast(node); + + if(m_WorkingNode.IsNotNull()) + { + mitk::LabelSetImage* workingImage = dynamic_cast(m_WorkingNode->GetData()); + assert(workingImage); + + //Establish LabelSetConnection + OnEstablishLabelSetConnection(); + + workingImage->BeforeChangeLayerEvent + += mitk::MessageDelegate(this,&QmitkMultiLabelSegmentationView::OnLooseLabelSetConnection); + workingImage->AfterchangeLayerEvent + += mitk::MessageDelegate(this,&QmitkMultiLabelSegmentationView::OnEstablishLabelSetConnection); + } + + m_ToolManager->SetWorkingData(m_WorkingNode); + + //check match of segmentation and reference image geometries + if (node && m_ReferenceNode.IsNotNull()) + { + mitk::Image* refImage = dynamic_cast(m_ReferenceNode->GetData()); + assert(refImage); + + mitk::Image* workingImage = dynamic_cast(node->GetData()); + assert(workingImage); + + if (!this->CheckForSameGeometry(refImage, workingImage)) + return; + } + + if (m_WorkingNode.IsNotNull()) + { + mitk::DataStorage::SetOfObjects::ConstPointer segNodes = this->GetDataStorage()->GetSubset(m_SegmentationPredicate); + for(mitk::DataStorage::SetOfObjects::const_iterator iter = segNodes->begin(); iter != segNodes->end(); ++iter) + { + mitk::DataNode* _segNode = *iter; + _segNode->SetVisibility(false); + } + + m_WorkingNode->SetVisibility(true); + } + + this->UpdateControls(); + + if (m_WorkingNode.IsNotNull()) + { + m_Controls.m_LabelSetWidget->ResetAllTableWidgetItems(); + } +} + +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(); + if (resource.IsValid()) + this->SetMouseCursor(resource, 0, 0); + } +} + +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 ) + { + mitk::ApplicationCursor::GetInstance()->PopCursor(); + } + + us::ModuleResourceStream cursor(resource, std::ios::binary); + mitk::ApplicationCursor::GetInstance()->PushCursor( cursor, hotspotX, hotspotY ); + m_MouseCursorSet = true; +} + +void QmitkMultiLabelSegmentationView::OnGoToLabel(const mitk::Point3D& pos) +{ + if (m_IRenderWindowPart) + m_IRenderWindowPart->SetSelectedPosition(pos); +} + +void QmitkMultiLabelSegmentationView::OnResetView() +{ + if (m_IRenderWindowPart) + m_IRenderWindowPart->ForceImmediateUpdate(); +} + +QString QmitkMultiLabelSegmentationView::GetLastFileOpenPath() +{ + return QString::fromStdString(this->GetPreferences()->Get("LastFileOpenPath", "")); +} + +void QmitkMultiLabelSegmentationView::SetLastFileOpenPath(const QString& path) +{ + this->GetPreferences()->Put("LastFileOpenPath", path.toStdString()); + this->GetPreferences()->Flush(); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.h new file mode 100644 index 0000000000..e96cc77024 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkMultiLabelSegmentationView.h @@ -0,0 +1,172 @@ +/*=================================================================== + +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 QmitkMultiLabelSegmentationView_h +#define QmitkMultiLabelSegmentationView_h + +#include +#include + +#include +#include +#include "mitkSegmentationInteractor.h" + +#include "ui_QmitkMultiLabelSegmentationControls.h" + + +class QmitkRenderWindow; + +/** + * \ingroup ToolManagerEtAl + * \ingroup org_mitk_gui_qt_multilabelsegmentation_internal + */ +class QmitkMultiLabelSegmentationView : public QmitkAbstractView, + public mitk::IRenderWindowPartListener, public berry::ISizeProvider +{ + Q_OBJECT + +public: + + static const std::string VIEW_ID; + + QmitkMultiLabelSegmentationView(); + virtual ~QmitkMultiLabelSegmentationView(); + + typedef std::map NodeTagMapType; + + // GUI setup + void CreateQtPartControl(QWidget* parent); + + virtual int GetSizeFlags(bool width); + virtual int ComputePreferredSize(bool width, int /*availableParallel*/, int /*availablePerpendicular*/, int preferredResult); + +protected slots: + + /// \brief reaction to the selection of a new patient (reference) image in the DataStorage combobox + void OnReferenceSelectionChanged(const mitk::DataNode* node); + + /// \brief reaction to the selection of a new Segmentation (working) image in the DataStorage combobox + void OnSegmentationSelectionChanged(const mitk::DataNode *node); + + /// \brief reaction to ... + void OnInterpolationSelectionChanged(int); + + /// \brief reaction to the selection of any 2D segmentation tool + void OnManualTool2DSelected(int id); + + /// \brief reaction to button "New Label" + void OnNewLabel(); + + /// \brief reaction to button "Show Label Table" + void OnShowLabelTable(bool value); + + /// \brief reaction to button "New Segmentation Session" + void OnNewSegmentationSession(); + + /// \brief reaction to signal "goToLabel" from labelset widget + void OnGoToLabel(const mitk::Point3D& pos); + + void OnResetView(); + + // reaction to the button "Add Layer" + void OnAddLayer(); + + // reaction to the button "Delete Layer" + void OnDeleteLayer(); + + // reaction to the button "Previous Layer" + void OnPreviousLayer(); + + // reaction to the button "Next Layer" + void OnNextLayer(); + + // reaction to the combobox change "Change Layer" + void OnChangeLayer(int); + + // reaction to the button "Deactive Active Tool" + void OnDeactivateActiveTool(); + + // reaction to the button "Lock exterior" + void OnLockExteriorToggled(bool); + +protected: + + void OnEstablishLabelSetConnection(); + void OnLooseLabelSetConnection(); + + void SetFocus(); + + void UpdateControls(); + + void RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart); + + void RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart); + + void ResetMouseCursor(); + + void SetMouseCursor(const us::ModuleResource, int hotspotX, int hotspotY ); + + void InitializeListeners(); + + /// \brief Checks if two images have the same size and geometry + bool CheckForSameGeometry(const mitk::Image *image1, const mitk::Image *image2) const; + + /// \brief Reimplemented from QmitkAbstractView + virtual void NodeAdded(const mitk::DataNode* node); + + /// \brief Reimplemented from QmitkAbstractView + virtual void NodeRemoved(const mitk::DataNode* node); + + QString GetLastFileOpenPath(); + + void SetLastFileOpenPath(const QString& path); + + // handling of a list of known (organ name, organ color) combination + // ATTENTION these methods are defined in QmitkSegmentationOrganNamesHandling.cpp +// QStringList GetDefaultOrganColorString(); +// void UpdateOrganList(QStringList& organColors, const QString& organname, mitk::Color colorname); +// void AppendToOrganList(QStringList& organColors, const QString& organname, int r, int g, int b); + + /// \brief the Qt parent of our GUI (NOT of this object) + QWidget* m_Parent; + + /// \brief Qt GUI file + Ui::QmitkMultiLabelSegmentationControls m_Controls; + + mitk::IRenderWindowPart* m_IRenderWindowPart; + + mitk::ToolManager* m_ToolManager; + + mitk::DataNode::Pointer m_ReferenceNode; + mitk::DataNode::Pointer m_WorkingNode; + + mitk::NodePredicateAnd::Pointer m_ReferencePredicate; + mitk::NodePredicateAnd::Pointer m_SegmentationPredicate; + + bool m_MouseCursorSet; + + mitk::SegmentationInteractor::Pointer m_Interactor; + + /** + * Reference to the service registration of the observer, + * it is needed to unregister the observer on unload. + */ + us::ServiceRegistration m_ServiceRegistration; + + +}; + +#endif // QmitkMultiLabelSegmentationView_h diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.cpp new file mode 100644 index 0000000000..7b0547a5e1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.cpp @@ -0,0 +1,117 @@ +/*=================================================================== + +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 "QmitkThresholdAction.h" + +// MITK +#include +#include +#include + +// Qt +#include +#include +#include +#include + +using namespace berry; +using namespace mitk; +using namespace std; + +QmitkThresholdAction::QmitkThresholdAction() +{ +} + +QmitkThresholdAction::~QmitkThresholdAction() +{ +} + +void QmitkThresholdAction::Run(const QList &selectedNodes) +{ + m_ThresholdingToolManager = ToolManager::New(m_DataStorage); + + m_ThresholdingToolManager->RegisterClient(); + + Tool *binaryThresholdTool = m_ThresholdingToolManager->GetToolById(m_ThresholdingToolManager->GetToolIdByToolType()); + if (binaryThresholdTool != NULL) + { + QmitkBinaryThresholdToolGUI *gui = dynamic_cast(binaryThresholdTool->GetGUI("Qmitk", "GUI").GetPointer()); + if (gui != NULL) + { + QDialog thresholdingDialog(QApplication::activeWindow(), Qt::Window | Qt::WindowStaysOnTopHint); + + thresholdingDialog.setWindowFlags(thresholdingDialog.windowFlags() & ~Qt::WindowMinimizeButtonHint); + + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel); + connect(buttonBox, SIGNAL(rejected()), &thresholdingDialog, SLOT(reject())); + connect(gui, SIGNAL(thresholdAccepted()), &thresholdingDialog, SLOT(reject())); + + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(3, 3, 3, 3); + + gui->SetTool(binaryThresholdTool); + gui->setParent(&thresholdingDialog); + + layout->addWidget(gui); + layout->addWidget(buttonBox); + + thresholdingDialog.setLayout(layout); + thresholdingDialog.setMinimumWidth(350); + + m_SelectedNode = selectedNodes[0]; + m_ThresholdingToolManager->SetReferenceData(selectedNodes[0]); + m_ThresholdingToolManager->ActivateTool(m_ThresholdingToolManager->GetToolIdByToolType()); + + m_ThresholdingToolManager->ActiveToolChanged += mitk::MessageDelegate(this, &QmitkThresholdAction::OnThresholdingToolManagerToolModified); + thresholdingDialog.exec(); + m_ThresholdingToolManager->ActiveToolChanged -= mitk::MessageDelegate(this, &QmitkThresholdAction::OnThresholdingToolManagerToolModified); + + m_ThresholdingToolManager->SetReferenceData(NULL); + m_ThresholdingToolManager->ActivateTool(-1); + m_SelectedNode = 0; + } + } + + m_ThresholdingToolManager->UnregisterClient(); +} + +void QmitkThresholdAction::OnThresholdingToolManagerToolModified() +{ + if (m_ThresholdingToolManager.IsNotNull()) + { + if (m_ThresholdingToolManager->GetActiveToolID() < 0) + { + m_ThresholdingToolManager->SetReferenceData(m_SelectedNode); + m_ThresholdingToolManager->ActivateTool(m_ThresholdingToolManager->GetToolIdByToolType()); + } + } +} + +void QmitkThresholdAction::SetDataStorage(DataStorage *dataStorage) +{ + m_DataStorage = dataStorage; +} + +void QmitkThresholdAction::SetSmoothed(bool) +{ +} + +void QmitkThresholdAction::SetDecimated(bool) +{ +} + +void QmitkThresholdAction::SetFunctionality(QtViewPart* /*functionality*/) +{ +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.h new file mode 100644 index 0000000000..53f3169acd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/QmitkThresholdAction.h @@ -0,0 +1,57 @@ +/*=================================================================== + +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 QMITKTHRESHOLDACTION_H +#define QMITKTHRESHOLDACTION_H + +#include + +// Parent classes +#include +#include + +// Data members +#include +#include + + +class MITK_QT_SEGMENTATION QmitkThresholdAction : public QObject, public mitk::IContextMenuAction +{ + Q_OBJECT + Q_INTERFACES(mitk::IContextMenuAction) + +public: + QmitkThresholdAction(); + ~QmitkThresholdAction(); + + // IContextMenuAction + void Run(const QList &selectedNodes); + void SetDataStorage(mitk::DataStorage *dataStorage); + void SetSmoothed(bool smoothed); + void SetDecimated(bool decimated); + void SetFunctionality(berry::QtViewPart *functionality); + + void OnThresholdingToolManagerToolModified(); + +private: + QmitkThresholdAction(const QmitkThresholdAction &); + QmitkThresholdAction & operator=(const QmitkThresholdAction &); + + mitk::DataNode::Pointer m_SelectedNode; + mitk::DataStorage::Pointer m_DataStorage; + mitk::ToolManager::Pointer m_ThresholdingToolManager; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp new file mode 100644 index 0000000000..ce40d43b5c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.cpp @@ -0,0 +1,144 @@ +/*=================================================================== + +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 "QmitkBooleanOperationsWidget.h" +#include "../../Common/QmitkDataSelectionWidget.h" +#include +#include +#include + +static const char* const HelpText = "Select two different masks above"; + +std::string GetPrefix(mitk::BooleanOperation::Type type) +{ + switch (type) + { + case mitk::BooleanOperation::Difference: + return "DifferenceFrom_"; + + case mitk::BooleanOperation::Intersection: + return "IntersectionWith_"; + + case mitk::BooleanOperation::Union: + return "UnionWith_"; + + default: + assert(false && "Unknown boolean operation type"); + return "UNKNOWN_BOOLEAN_OPERATION_WITH_"; + } +} + +void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent = NULL) +{ + mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); + + dataNode->SetBoolProperty("binary", true); + dataNode->SetName(name); + dataNode->SetData(segmentation); + + dataStorage->Add(dataNode, parent); +} + +QmitkBooleanOperationsWidget::QmitkBooleanOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) + : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +{ + m_Controls.setupUi(this); + + m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::MaskPredicate); + m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::MaskPredicate); + + m_Controls.dataSelectionWidget->SetHelpText(HelpText); + + connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); + connect(m_Controls.differenceButton, SIGNAL(clicked()), this, SLOT(OnDifferenceButtonClicked())); + connect(m_Controls.intersectionButton, SIGNAL(clicked()), this, SLOT(OnIntersectionButtonClicked())); + connect(m_Controls.unionButton, SIGNAL(clicked()), this, SLOT(OnUnionButtonClicked())); +} + +QmitkBooleanOperationsWidget::~QmitkBooleanOperationsWidget() +{ +} + +void QmitkBooleanOperationsWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) +{ + QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; + + mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0); + mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1); + + if (node0.IsNotNull() && node1.IsNotNull() && node0 != node1) + { + dataSelectionWidget->SetHelpText(""); + this->EnableButtons(); + } + else + { + dataSelectionWidget->SetHelpText(HelpText); + this->EnableButtons(false); + } +} + +void QmitkBooleanOperationsWidget::EnableButtons(bool enable) +{ + m_Controls.differenceButton->setEnabled(enable); + m_Controls.intersectionButton->setEnabled(enable); + m_Controls.unionButton->setEnabled(enable); +} + +void QmitkBooleanOperationsWidget::OnDifferenceButtonClicked() +{ + this->DoBooleanOperation(mitk::BooleanOperation::Difference); +} + +void QmitkBooleanOperationsWidget::OnIntersectionButtonClicked() +{ + this->DoBooleanOperation(mitk::BooleanOperation::Intersection); +} + +void QmitkBooleanOperationsWidget::OnUnionButtonClicked() +{ + this->DoBooleanOperation(mitk::BooleanOperation::Union); +} + +void QmitkBooleanOperationsWidget::DoBooleanOperation(mitk::BooleanOperation::Type type) +{ + mitk::SliceNavigationController* timeNavigationController = this->GetTimeNavigationController(); + assert(timeNavigationController != NULL); + + mitk::Image::Pointer segmentation0 = static_cast(m_Controls.dataSelectionWidget->GetSelection(0)->GetData()); + mitk::Image::Pointer segmentation1 = static_cast(m_Controls.dataSelectionWidget->GetSelection(1)->GetData()); + mitk::Image::Pointer result; + + try + { + mitk::BooleanOperation booleanOperation(type, segmentation0, segmentation1, timeNavigationController->GetTime()->GetPos()); + result = booleanOperation.GetResult(); + } + catch (const mitk::Exception &exception) + { + MITK_ERROR << "Boolean operation failed: " << exception.GetDescription(); + } + + assert(result.IsNotNull()); + + QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; + + AddToDataStorage( + dataSelectionWidget->GetDataStorage(), + result, + GetPrefix(type) + dataSelectionWidget->GetSelection(1)->GetName(), + dataSelectionWidget->GetSelection(0)); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h new file mode 100644 index 0000000000..321a6b28cf --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidget.h @@ -0,0 +1,45 @@ +/*=================================================================== + +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 QmitkBooleanOperationsWidget_h +#define QmitkBooleanOperationsWidget_h + +#include "../QmitkSegmentationUtilityWidget.h" +#include +#include + +class QmitkBooleanOperationsWidget : public QmitkSegmentationUtilityWidget +{ + Q_OBJECT + +public: + explicit QmitkBooleanOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); + ~QmitkBooleanOperationsWidget(); + +private slots: + void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); + void OnDifferenceButtonClicked(); + void OnIntersectionButtonClicked(); + void OnUnionButtonClicked(); + +private: + void EnableButtons(bool enable = true); + void DoBooleanOperation(mitk::BooleanOperation::Type type); + + Ui::QmitkBooleanOperationsWidgetControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui new file mode 100644 index 0000000000..bbd900d8b9 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/BooleanOperations/QmitkBooleanOperationsWidgetControls.ui @@ -0,0 +1,161 @@ + + + QmitkBooleanOperationsWidgetControls + + + + 0 + 0 + 251 + 300 + + + + + + + + + + + + false + + + + 0 + 0 + + + + Difference + + + + :/MultiLabelSegmentationUtilities/BooleanOperations/BooleanDifference_48x48.png:/MultiLabelSegmentationUtilities/BooleanOperations/BooleanDifference_48x48.png + + + + 24 + 24 + + + + false + + + false + + + Qt::ToolButtonTextUnderIcon + + + Qt::NoArrow + + + + + + + false + + + + 0 + 0 + + + + Intersection + + + + :/MultiLabelSegmentationUtilities/BooleanOperations/BooleanIntersection_48x48.png:/MultiLabelSegmentationUtilities/BooleanOperations/BooleanIntersection_48x48.png + + + + 24 + 24 + + + + false + + + false + + + Qt::ToolButtonTextUnderIcon + + + Qt::NoArrow + + + + + + + false + + + + 0 + 0 + + + + Union + + + + :/MultiLabelSegmentationUtilities/BooleanOperations/BooleanUnion_48x48.png:/MultiLabelSegmentationUtilities/BooleanOperations/BooleanUnion_48x48.png + + + + 24 + 24 + + + + false + + + false + + + Qt::ToolButtonTextUnderIcon + + + Qt::NoArrow + + + + + + + + + Qt::Vertical + + + + 20 + 273 + + + + + + + + + QmitkDataSelectionWidget + QWidget +
internal/Common/QmitkDataSelectionWidget.h
+
+
+ + + + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp new file mode 100644 index 0000000000..1719ef2db6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.cpp @@ -0,0 +1,340 @@ +/*=================================================================== + +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 "QmitkImageMaskingWidget.h" +#include "../../Common/QmitkDataSelectionWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const char* const HelpText = "Select a patient image and a mask"; + +QmitkImageMaskingWidget::QmitkImageMaskingWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) + : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +{ + m_Controls.setupUi(this); + + m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::ImagePredicate); + m_Controls.dataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::MaskPredicate); + m_Controls.dataSelectionWidget->SetHelpText(HelpText); + + mitk::IDataStorageService::Pointer service = + berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); + + assert(service.IsNotNull()); + + m_Controls.m_LabelSetWidget->SetDataStorage(service->GetDefaultDataStorage()->GetDataStorage()); + m_Controls.m_LabelSetWidget->setEnabled(true); + + m_Controls.m_MaskStampWidget->SetDataStorage(service->GetDefaultDataStorage()->GetDataStorage()); + + this->EnableButtons(false); + + connect (m_Controls.rbMaskImage, SIGNAL(toggled(bool)), this, SLOT(OnImageMaskingToggled(bool))); + connect (m_Controls.rbMaskSurface, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceMaskingToggled(bool))); + connect (m_Controls.btnMaskImage, SIGNAL(pressed()), this, SLOT(OnMaskImagePressed())); + + connect(m_Controls.dataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), + this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); + + if( m_Controls.dataSelectionWidget->GetSelection(0).IsNotNull() && + m_Controls.dataSelectionWidget->GetSelection(1).IsNotNull() ) + { + this->OnSelectionChanged( 0, m_Controls.dataSelectionWidget->GetSelection(0)); + } +} + +QmitkImageMaskingWidget::~QmitkImageMaskingWidget() +{ +} + +void QmitkImageMaskingWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) +{ + QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; + mitk::DataNode::Pointer node0 = dataSelectionWidget->GetSelection(0); + mitk::DataNode::Pointer node1 = dataSelectionWidget->GetSelection(1); + + if (node0.IsNull() || node1.IsNull() ) + { + if( m_Controls.rbMaskImage->isChecked() ) + { + dataSelectionWidget->SetHelpText(HelpText); + } + else + { + dataSelectionWidget->SetHelpText("Select a patient image and a surface"); + } + this->EnableButtons(false); + } + else + { + this->SelectionControl(index, selection); + } +} + +void QmitkImageMaskingWidget::SelectionControl(unsigned int index, const mitk::DataNode* selection) +{ + QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; + mitk::DataNode::Pointer node = dataSelectionWidget->GetSelection(index); + + //if Image-Masking is enabled, check if image-dimension of reference and binary image is identical + if( m_Controls.rbMaskImage->isChecked() ) + { + if( dataSelectionWidget->GetSelection(0) == dataSelectionWidget->GetSelection(1) ) + { + dataSelectionWidget->SetHelpText("Select two different images above"); + this->EnableButtons(false); + return; + } + /* + else if( node.IsNotNull() && selection ) + { + mitk::Image::Pointer referenceImage = dynamic_cast ( dataSelectionWidget->GetSelection(0)->GetData() ); + mitk::Image::Pointer maskImage = dynamic_cast ( dataSelectionWidget->GetSelection(1)->GetData() ); + + if( referenceImage->GetLargestPossibleRegion().GetSize() != maskImage->GetLargestPossibleRegion().GetSize() ) + { + dataSelectionWidget->SetHelpText("Different image sizes cannot be masked"); + this->EnableButtons(false); + return; + } + } + + else + { + dataSelectionWidget->SetHelpText(HelpText); + return; + } + */ + } + + dataSelectionWidget->SetHelpText(""); + this->EnableButtons(); +} + +void QmitkImageMaskingWidget::EnableButtons(bool enable) +{ + m_Controls.btnMaskImage->setEnabled(enable); +} + +void QmitkImageMaskingWidget::OnImageMaskingToggled(bool status) +{ + if (status) + { + m_Controls.dataSelectionWidget->SetHelpText("Select a patient image and a mask"); + m_Controls.dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::MaskPredicate); + } +} + +void QmitkImageMaskingWidget::OnSurfaceMaskingToggled(bool status) +{ + if (status) + { + m_Controls.dataSelectionWidget->SetHelpText("Select a patient image and a surface"); + m_Controls.dataSelectionWidget->SetPredicate(1, QmitkDataSelectionWidget::SurfacePredicate); + } +} + + +void QmitkImageMaskingWidget::OnMaskImagePressed() +{ + //Disable Buttons during calculation and initialize Progressbar + this->EnableButtons(false); + mitk::ProgressBar::GetInstance()->AddStepsToDo(4); + mitk::ProgressBar::GetInstance()->Progress(); + + QmitkDataSelectionWidget* dataSelectionWidget = m_Controls.dataSelectionWidget; + + //create result image, get mask node and reference image + mitk::Image::Pointer resultImage(0); + mitk::DataNode::Pointer maskingNode = dataSelectionWidget->GetSelection(1); + mitk::Image::Pointer referenceImage = static_cast(dataSelectionWidget->GetSelection(0)->GetData()); + + if(referenceImage.IsNull() || maskingNode.IsNull() ) + { + MITK_ERROR << "Selection does not contain an image"; + QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain an image", QMessageBox::Ok ); + m_Controls.btnMaskImage->setEnabled(true); + return; + } + + //Do Image-Masking + if (m_Controls.rbMaskImage->isChecked()) + { + mitk::ProgressBar::GetInstance()->Progress(); + + mitk::Image::Pointer maskImage = dynamic_cast ( maskingNode->GetData() ); + + if( referenceImage->GetLargestPossibleRegion().GetSize() != maskImage->GetLargestPossibleRegion().GetSize() ) + { + mitk::PadImageFilter::Pointer padImageFilter = mitk::PadImageFilter::New(); + padImageFilter->SetInput(0, maskImage); + padImageFilter->SetInput(1, referenceImage); + padImageFilter->SetPadConstant(0); + padImageFilter->SetBinaryFilter(false); + padImageFilter->SetLowerThreshold(0); + padImageFilter->SetUpperThreshold(1); + + MITK_INFO << "Padding mask ..."; + + padImageFilter->Update(); + + maskImage = padImageFilter->GetOutput(); + } + + if(maskImage.IsNull() ) + { + MITK_ERROR << "Selection does not contain a binary image"; + QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a binary image", QMessageBox::Ok ); + this->EnableButtons(); + return; + } + + resultImage = this->MaskImage( referenceImage, maskImage ); + } + + //Do Surface-Masking + else + { + mitk::ProgressBar::GetInstance()->Progress(); + + //1. convert surface to image + mitk::Surface::Pointer surface = dynamic_cast ( maskingNode->GetData() ); + + //TODO Get 3D Surface of current time step + + if(surface.IsNull()) + { + MITK_ERROR << "Selection does not contain a surface"; + QMessageBox::information( this, "Image and Surface Masking", "Selection does not contain a surface", QMessageBox::Ok ); + this->EnableButtons(); + return; + } + + mitk::Image::Pointer maskImage = this->ConvertSurfaceToImage( referenceImage, surface ); + + //2. mask reference image with mask image + if(maskImage.IsNotNull() && + referenceImage->GetLargestPossibleRegion().GetSize() == maskImage->GetLargestPossibleRegion().GetSize() ) + { + resultImage = this->MaskImage( referenceImage, maskImage ); + } + } + + mitk::ProgressBar::GetInstance()->Progress(); + + if( resultImage.IsNull() ) + { + MITK_ERROR << "Masking failed"; + QMessageBox::information( this, "Image and Surface Masking", "Masking failed. For more information please see logging window.", QMessageBox::Ok ); + this->EnableButtons(); + mitk::ProgressBar::GetInstance()->Progress(4); + return; + } + + //Add result to data storage + this->AddToDataStorage( + dataSelectionWidget->GetDataStorage(), + resultImage, + dataSelectionWidget->GetSelection(0)->GetName() + "_" + dataSelectionWidget->GetSelection(1)->GetName(), + dataSelectionWidget->GetSelection(0)); + + this->EnableButtons(); + + mitk::ProgressBar::GetInstance()->Progress(); +} + +mitk::Image::Pointer QmitkImageMaskingWidget::MaskImage(mitk::Image::Pointer referenceImage, mitk::Image::Pointer maskImage ) +{ + mitk::Image::Pointer resultImage(0); + + mitk::MaskImageFilter::Pointer maskFilter = mitk::MaskImageFilter::New(); + maskFilter->SetInput( referenceImage ); + maskFilter->SetMask( maskImage ); + if ( m_Controls.m_chkMakeOutputBinary->isChecked() ) + { + maskFilter->SetInsideValue(1.0); + maskFilter->SetOutsideValue(0.0); + maskFilter->SetOverrideOutsideValue(true); + maskFilter->SetOverrideInsideValue(true); + } + + maskFilter->SetOverrideOutsideValue( m_Controls.m_chkOverwriteBackground->isChecked() ); + maskFilter->SetOverrideInsideValue( m_Controls.m_chkOverwriteForeground->isChecked() ); + maskFilter->SetInsideValue( m_Controls.m_leForegroundValue->text().toFloat() );//referenceImage->GetStatistics()->GetScalarValueMin() ); + maskFilter->SetOutsideValue( m_Controls.m_leBackgroundValue->text().toFloat() );//referenceImage->GetStatistics()->GetScalarValueMin() ); + + try + { + maskFilter->Update(); + } + catch(itk::ExceptionObject& excpt) + { + MITK_ERROR << excpt.GetDescription(); + return 0; + } + + resultImage = maskFilter->GetOutput(); + + return resultImage; +} + +mitk::Image::Pointer QmitkImageMaskingWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ) +{ + mitk::ProgressBar::GetInstance()->AddStepsToDo(2); + mitk::ProgressBar::GetInstance()->Progress(); + + mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New(); + surfaceToImageFilter->MakeOutputBinaryOn(); + surfaceToImageFilter->SetInput(surface); + surfaceToImageFilter->SetImage(image); + try + { + surfaceToImageFilter->Update(); + } + catch(itk::ExceptionObject& excpt) + { + MITK_ERROR << excpt.GetDescription(); + return 0; + } + + mitk::ProgressBar::GetInstance()->Progress(); + mitk::Image::Pointer resultImage = mitk::Image::New(); + resultImage = surfaceToImageFilter->GetOutput(); + + return resultImage; +} + +void QmitkImageMaskingWidget::AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, const std::string& name, mitk::DataNode::Pointer parent ) +{ + mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); + + dataNode->SetName(name); + dataNode->SetData(segmentation); + + dataStorage->Add(dataNode, parent); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h new file mode 100644 index 0000000000..e370cefa40 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidget.h @@ -0,0 +1,80 @@ +/*=================================================================== + +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 QmitkImageMaskingWidget_h +#define QmitkImageMaskingWidget_h + +#include "../QmitkSegmentationUtilityWidget.h" +#include + +#include + +/*! + \brief QmitkImageMaskingWidget + + Tool masks an image with a binary image or a surface. The Method requires + an image and a binary image mask or a surface. The input image and the binary + image mask must be of the same size. Masking with a surface creates first a + binary image of the surface and then use this for the masking of the input image. +*/ +class QmitkImageMaskingWidget : public QmitkSegmentationUtilityWidget +{ + Q_OBJECT + +public: + + /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ + explicit QmitkImageMaskingWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); + + /** @brief Defaul destructor. */ + ~QmitkImageMaskingWidget(); + +private slots: + + /** @brief This slot is called if the selection in the workbench is changed. */ + void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); + + /** @brief This slot is called if user activates the radio button for masking an image with a binary image mask. */ + void OnImageMaskingToggled(bool); + + /** @brief This slot is called if user activates the radio button for masking an image with a surface. */ + void OnSurfaceMaskingToggled(bool); + + /** @brief This slot is called if user activates the button to mask an image. */ + void OnMaskImagePressed(); + +private: + + /** @brief Check if selections is valid. */ + void SelectionControl( unsigned int index, const mitk::DataNode* selection); + + /** @brief Enable buttons if data selction is valid. */ + void EnableButtons(bool enable = true); + + /** @brief Mask an image with a given binary mask. Note that the input image and the mask image must be of the same size. */ + mitk::Image::Pointer MaskImage(mitk::Image::Pointer referenceImage, mitk::Image::Pointer maskImage ); + + /** @brief Convert a surface into an binary image. */ + mitk::Image::Pointer ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ); + + /** @brief Adds a new data object to the DataStorage.*/ + void AddToDataStorage(mitk::DataStorage::Pointer dataStorage, mitk::Image::Pointer segmentation, + const std::string& name, mitk::DataNode::Pointer parent = NULL); + + Ui::QmitkImageMaskingWidgetControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui new file mode 100644 index 0000000000..f2efb8aaf6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/ImageMasking/QmitkImageMaskingWidgetControls.ui @@ -0,0 +1,277 @@ + + + QmitkImageMaskingWidgetControls + + + + 0 + 0 + 197 + 420 + + + + + 2 + + + 4 + + + + + 1 + + + + Masks + + + + 3 + + + 4 + + + + + + 0 + 10 + + + + + + + + Masking Mode + + + + + + Image Masking + + + true + + + + + + + Surface Masking + + + + + + + + + + Mask + + + + + + + make output binary + + + + + + + overwrite foreground + + + + + + + overwrite background + + + + + + + + + Background Value: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 0.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Foreground Value: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 1.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Vertical + + + + 20 + 8 + + + + + + + + + Labels + + + + 3 + + + 4 + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + + + + + + + Qt::Vertical + + + + 20 + 113 + + + + + + + + + + + + + QmitkDataSelectionWidget + QWidget +
internal/Common/QmitkDataSelectionWidget.h
+
+ + QmitkLabelSetWidget + QWidget +
Qmitk/QmitkLabelSetWidget.h
+ 1 +
+ + QmitkMaskStampWidget + QWidget +
QmitkMaskStampWidget.h
+ 1 +
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp new file mode 100644 index 0000000000..a2bad6bc21 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.cpp @@ -0,0 +1,253 @@ +/*=================================================================== + +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 "QmitkMorphologicalOperationsWidget.h" +#include +#include +#include +#include +#include + +static const char* const HelpText = "Select a mask above"; + +QmitkMorphologicalOperationsWidget::QmitkMorphologicalOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) + : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +{ + m_Controls.setupUi(this); + + m_Controls.m_DataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::MaskPredicate); + m_Controls.m_DataSelectionWidget->SetHelpText(HelpText); + + mitk::IDataStorageService::Pointer service = + berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); + + assert(service.IsNotNull()); + + m_Controls.m_LabelSetWidget->SetDataStorage(service->GetDefaultDataStorage()->GetDataStorage()); + m_Controls.m_LabelSetWidget->setEnabled(true); + + + m_Controls.m_ToolSelectionBox->SetGenerateAccelerators(true); + m_Controls.m_ToolSelectionBox->SetToolGUIArea( m_Controls.m_ToolGUIContainer ); + m_Controls.m_ToolSelectionBox->SetEnabledMode( QmitkToolSelectionBox::EnabledWithReferenceAndWorkingDataVisible ); + m_Controls.m_ToolSelectionBox->SetDisplayedToolGroups("Median Dilate Erode Open Close 'Fill Holes' 'Keep N Largest' 'Split' 'Region Selector'"); +// m_Controls.m_LabelSetWidget->SetDataStorage( *(this->GetDataStorage()) ); + + connect(m_Controls.btnClosing, SIGNAL(clicked()), this, SLOT(OnClosingButtonClicked())); + connect(m_Controls.btnOpening, SIGNAL(clicked()), this, SLOT(OnOpeningButtonClicked())); + connect(m_Controls.btnDilatation, SIGNAL(clicked()), this, SLOT(OnDilatationButtonClicked())); + connect(m_Controls.btnErosion, SIGNAL(clicked()), this, SLOT(OnErosionButtonClicked())); + connect(m_Controls.btnFillHoles, SIGNAL(clicked()), this, SLOT(OnFillHolesButtonClicked())); + connect(m_Controls.radioButtonMorphoCross, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked())); + connect(m_Controls.radioButtonMorphoBall, SIGNAL(clicked()), this, SLOT(OnRadioButtonsClicked())); + connect(m_Controls.m_DataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); + + if (m_Controls.m_DataSelectionWidget->GetSelection(0).IsNotNull()) + this->OnSelectionChanged(0, m_Controls.m_DataSelectionWidget->GetSelection(0)); +} + +QmitkMorphologicalOperationsWidget::~QmitkMorphologicalOperationsWidget() +{ +} + +void QmitkMorphologicalOperationsWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) +{ + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + + if (node.IsNotNull()) + { + m_Controls.m_DataSelectionWidget->SetHelpText(""); + this->EnableButtons(true); + } + else + { + m_Controls.m_DataSelectionWidget->SetHelpText(HelpText); + this->EnableButtons(false); + } +} + +void QmitkMorphologicalOperationsWidget::EnableButtons(bool enable) +{ + m_Controls.btnClosing->setEnabled(enable); + m_Controls.btnDilatation->setEnabled(enable); + m_Controls.btnErosion->setEnabled(enable); + m_Controls.btnFillHoles->setEnabled(enable); + m_Controls.btnOpening->setEnabled(enable); +} + +void QmitkMorphologicalOperationsWidget::OnRadioButtonsClicked() +{ + bool enable = m_Controls.radioButtonMorphoBall->isChecked(); + + m_Controls.sliderMorphFactor->setEnabled(enable); + m_Controls.spinBoxMorphFactor->setEnabled(enable); +} + +void QmitkMorphologicalOperationsWidget::OnClosingButtonClicked() +{ + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + mitk::Image::Pointer image = static_cast(node->GetData()); + bool ball = m_Controls.radioButtonMorphoBall->isChecked(); + + mitk::MorphologicalOperations::StructuralElementType structuralElement = ball + ? mitk::MorphologicalOperations::Ball + : mitk::MorphologicalOperations::Cross; + + try + { + mitk::MorphologicalOperations::Closing(image, m_Controls.spinBoxMorphFactor->value(), structuralElement); + } + catch (const itk::ExceptionObject& exception) + { + MITK_WARN << "Exception caught: " << exception.GetDescription(); + + QApplication::restoreOverrideCursor(); + return; + } + + node->SetData(image); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + QApplication::restoreOverrideCursor(); +} + +void QmitkMorphologicalOperationsWidget::OnOpeningButtonClicked() +{ + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + mitk::Image::Pointer image = static_cast(node->GetData()); + bool ball = m_Controls.radioButtonMorphoBall->isChecked(); + + mitk::MorphologicalOperations::StructuralElementType structuralElement = ball + ? mitk::MorphologicalOperations::Ball + : mitk::MorphologicalOperations::Cross; + + try + { + mitk::MorphologicalOperations::Opening(image, m_Controls.spinBoxMorphFactor->value(), structuralElement); + } + catch (const itk::ExceptionObject& exception) + { + MITK_WARN << "Exception caught: " << exception.GetDescription(); + + QApplication::restoreOverrideCursor(); + return; + } + + node->SetData(image); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + QApplication::restoreOverrideCursor(); +} + +void QmitkMorphologicalOperationsWidget::OnDilatationButtonClicked() +{ + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + mitk::Image::Pointer image = static_cast(node->GetData()); + bool ball = m_Controls.radioButtonMorphoBall->isChecked(); + + mitk::MorphologicalOperations::StructuralElementType structuralElement = ball + ? mitk::MorphologicalOperations::Ball + : mitk::MorphologicalOperations::Cross; + + try + { + mitk::MorphologicalOperations::Dilate(image, m_Controls.spinBoxMorphFactor->value(), structuralElement); + } + catch (const itk::ExceptionObject& exception) + { + MITK_WARN << "Exception caught: " << exception.GetDescription(); + + QApplication::restoreOverrideCursor(); + return; + } + + node->SetData(image); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + QApplication::restoreOverrideCursor(); +} + +void QmitkMorphologicalOperationsWidget::OnErosionButtonClicked() +{ + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + mitk::Image::Pointer image = static_cast(node->GetData()); + bool ball = m_Controls.radioButtonMorphoBall->isChecked(); + + mitk::MorphologicalOperations::StructuralElementType structuralElement = ball + ? mitk::MorphologicalOperations::Ball + : mitk::MorphologicalOperations::Cross; + + try + { + mitk::MorphologicalOperations::Erode(image, m_Controls.spinBoxMorphFactor->value(), structuralElement); + } + catch (const itk::ExceptionObject& exception) + { + MITK_WARN << "Exception caught: " << exception.GetDescription(); + + QApplication::restoreOverrideCursor(); + return; + } + + node->SetData(image); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + QApplication::restoreOverrideCursor(); +} + +void QmitkMorphologicalOperationsWidget::OnFillHolesButtonClicked() +{ + QApplication::setOverrideCursor(QCursor(Qt::BusyCursor)); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + QmitkDataSelectionWidget* m_DataSelectionWidget = m_Controls.m_DataSelectionWidget; + mitk::DataNode::Pointer node = m_DataSelectionWidget->GetSelection(0); + mitk::Image::Pointer image = static_cast(node->GetData()); + + try + { + mitk::MorphologicalOperations::FillHoles(image); + } + catch (const itk::ExceptionObject& exception) + { + MITK_WARN << "Exception caught: " << exception.GetDescription(); + + QApplication::restoreOverrideCursor(); + return; + } + + node->SetData(image); + + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + QApplication::restoreOverrideCursor(); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h new file mode 100644 index 0000000000..01fe747748 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidget.h @@ -0,0 +1,49 @@ +/*=================================================================== + +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 QmitkMorphologicalOperationsWidget_h +#define QmitkMorphologicalOperationsWidget_h + +#include "../QmitkSegmentationUtilityWidget.h" +#include + +/** \brief GUI class for morphological segmentation tools. + */ +class QmitkMorphologicalOperationsWidget : public QmitkSegmentationUtilityWidget +{ + Q_OBJECT + +public: + explicit QmitkMorphologicalOperationsWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); + ~QmitkMorphologicalOperationsWidget(); + +public slots: + void OnClosingButtonClicked(); + void OnOpeningButtonClicked(); + void OnDilatationButtonClicked(); + void OnErosionButtonClicked(); + void OnFillHolesButtonClicked(); + void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); + void OnRadioButtonsClicked(); + +protected: + void EnableButtons(bool enable); + +private: + Ui::QmitkMorphologicalOperationsWidgetControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui new file mode 100644 index 0000000000..7f33ec3a47 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/MorphologicalOperations/QmitkMorphologicalOperationsWidgetControls.ui @@ -0,0 +1,429 @@ + + + QmitkMorphologicalOperationsWidgetControls + + + + 0 + 0 + 236 + 507 + + + + + 0 + 0 + + + + Form + + + + + + + 0 + 0 + + + + 0 + + + + Masks + + + + 3 + + + 4 + + + + + + + + Structuring Element + + + + + + Ball + + + true + + + + + + + Cross + + + + + + + + + + + + Radius + + + + + + + 1 + + + 20 + + + 1 + + + Qt::Horizontal + + + + + + + 1 + + + 20 + + + + + + + + + + + false + + + + 0 + 0 + + + + Dilatation + + + + :/SegmentationUtilities/MorphologicalOperations/Dilate_48x48.png:/SegmentationUtilities/MorphologicalOperations/Dilate_48x48.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + Globally fills holes in segmentation (radius not required) + + + Fill Holes + + + + :/SegmentationUtilities/MorphologicalOperations/FillHoles_48x48.png:/SegmentationUtilities/MorphologicalOperations/FillHoles_48x48.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + Erosion + + + + :/SegmentationUtilities/MorphologicalOperations/Erode_48x48.png:/SegmentationUtilities/MorphologicalOperations/Erode_48x48.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + Closing + + + + :/SegmentationUtilities/MorphologicalOperations/Closing_48x48.png:/SegmentationUtilities/MorphologicalOperations/Closing_48x48.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + false + + + + 0 + 0 + + + + Opening + + + + :/SegmentationUtilities/MorphologicalOperations/Opening_48x48.png:/SegmentationUtilities/MorphologicalOperations/Opening_48x48.png + + + + 32 + 32 + + + + Qt::ToolButtonTextUnderIcon + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Labels + + + + 3 + + + 4 + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + + + + + 0 + 0 + + + + + 15 + 0 + + + + + 50 + false + + + + + + + + + 0 + 0 + + + + + 0 + 15 + + + + + 50 + false + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + QmitkDataSelectionWidget + QWidget +
internal/Common/QmitkDataSelectionWidget.h
+ 1 +
+ + QmitkToolSelectionBox + QWidget +
QmitkToolSelectionBox.h
+
+ + QmitkToolGUIArea + QWidget +
QmitkToolGUIArea.h
+
+ + QmitkLabelSetWidget + QWidget +
Qmitk/QmitkLabelSetWidget.h
+ 1 +
+
+ + + + + + sliderMorphFactor + valueChanged(int) + spinBoxMorphFactor + setValue(int) + + + 240 + 27 + + + 766 + 36 + + + + + spinBoxMorphFactor + valueChanged(int) + sliderMorphFactor + setValue(int) + + + 784 + 38 + + + 657 + 38 + + + + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.cpp new file mode 100644 index 0000000000..ff3a1374f2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.cpp @@ -0,0 +1,90 @@ +/*=================================================================== + +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. + +===================================================================*/ + +// #define ENABLE_CTK_WIDGETS_WIDGET + +#include "QmitkMultiLabelSegmentationUtilitiesView.h" +#include "BooleanOperations/QmitkBooleanOperationsWidget.h" +#include "MorphologicalOperations/QmitkMorphologicalOperationsWidget.h" +#include "SurfaceToImage/QmitkSurfaceToImageWidget.h" +#include "ImageMasking/QmitkImageMaskingWidget.h" + +QmitkMultiLabelSegmentationUtilitiesView::QmitkMultiLabelSegmentationUtilitiesView() : +m_BooleanOperationsWidget(NULL), +m_MorphologicalOperationsWidget(NULL), +m_SurfaceToImageWidget(NULL), +m_ImageMaskingWidget(NULL) +{ +} + +QmitkMultiLabelSegmentationUtilitiesView::~QmitkMultiLabelSegmentationUtilitiesView() +{ +} + +void QmitkMultiLabelSegmentationUtilitiesView::CreateQtPartControl(QWidget* parent) +{ + m_Controls.setupUi(parent); + + mitk::IRenderWindowPart* renderWindowPart = this->GetRenderWindowPart(); + + mitk::SliceNavigationController* timeNavigationController = renderWindowPart != NULL + ? renderWindowPart->GetTimeNavigationController() + : NULL; + + m_BooleanOperationsWidget = new QmitkBooleanOperationsWidget(timeNavigationController, parent); + + m_MorphologicalOperationsWidget = new QmitkMorphologicalOperationsWidget(timeNavigationController, parent); + + m_SurfaceToImageWidget = new QmitkSurfaceToImageWidget(timeNavigationController, parent); + + m_ImageMaskingWidget = new QmitkImageMaskingWidget(timeNavigationController, parent); + + this->AddUtilityWidget(m_BooleanOperationsWidget, QIcon(":/MultiLabelSegmentationUtilities/BooleanOperations_48x48.png"), "Boolean Operations"); + + this->AddUtilityWidget(m_MorphologicalOperationsWidget, QIcon(":/MultiLabelSegmentationUtilities/MorphologicalOperations_48x48.png"), "Morphological Operations"); + + this->AddUtilityWidget(m_SurfaceToImageWidget, QIcon(":/MultiLabelSegmentationUtilities/SurfaceToImage_48x48.png"), "Surface To Image"); + + this->AddUtilityWidget(m_ImageMaskingWidget, QIcon(":/MultiLabelSegmentationUtilities/ImageMasking_48x48.png"), "Image Masking"); +} + +void QmitkMultiLabelSegmentationUtilitiesView::AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text) +{ + m_Controls.toolBox->addItem(widget, icon, text); +} + +void QmitkMultiLabelSegmentationUtilitiesView::SetFocus() +{ + m_Controls.toolBox->setFocus(); +} + +void QmitkMultiLabelSegmentationUtilitiesView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) +{ + mitk::SliceNavigationController* timeNavigationController = renderWindowPart->GetTimeNavigationController(); + + m_BooleanOperationsWidget->SetTimeNavigationController(timeNavigationController); + m_MorphologicalOperationsWidget->SetTimeNavigationController(timeNavigationController); + m_SurfaceToImageWidget->SetTimeNavigationController(timeNavigationController); + m_ImageMaskingWidget->SetTimeNavigationController(timeNavigationController); +} + +void QmitkMultiLabelSegmentationUtilitiesView::RenderWindowPartDeactivated(mitk::IRenderWindowPart*) +{ + m_BooleanOperationsWidget->SetTimeNavigationController(NULL); + m_MorphologicalOperationsWidget->SetTimeNavigationController(NULL); + m_SurfaceToImageWidget->SetTimeNavigationController(NULL); + m_ImageMaskingWidget->SetTimeNavigationController(NULL); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.h new file mode 100644 index 0000000000..865257ebe3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesView.h @@ -0,0 +1,57 @@ +/*=================================================================== + +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 QmitkMultiLabelSegmentationUtilitiesView_h +#define QmitkMultiLabelSegmentationUtilitiesView_h + +#include +#include +#include + +class QmitkBooleanOperationsWidget; +class QmitkSurfaceToImageWidget; +class QmitkImageMaskingWidget; +class QmitkMorphologicalOperationsWidget; + +class QmitkMultiLabelSegmentationUtilitiesView : public QmitkAbstractView, public mitk::IRenderWindowPartListener +{ + Q_OBJECT + +public: + QmitkMultiLabelSegmentationUtilitiesView(); + ~QmitkMultiLabelSegmentationUtilitiesView(); + + void CreateQtPartControl(QWidget* parent); + void SetFocus(); + + void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart); + void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart); + +private: + void AddUtilityWidget(QWidget* widget, const QIcon& icon, const QString& text); + + QmitkBooleanOperationsWidget* m_BooleanOperationsWidget; + + QmitkMorphologicalOperationsWidget* m_MorphologicalOperationsWidget; + + QmitkSurfaceToImageWidget* m_SurfaceToImageWidget; + + QmitkImageMaskingWidget* m_ImageMaskingWidget; + + Ui::QmitkMultiLabelSegmentationUtilitiesViewControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesViewControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesViewControls.ui new file mode 100644 index 0000000000..5853d2f7a1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkMultiLabelSegmentationUtilitiesViewControls.ui @@ -0,0 +1,61 @@ + + + QmitkMultiLabelSegmentationUtilitiesViewControls + + + + 0 + 0 + 289 + 418 + + + + + 0 + 0 + + + + QmitkTemplate + + + icon-size: 32px 32px + + + + 0 + + + + + + + + ::tab +{ + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 palette(light), stop:1 palette(midlight)); +} + +::tab:selected +{ + background: palette(highlight); + color: palette(highlighted-text); +} + + + -1 + + + 0 + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp new file mode 100644 index 0000000000..3616272fbd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +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 "QmitkSegmentationUtilityWidget.h" + +QmitkSegmentationUtilityWidget::QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) + : QWidget(parent) +{ + this->SetTimeNavigationController(timeNavigationController); +} + +QmitkSegmentationUtilityWidget::~QmitkSegmentationUtilityWidget() +{ +} + +mitk::SliceNavigationController* QmitkSegmentationUtilityWidget::GetTimeNavigationController() const +{ + return m_TimeNavigationController; +} + +void QmitkSegmentationUtilityWidget::SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController) +{ + m_TimeNavigationController = timeNavigationController; + this->setEnabled(timeNavigationController != NULL); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h new file mode 100644 index 0000000000..a588a993b4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/QmitkSegmentationUtilityWidget.h @@ -0,0 +1,55 @@ +/*=================================================================== + +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 QmitkSegmentationUtilityWidget_h +#define QmitkSegmentationUtilityWidget_h + +#include + +namespace mitk +{ + class SliceNavigationController; +} + +/** \brief Base class for segmentation utility widgets that need access to the time navigation controller. + * + * Call GetTimeNavigationController() in your derived class to gain access to the time navigation controller. + * The time navigation controller is not not available at all times and hence this method can return NULL. + */ +class QmitkSegmentationUtilityWidget : public QWidget +{ + Q_OBJECT + +public: + explicit QmitkSegmentationUtilityWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); + virtual ~QmitkSegmentationUtilityWidget(); + + /** \brief Usually called only from QmitkSegmentationUtilitiesView::RenderWindowPartActivated() and QmitkSegmentationUtilitiesView::RenderWindowPartDeactivated(). + */ + void SetTimeNavigationController(mitk::SliceNavigationController* timeNavigationController); + +protected: + /** \brief Call this method to access the time navigation controller. + * + * \return Pointer to the time navigation controller or NULL, if it is not available. + */ + mitk::SliceNavigationController* GetTimeNavigationController() const; + +private: + mitk::SliceNavigationController* m_TimeNavigationController; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp new file mode 100644 index 0000000000..202bd30fd0 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.cpp @@ -0,0 +1,178 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "QmitkSurfaceToImageWidget.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +static const char* const HelpText = "Select a patient image and a surface"; + +QmitkSurfaceToImageWidget::QmitkSurfaceToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent) + : QmitkSegmentationUtilityWidget(timeNavigationController, parent) +{ + m_Controls.setupUi(this); + + m_Controls.m_DataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::ImagePredicate); + m_Controls.m_DataSelectionWidget->AddDataStorageComboBox(QmitkDataSelectionWidget::SurfacePredicate); + m_Controls.m_DataSelectionWidget->SetHelpText(HelpText); + + mitk::IDataStorageService::Pointer service = + berry::Platform::GetServiceRegistry().GetServiceById(mitk::IDataStorageService::ID); + + assert(service.IsNotNull()); + + m_Controls.m_LabelSetWidget->SetDataStorage(service->GetDefaultDataStorage()->GetDataStorage()); + m_Controls.m_LabelSetWidget->setEnabled(true); + + m_Controls.m_SurfaceStampWidget->SetDataStorage(service->GetDefaultDataStorage()->GetDataStorage()); + + this->EnableButtons(false); + + m_Controls.m_chkMakeOutputBinary->setChecked(true); + + connect (m_Controls.btnSurface2Image, SIGNAL(pressed()), this, SLOT(OnSurface2ImagePressed())); + connect(m_Controls.m_DataSelectionWidget, SIGNAL(SelectionChanged(unsigned int, const mitk::DataNode*)), + this, SLOT(OnSelectionChanged(unsigned int, const mitk::DataNode*))); + connect (m_Controls.m_chkMakeOutputBinary, SIGNAL(toggled(bool)), this, SLOT(OnMakeOutputBinaryChanged(bool))); + + if( m_Controls.m_DataSelectionWidget->GetSelection(0).IsNotNull() && + m_Controls.m_DataSelectionWidget->GetSelection(1).IsNotNull() ) + { + this->OnSelectionChanged( 0, m_Controls.m_DataSelectionWidget->GetSelection(0)); + } +} + +QmitkSurfaceToImageWidget::~QmitkSurfaceToImageWidget() +{ +} + +void QmitkSurfaceToImageWidget::EnableButtons(bool enable) +{ + m_Controls.btnSurface2Image->setEnabled(enable); + m_Controls.m_chkMakeOutputBinary->setEnabled(enable); + m_Controls.m_chkOverwriteBackground->setEnabled(enable && !m_Controls.m_chkMakeOutputBinary->isChecked()); + m_Controls.m_leForegroundValue->setEnabled(enable && !m_Controls.m_chkMakeOutputBinary->isChecked()); + m_Controls.m_leBackgroundValue->setEnabled(enable && !m_Controls.m_chkMakeOutputBinary->isChecked()); +} + +void QmitkSurfaceToImageWidget::OnSelectionChanged(unsigned int index, const mitk::DataNode* selection) +{ + mitk::DataNode::Pointer imageNode = m_Controls.m_DataSelectionWidget->GetSelection(0); + mitk::DataNode::Pointer surfaceNode = m_Controls.m_DataSelectionWidget->GetSelection(1); + + if (imageNode.IsNull() || surfaceNode.IsNull() ) + { + m_Controls.m_DataSelectionWidget->SetHelpText(HelpText); + this->EnableButtons(false); + } + else + { + mitk::Image::Pointer image = dynamic_cast( m_Controls.m_DataSelectionWidget->GetSelection(0)->GetData() ); + mitk::Surface::Pointer surface = dynamic_cast( m_Controls.m_DataSelectionWidget->GetSelection(1)->GetData() ); + if( image->GetTimeSteps() != surface->GetTimeSteps() ) + { + m_Controls.m_DataSelectionWidget->SetHelpText("Image and surface are of different size"); + this->EnableButtons(false); + } + else + { + m_Controls.m_DataSelectionWidget->SetHelpText(""); + this->EnableButtons(); + } + } +} + +void QmitkSurfaceToImageWidget::OnSurface2ImagePressed() +{ + this->EnableButtons(false); + + mitk::Image::Pointer image = dynamic_cast( m_Controls.m_DataSelectionWidget->GetSelection(0)->GetData() ); + mitk::Surface::Pointer surface = dynamic_cast( m_Controls.m_DataSelectionWidget->GetSelection(1)->GetData() ); + + if( image.IsNull() || surface.IsNull()) + { + MITK_ERROR << "Selection does not contain an image and/or a surface"; + QMessageBox::information( this, "Surface To Image", "Selection does not contain an image and/or a surface", QMessageBox::Ok ); + this->EnableButtons(); + return; + } + + mitk::Image::Pointer resultImage(0); + resultImage = this->ConvertSurfaceToImage( image, surface ); + + if( resultImage.IsNull() ) + { + QMessageBox::information( this, "Surface to Image", "Could not stamp surface.\n See error log for details.", QMessageBox::Ok ); + this->EnableButtons(); + return; + } + + //create name for result node + std::string nameOfResultImage = m_Controls.m_DataSelectionWidget->GetSelection(0)->GetName(); + nameOfResultImage.append("_"); + nameOfResultImage.append(m_Controls.m_DataSelectionWidget->GetSelection(1)->GetName()); + + //create data node and add to data storage + mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); + resultNode->SetData( resultImage ); + resultNode->SetProperty("name", mitk::StringProperty::New(nameOfResultImage) ); + resultNode->SetProperty("binary", mitk::BoolProperty::New(m_Controls.m_chkMakeOutputBinary->isChecked()) ); + + m_Controls.m_DataSelectionWidget->GetDataStorage()->Add(resultNode, m_Controls.m_DataSelectionWidget->GetSelection(0)); + + this->EnableButtons(); +} + +mitk::Image::Pointer QmitkSurfaceToImageWidget::ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ) +{ + mitk::SurfaceStampImageFilter::Pointer filter = mitk::SurfaceStampImageFilter::New(); + filter->SetInput(image); + filter->SetSurface(surface); + filter->SetMakeOutputBinary(m_Controls.m_chkMakeOutputBinary->isChecked()); + filter->SetOverwriteBackground(m_Controls.m_chkOverwriteBackground->isChecked()); + filter->SetForegroundValue(m_Controls.m_leForegroundValue->text().toFloat()); + filter->SetBackgroundValue(m_Controls.m_leBackgroundValue->text().toFloat()); + + try + { + filter->Update(); + } + catch(mitk::Exception& e) + { + MITK_ERROR << "exception caught: " << e.GetDescription(); + return 0; + } + + mitk::Image::Pointer resultImage = filter->GetOutput(); + + return resultImage; +} + +void QmitkSurfaceToImageWidget::OnMakeOutputBinaryChanged(bool value) +{ + m_Controls.m_chkOverwriteBackground->setEnabled(!value); + m_Controls.m_leForegroundValue->setEnabled(!value); + m_Controls.m_leBackgroundValue->setEnabled(!value); +} diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h new file mode 100644 index 0000000000..ef7aff69c6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidget.h @@ -0,0 +1,66 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkSurfaceToImageWidget_h +#define QmitkSurfaceToImageWidget_h + +#include "../QmitkSegmentationUtilityWidget.h" +#include + +#include + +/*! + \brief QmitkSurfaceToImageWidget + + The Tool converts a surface to a binary image. The Method requires + a surface and an image, which header information defines the output + image. The resulting binary image has the same dimension, size, and + Geometry3D as the input image. +*/ +class QmitkSurfaceToImageWidget : public QmitkSegmentationUtilityWidget +{ + Q_OBJECT + +public: + + /** @brief Default constructor, including creation of GUI elements and signals/slots connections. */ + explicit QmitkSurfaceToImageWidget(mitk::SliceNavigationController* timeNavigationController, QWidget* parent = NULL); + + /** @brief Defaul destructor. */ + ~QmitkSurfaceToImageWidget(); + +private slots: + + /** @brief This slot is called if the selection in the workbench is changed. */ + void OnSelectionChanged(unsigned int index, const mitk::DataNode* selection); + + /** @brief This slot is called if user activates the button to convert a surface into a binary image. */ + void OnSurface2ImagePressed(); + + void OnMakeOutputBinaryChanged(bool value); + +private: + + /** @brief Enable buttons if data selction is valid. */ + void EnableButtons(bool enable = true); + + /** @brief Convert a surface into an binary image. */ + mitk::Image::Pointer ConvertSurfaceToImage( mitk::Image::Pointer image, mitk::Surface::Pointer surface ); + + Ui::QmitkSurfaceToImageWidgetControls m_Controls; +}; + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui new file mode 100644 index 0000000000..6548e7060e --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/SegmentationUtilities/SurfaceToImage/QmitkSurfaceToImageWidgetControls.ui @@ -0,0 +1,245 @@ + + + QmitkSurfaceToImageWidgetControls + + + + 0 + 0 + 198 + 482 + + + + + 3 + + + 4 + + + + + 0 + + + + Masks + + + + 3 + + + 4 + + + + + + + + make output binary + + + + + + + overwrite background + + + + + + + + + Background Value: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 0.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + Foreground Value: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + 1.0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Convert + + + + + + + Qt::Vertical + + + + 20 + 308 + + + + + + + + + Labels + + + + 2 + + + 2 + + + + + + 0 + 0 + + + + + 0 + 50 + + + + + + + + + 0 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 202 + + + + + + + + + + + + + QmitkDataSelectionWidget + QWidget +
internal/Common/QmitkDataSelectionWidget.h
+ 1 +
+ + QmitkLabelSetWidget + QWidget +
Qmitk/QmitkLabelSetWidget.h
+ 1 +
+ + QmitkSurfaceStampWidget + QWidget +
QmitkSurfaceStampWidget.h
+ 1 +
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp new file mode 100644 index 0000000000..8aaaf4006c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,66 @@ +/*=================================================================== + +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 "mitkPluginActivator.h" + +#include "QmitkMultiLabelSegmentationView.h" +#include "QmitkThresholdAction.h" +#include "QmitkCreatePolygonModelAction.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 = NULL; + +void mitk::PluginActivator::start(ctkPluginContext *context) +{ + BERRY_REGISTER_EXTENSION_CLASS(QmitkMultiLabelSegmentationView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkThresholdAction, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkCreatePolygonModelAction, 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* context) +{ + Q_UNUSED(context) + m_Context = NULL; +} + +ctkPluginContext* mitk::PluginActivator::getContext() +{ + return m_Context; +} + +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_multilabelsegmentation, mitk::PluginActivator) + +US_INITIALIZE_MODULE("MultiLabelSegmentation", "liborg_mitk_gui_qt_multilabelsegmentation") diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..57885f8ca5 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/src/internal/mitkPluginActivator.h @@ -0,0 +1,42 @@ +/*=================================================================== + +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 MITKPLUGINACTIVATOR_H +#define MITKPLUGINACTIVATOR_H + +// Parent classes +#include +#include +#include + +namespace mitk +{ + class MITK_LOCAL PluginActivator : public QObject, public ctkPluginActivator + { + Q_OBJECT + Q_INTERFACES(ctkPluginActivator) + + public: + void start(ctkPluginContext *context); + void stop(ctkPluginContext *context); + + static ctkPluginContext* getContext(); + + private: + static ctkPluginContext* m_Context; + }; +} + +#endif diff --git a/Plugins/org.mitk.gui.qt.multilabelsegmentation/target_libraries.cmake b/Plugins/org.mitk.gui.qt.multilabelsegmentation/target_libraries.cmake new file mode 100644 index 0000000000..6c71bbbf08 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.multilabelsegmentation/target_libraries.cmake @@ -0,0 +1,3 @@ +set(target_libraries + CTKWidgets +)