diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake
index aeec51a9f9..c68db26580 100644
--- a/Plugins/PluginList.cmake
+++ b/Plugins/PluginList.cmake
@@ -1,102 +1,103 @@
# Plug-ins must be ordered according to their dependencies
set(MITK_PLUGINS
org.blueberry.core.runtime:ON
org.blueberry.core.expressions:OFF
org.blueberry.core.commands:OFF
org.blueberry.core.jobs:OFF
org.blueberry.ui.qt:OFF
org.blueberry.ui.qt.help:ON
org.blueberry.ui.qt.log:ON
org.blueberry.ui.qt.objectinspector:OFF
#org.blueberry.test:ON
#org.blueberry.uitest:ON
#Testing/org.blueberry.core.runtime.tests:ON
#Testing/org.blueberry.osgi.tests:ON
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.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.mxnmultiwidgeteditor:OFF
org.mitk.gui.qt.common.legacy:OFF
org.mitk.gui.qt.cmdlinemodules:OFF
org.mitk.gui.qt.chartExample:OFF
org.mitk.gui.qt.datamanager:ON
org.mitk.gui.qt.datamanagerlight:OFF
org.mitk.gui.qt.datastorageviewertest:OFF
org.mitk.gui.qt.properties:ON
org.mitk.gui.qt.basicimageprocessing:OFF
org.mitk.gui.qt.dicom:OFF
org.mitk.gui.qt.dicominspector:OFF
org.mitk.gui.qt.dosevisualization:OFF
org.mitk.gui.qt.geometrytools:OFF
org.mitk.gui.qt.igtexamples:OFF
org.mitk.gui.qt.igttracking:OFF
org.mitk.gui.qt.lasercontrol:OFF
org.mitk.gui.qt.openigtlink: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.pointsetinteractionmultispectrum:OFF
org.mitk.gui.qt.python:OFF
org.mitk.gui.qt.remeshing:OFF
org.mitk.gui.qt.segmentation:OFF
org.mitk.gui.qt.aicpregistration:OFF
org.mitk.gui.qt.renderwindowmanager:OFF
org.mitk.gui.qt.semanticrelations:OFF
org.mitk.gui.qt.toftutorial:OFF
org.mitk.gui.qt.tofutil:OFF
org.mitk.gui.qt.tubegraph:OFF
org.mitk.gui.qt.ugvisualization:OFF
org.mitk.gui.qt.photoacoustics.pausviewer:OFF
org.mitk.gui.qt.photoacoustics.pausmotioncompensation:OFF
org.mitk.gui.qt.photoacoustics.imageprocessing:OFF
org.mitk.gui.qt.photoacoustics.simulation:OFF
org.mitk.gui.qt.photoacoustics.spectralunmixing: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.igt.app.ultrasoundtrackingnavigation:OFF
org.mitk.gui.qt.spectrocamrecorder:OFF
org.mitk.gui.qt.classificationsegmentation:OFF
org.mitk.gui.qt.overlaymanager:OFF
org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF
org.mitk.gui.qt.multilabelsegmentation:OFF
org.mitk.matchpoint.core.helper:OFF
org.mitk.gui.qt.matchpoint.algorithm.browser:OFF
org.mitk.gui.qt.matchpoint.algorithm.control:OFF
org.mitk.gui.qt.matchpoint.algorithm.batch:OFF
org.mitk.gui.qt.matchpoint.mapper:OFF
org.mitk.gui.qt.matchpoint.framereg:OFF
org.mitk.gui.qt.matchpoint.visualizer:OFF
org.mitk.gui.qt.matchpoint.evaluator:OFF
org.mitk.gui.qt.matchpoint.manipulator:OFF
org.mitk.gui.qt.preprocessing.resampling:OFF
org.mitk.gui.qt.radiomics:OFF
org.mitk.gui.qt.cest:OFF
org.mitk.gui.qt.fit.demo:OFF
org.mitk.gui.qt.fit.inspector:OFF
org.mitk.gui.qt.fit.genericfitting:OFF
org.mitk.gui.qt.pharmacokinetics.mri:OFF
org.mitk.gui.qt.pharmacokinetics.pet:OFF
org.mitk.gui.qt.pharmacokinetics.simulation:OFF
org.mitk.gui.qt.pharmacokinetics.curvedescriptor:OFF
org.mitk.gui.qt.pharmacokinetics.concentration.mri:OFF
+ org.mitk.gui.qt.bonesegmentationrework:ON
)
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/CMakeLists.txt b/Plugins/org.mitk.gui.qt.bonesegmentationrework/CMakeLists.txt
new file mode 100644
index 0000000000..ee0557331c
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/CMakeLists.txt
@@ -0,0 +1,13 @@
+project(org_mitk_gui_qt_bonesegmentationrework)
+
+mitk_create_plugin(
+ EXPORT_DIRECTIVE BONESEGMENTATIONREWORK_EXPORT
+ EXPORTED_INCLUDE_SUFFIXES src
+ MODULE_DEPENDS MitkQtWidgetsExt MitkPython
+PACKAGE_DEPENDS
+ PUBLIC Qt5|Widgets CTK|CTKScriptingPythonCore+CTKScriptingPythonWidgets
+)
+if(TARGET ${PLUGIN_TARGET})
+ target_link_libraries(${PLUGIN_TARGET} PUBLIC Python3::NumPy)
+ configure_file(PythonPath.h.in "${CMAKE_CURRENT_BINARY_DIR}/PythonPath.h" @ONLY)
+endif()
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/PythonPath.h.in b/Plugins/org.mitk.gui.qt.bonesegmentationrework/PythonPath.h.in
new file mode 100644
index 0000000000..28581baec4
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/PythonPath.h.in
@@ -0,0 +1,16 @@
+#ifdef _DEBUG
+#define PYTHON_PATH_BUILD_TYPE "/Debug"
+#else
+#define PYTHON_PATH_BUILD_TYPE "/Release"
+#endif
+
+#define PYTHON_LIBRARY "@PYTHON_LIBRARY@"
+
+#ifdef WIN32
+//Todo: windows system python
+#define EXTERNAL_SITE_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python@PYTHON_VERSION_MAJOR@.@PYTHON_VERSION_MINOR@/site-packages"
+#define EXTERNAL_DIST_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python@PYTHON_VERSION_MAJOR@.@PYTHON_VERSION_MINOR@/dist-packages"
+#else
+#define EXTERNAL_SITE_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python@PYTHON_VERSION_MAJOR@.@PYTHON_VERSION_MINOR@/site-packages"
+#define EXTERNAL_DIST_PACKAGES "@MITK_EXTERNAL_PROJECT_PREFIX@/lib/python@PYTHON_VERSION_MAJOR@.@PYTHON_VERSION_MINOR@/dist-packages"
+#endif
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/Manual.dox
new file mode 100644
index 0000000000..3e05d63e27
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/Manual.dox
@@ -0,0 +1,17 @@
+/**
+\page org_mitk_gui_qt_bonesegmentationrework The Bonesegmentation Rework
+
+\imageMacro{icon.png,"Icon of Bonesegmentation Rework",2.00}
+
+\tableofcontents
+
+\section org_mitk_gui_qt_bonesegmentationreworkOverview Overview
+Describe the features of your awesome plugin here
+
+- Increases productivity
+
- Creates beautiful images
+
- Generates PhD thesis
+
- Brings world peace
+
+
+*/
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/icon.xpm b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/icon.xpm
new file mode 100644
index 0000000000..9057c20bc6
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/UserManual/icon.xpm
@@ -0,0 +1,21 @@
+/* XPM */
+static const char * icon_xpm[] = {
+"16 16 2 1",
+" c #FF0000",
+". c #000000",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/doxygen/modules.dox
new file mode 100644
index 0000000000..e87862429c
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/documentation/doxygen/modules.dox
@@ -0,0 +1,16 @@
+/**
+ \defgroup org_mitk_gui_qt_bonesegmentationrework org.mitk.gui.qt.bonesegmentationrework
+ \ingroup MITKPlugins
+
+ \brief Describe your plugin here.
+
+*/
+
+/**
+ \defgroup org_mitk_gui_qt_bonesegmentationrework_internal Internal
+ \ingroup org_mitk_gui_qt_bonesegmentationrework
+
+ \brief This subcategory includes the internal classes of the org.mitk.gui.qt.bonesegmentationrework plugin. Other
+ plugins must not rely on these classes. They contain implementation details and their interface
+ may change at any time. We mean it.
+*/
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/files.cmake b/Plugins/org.mitk.gui.qt.bonesegmentationrework/files.cmake
new file mode 100644
index 0000000000..bb1698267d
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/files.cmake
@@ -0,0 +1,44 @@
+set(SRC_CPP_FILES
+
+)
+
+set(INTERNAL_CPP_FILES
+ org_mitk_gui_qt_bonesegmentationrework_Activator.cpp
+ BoneSegmentationRework.cpp
+ ImageTransferPython.cpp
+)
+
+set(UI_FILES
+ src/internal/BoneSegmentationReworkControls.ui
+)
+
+set(MOC_H_FILES
+ src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.h
+ src/internal/BoneSegmentationRework.h
+ src/internal/ImageTransferPython.h
+)
+
+# list of resource files which can be used by the plug-in
+# system without loading the plug-ins shared library,
+# for example the icon used in the menu and tabs for the
+# plug-in views in the workbench
+set(CACHED_RESOURCE_FILES
+ resources/icon.svg
+ plugin.xml
+)
+
+# list of Qt .qrc files which contain additional resources
+# specific to this plugin
+set(QRC_FILES
+ resources/boneseg.qrc
+)
+
+set(CPP_FILES )
+
+foreach(file ${SRC_CPP_FILES})
+ set(CPP_FILES ${CPP_FILES} src/${file})
+endforeach(file ${SRC_CPP_FILES})
+
+foreach(file ${INTERNAL_CPP_FILES})
+ set(CPP_FILES ${CPP_FILES} src/internal/${file})
+endforeach(file ${INTERNAL_CPP_FILES})
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.bonesegmentationrework/manifest_headers.cmake
new file mode 100644
index 0000000000..936e4f88ac
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/manifest_headers.cmake
@@ -0,0 +1,5 @@
+set(Plugin-Name "Bonesegmentation Rework")
+set(Plugin-Version "0.1")
+set(Plugin-Vendor "DKFZ")
+set(Plugin-ContactAddress "")
+set(Require-Plugin org.mitk.gui.qt.common)
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/plugin.xml b/Plugins/org.mitk.gui.qt.bonesegmentationrework/plugin.xml
new file mode 100644
index 0000000000..e531c5883d
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/plugin.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/boneseg.qrc b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/boneseg.qrc
new file mode 100644
index 0000000000..b1940d6050
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/boneseg.qrc
@@ -0,0 +1,5 @@
+
+
+ segment.py
+
+
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/icon.svg b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/icon.svg
new file mode 100644
index 0000000000..4d4941c235
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/icon.svg
@@ -0,0 +1,2413 @@
+
+
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/segment.py b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/segment.py
new file mode 100644
index 0000000000..219a7c8c63
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/resources/segment.py
@@ -0,0 +1,385 @@
+import os
+import numpy as np
+import SimpleITK
+import torch
+import torch.cuda
+
+print('Started python script...')
+
+import SimpleITK as sitk
+from skimage.transform import resize
+import sys
+
+
+def resize_image(image, old_spacing, new_spacing, order=3):
+ new_shape = (int(np.round(old_spacing[0]/new_spacing[0]*float(image.shape[0]))),
+ int(np.round(old_spacing[1]/new_spacing[1]*float(image.shape[1]))),
+ int(np.round(old_spacing[2]/new_spacing[2]*float(image.shape[2]))))
+ return resize(image, new_shape, order=order, mode='edge')
+
+
+def cut_off_values_upper_lower_percentile(image, mask=None, percentile_lower=0.2, percentile_upper=99.8):
+ if mask is None:
+ mask = image!=image[0,0,0]
+ cut_off_lower = np.percentile(image[mask!=0].ravel(), percentile_lower)
+ cut_off_upper = np.percentile(image[mask!=0].ravel(), percentile_upper)
+ res = np.copy(image)
+ res[(res < cut_off_lower) & (mask !=0 )] = cut_off_lower
+ res[(res > cut_off_upper) & (mask !=0 )] = cut_off_upper
+ return image
+
+
+def preprocess_image(itk_image, is_seg=False, spacing_target=(1, 0.5, 0.5)):
+ spacing = np.array(itk_image.GetSpacing())[[2, 1, 0]]
+ image = sitk.GetArrayFromImage(itk_image).astype(float)
+ if not is_seg:
+ image = resize_image(image, spacing, spacing_target).astype(np.float32)
+ # cut off outliers
+ image = cut_off_values_upper_lower_percentile(image, np.ones(image.shape), 1., 99.)
+ #subtract mean, divide by std. use heuristic masking
+ image -= image.mean()
+ image /= image.std()
+ else:
+ image = resize_image(image, spacing, spacing_target, 0)
+ return image
+
+
+def load_and_preprocess(in_image):
+ images = {}
+
+ np_array = sitk.GetArrayFromImage(in_image).astype(float)
+ if len(np_array.shape) > 3:
+ b0 = sitk.GetImageFromArray(np_array[:,:,:,0])
+ b0.SetSpacing(in_image.GetSpacing())
+ b0.SetOrigin(in_image.GetOrigin())
+ b0.SetDirection(in_image.GetDirection())
+ images["T1"] = b0
+ elif len(np_array.shape)==3 :
+ images["T1"] = in_image
+
+ properties_dict = {
+ "spacing": in_image.GetSpacing(),
+ "direction": in_image.GetDirection(),
+ "size": in_image.GetSize(),
+ "origin": in_image.GetOrigin()
+ }
+
+ for k in images.keys():
+ images[k] = preprocess_image(images[k], is_seg=False, spacing_target=(1.5, 1.5, 1.5))
+
+ properties_dict['size_before_cropping'] = images["T1"].shape
+
+ imgs = []
+ for seq in ['T1']:
+ imgs.append(images[seq][None])
+ all_data = np.vstack(imgs)
+ return all_data, properties_dict
+
+def get_sitk_from_nparray(segmentation, original_image, dct) :
+ '''
+ segmentation must have the same spacing as the original nifti (for now). segmentation may have been cropped out
+ of the original image
+ :param segmentation:
+ :param dct:
+ :return:
+ '''
+ old_size = np.array(dct['size_before_cropping'])
+ bbox = dct.get('brain_bbox')
+ if bbox is not None:
+ seg_old_size = np.zeros(old_size)
+ for c in range(3):
+ bbox[c][1] = np.min((bbox[c][0] + segmentation.shape[c], old_size[c]))
+ seg_old_size[bbox[0][0]:bbox[0][1],
+ bbox[1][0]:bbox[1][1],
+ bbox[2][0]:bbox[2][1]] = segmentation
+ else:
+ seg_old_size = segmentation
+
+ seg_old_spacing = resize_segmentation(seg_old_size, np.array(dct['size'])[[2, 1, 0]], order=3)
+ seg_resized_itk = sitk.GetImageFromArray(seg_old_spacing.astype(np.uint8))
+ seg_resized_itk.SetSpacing(np.array(dct['spacing'])[[0, 1, 2]])
+ seg_resized_itk.SetOrigin(dct['origin'])
+ seg_resized_itk.SetDirection(dct['direction'])
+
+ if original_image is not None :
+ image = sitk.GetArrayFromImage(original_image).astype(float)
+
+ if len(image.shape) > 3 :
+ for i in range(image.shape[3]) :
+ image[:,:,:,i] *= seg_old_spacing
+ else :
+ image *= seg_old_spacing
+
+ brain_extracted = sitk.GetImageFromArray(image.astype(np.float32))
+ brain_extracted.SetSpacing(np.array(dct['spacing'])[[0, 1, 2]])
+ brain_extracted.SetOrigin(dct['origin'])
+ brain_extracted.SetDirection(dct['direction'])
+ else :
+ brain_extracted = None
+
+ return seg_resized_itk, brain_extracted
+
+def save_segmentation_nifti(segmentation, dct, out_fname):
+ '''
+ segmentation must have the same spacing as the original nifti (for now). segmentation may have been cropped out
+ of the original image
+ :param segmentation:
+ :param dct:
+ :param out_fname:
+ :return:
+ '''
+ old_size = np.array(dct['size_before_cropping'])
+ bbox = dct.get('brain_bbox')
+ if bbox is not None:
+ seg_old_size = np.zeros(old_size)
+ for c in range(3):
+ bbox[c][1] = np.min((bbox[c][0] + segmentation.shape[c], old_size[c]))
+ seg_old_size[bbox[0][0]:bbox[0][1],
+ bbox[1][0]:bbox[1][1],
+ bbox[2][0]:bbox[2][1]] = segmentation
+ else:
+ seg_old_size = segmentation
+
+ seg_old_spacing = resize_segmentation(seg_old_size, np.array(dct['size'])[[2, 1, 0]], order=3)
+ seg_resized_itk = sitk.GetImageFromArray(seg_old_spacing.astype(np.uint8))
+ seg_resized_itk.SetSpacing(np.array(dct['spacing'])[[0, 1, 2]])
+ seg_resized_itk.SetOrigin(dct['origin'])
+ seg_resized_itk.SetDirection(dct['direction'])
+ sitk.WriteImage(seg_resized_itk, out_fname)
+
+
+def resize_segmentation(segmentation, new_shape, order=3):
+ unique_labels = np.unique(segmentation)
+ assert len(segmentation.shape) == len(new_shape), "new shape must have same dimensionality as segmentation"
+ reshaped_multihot = np.zeros([len(unique_labels)] + list(new_shape), dtype=float)
+ for i, c in enumerate(unique_labels):
+ reshaped_multihot[i] = resize((segmentation == c).astype(float), new_shape, order, mode="constant", cval=0, clip=True)
+ reshaped = unique_labels[np.argmax(reshaped_multihot, 0)]
+ return reshaped.astype(segmentation.dtype)
+
+
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2017 Division of Medical Image Computing, German Cancer Research Center (DKFZ)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import numpy as np
+
+
+def reshape(orig_img, append_value=-1024, new_shape=(512, 512, 512)):
+ reshaped_image = np.zeros(new_shape)
+ reshaped_image[...] = append_value
+ x_offset = 0
+ y_offset = 0 # (new_shape[1] - orig_img.shape[1]) // 2
+ z_offset = 0 # (new_shape[2] - orig_img.shape[2]) // 2
+
+ reshaped_image[x_offset:orig_img.shape[0]+x_offset, y_offset:orig_img.shape[1]+y_offset, z_offset:orig_img.shape[2]+z_offset] = orig_img
+ # insert temp_img.min() as background value
+
+ return reshaped_image
+
+
+def crop_image_to_orig_size(image, orig_shape):
+ x_offset = 0
+ y_offset = 0 # (512 - orig_shape[1]) // 2
+ z_offset = 0 # (512 - orig_shape[2]) // 2
+
+ return image[x_offset:orig_shape[0] + x_offset, y_offset:orig_shape[1] + y_offset, z_offset:orig_shape[2] + z_offset]
+
+def next_power_of_2(x):
+ return 1 if x == 0 else 2**(x - 1).bit_length()
+
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2017 Division of Medical Image Computing, German Cancer Research Center (DKFZ)
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Defines the Unet.
+# |num_downs|: number of downsamplings in UNet. For example,
+# if |num_downs| == 7, image of size 128x128 will become of size 1x1 at the bottleneck
+
+# recursive implementation of Unet
+import torch
+
+from torch import nn
+
+
+class UNet(nn.Module):
+ def __init__(self, num_classes=3, in_channels=1, initial_filter_size=64, kernel_size=3, num_downs=4, norm_layer=nn.InstanceNorm2d):
+ # norm_layer=nn.BatchNorm2d, use_dropout=False):
+ super(UNet, self).__init__()
+
+ # construct unet structure
+ unet_block = UnetSkipConnectionBlock(in_channels=initial_filter_size * 2 ** (num_downs-1), out_channels=initial_filter_size * 2 ** num_downs,
+ num_classes=num_classes, kernel_size=kernel_size, norm_layer=norm_layer, innermost=True)
+ for i in range(1, num_downs):
+ unet_block = UnetSkipConnectionBlock(in_channels=initial_filter_size * 2 ** (num_downs-(i+1)),
+ out_channels=initial_filter_size * 2 ** (num_downs-i),
+ num_classes=num_classes, kernel_size=kernel_size, submodule=unet_block, norm_layer=norm_layer)
+ unet_block = UnetSkipConnectionBlock(in_channels=in_channels, out_channels=initial_filter_size,
+ num_classes=num_classes, kernel_size=kernel_size, submodule=unet_block, norm_layer=norm_layer,
+ outermost=True)
+
+ self.model = unet_block
+
+ def forward(self, x):
+ return self.model(x)
+
+
+# Defines the submodule with skip connection.
+# X -------------------identity---------------------- X
+# |-- downsampling -- |submodule| -- upsampling --|
+class UnetSkipConnectionBlock(nn.Module):
+ def __init__(self, in_channels=None, out_channels=None, num_classes=1, kernel_size=3,
+ submodule=None, outermost=False, innermost=False, norm_layer=nn.InstanceNorm2d, use_dropout=False):
+ super(UnetSkipConnectionBlock, self).__init__()
+ self.outermost = outermost
+ # downconv
+ pool = nn.MaxPool2d(2, stride=2)
+ conv1 = self.contract(in_channels=in_channels, out_channels=out_channels, kernel_size=kernel_size, norm_layer=norm_layer)
+ conv2 = self.contract(in_channels=out_channels, out_channels=out_channels, kernel_size=kernel_size, norm_layer=norm_layer)
+
+ # upconv
+ conv3 = self.expand(in_channels=out_channels*2, out_channels=out_channels, kernel_size=kernel_size)
+ conv4 = self.expand(in_channels=out_channels, out_channels=out_channels, kernel_size=kernel_size)
+
+ if outermost:
+ final = nn.Conv2d(out_channels, num_classes, kernel_size=1)
+ down = [conv1, conv2]
+ up = [conv3, conv4, final]
+ model = down + [submodule] + up
+ elif innermost:
+ upconv = nn.ConvTranspose2d(in_channels*2, in_channels,
+ kernel_size=2, stride=2)
+ model = [pool, conv1, conv2, upconv]
+ else:
+ upconv = nn.ConvTranspose2d(in_channels*2, in_channels, kernel_size=2, stride=2)
+
+ down = [pool, conv1, conv2]
+ up = [conv3, conv4, upconv]
+
+ if use_dropout:
+ model = down + [submodule] + up + [nn.Dropout(0.5)]
+ else:
+ model = down + [submodule] + up
+
+ self.model = nn.Sequential(*model)
+
+ @staticmethod
+ def contract(in_channels, out_channels, kernel_size=3, norm_layer=nn.InstanceNorm2d):
+ layer = nn.Sequential(
+ nn.Conv2d(in_channels, out_channels, kernel_size, padding=1),
+ norm_layer(out_channels),
+ nn.LeakyReLU(inplace=True))
+ return layer
+
+ @staticmethod
+ def expand(in_channels, out_channels, kernel_size=3):
+ layer = nn.Sequential(
+ nn.Conv2d(in_channels, out_channels, kernel_size, padding=1),
+ nn.LeakyReLU(inplace=True),
+ )
+ return layer
+
+ @staticmethod
+ def center_crop(layer, target_width, target_height):
+ batch_size, n_channels, layer_width, layer_height = layer.size()
+ xy1 = (layer_width - target_width) // 2
+ xy2 = (layer_height - target_height) // 2
+ return layer[:, :, xy1:(xy1 + target_width), xy2:(xy2 + target_height)]
+
+ def forward(self, x):
+ if self.outermost:
+ return self.model(x)
+ else:
+ crop = self.center_crop(self.model(x), x.size()[2], x.size()[3])
+ return torch.cat([x, crop], 1)
+
+batch_size = 8
+num_classes = 2
+
+device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
+
+
+model = UNet(num_classes=num_classes, in_channels=1)
+model.load_state_dict(torch.load(
+ seg_load_network_path, map_location=device))
+print(device)
+
+model.eval()
+model.to(device)
+
+result = []
+first = True
+print('Segmenting...')
+
+input_image_array = SimpleITK.GetArrayFromImage(nrrd_image)
+append_empty_slices = batch_size - (input_image_array.shape[0]%batch_size)
+print("A")
+y = next_power_of_2(input_image_array.shape[1])
+z = next_power_of_2(input_image_array.shape[2])
+print("B")
+if y > 512 or z > 512:
+ batch_size = 2
+temp_array = np.ones((input_image_array.shape[0] + append_empty_slices, y, z))*(-1024)
+temp_array[0:input_image_array.shape[0], 0:input_image_array.shape[1], 0:input_image_array.shape[2]] = input_image_array
+print("C")
+with torch.no_grad():
+ print("here1")
+ start = 0
+ end = start+batch_size
+ while end <= temp_array.shape[0]:
+ print("here2")
+ pred = model(torch.from_numpy(np.expand_dims(
+ temp_array[start:end], axis=1).astype(np.float32)).to(device))
+ print("D")
+ if first:
+ result = pred.detach().data.cpu()
+ first = False
+ print("if")
+ else:
+ result = torch.cat((result, pred.detach().data.cpu()))
+ print("else")
+ print(result.shape)
+ start = end
+ end = start + batch_size
+result = torch.argmax(result, dim=1, keepdim=True)
+print("E")
+array_to_write = result.data.numpy().squeeze()
+array_to_write = array_to_write[0:input_image_array.shape[0], 0:input_image_array.shape[1], 0:input_image_array.shape[2]]
+array_to_write = crop_image_to_orig_size( array_to_write, SimpleITK.GetArrayFromImage(nrrd_image).shape)
+print(array_to_write.shape)
+
+image_to_write = SimpleITK.GetImageFromArray(array_to_write)
+
+image_to_write.SetSpacing(nrrd_image.GetSpacing())
+image_to_write.SetOrigin(nrrd_image.GetOrigin())
+image_to_write.SetDirection(nrrd_image.GetDirection())
+image_to_write = SimpleITK.Cast(image_to_write, SimpleITK.sitkUInt8)
+
+SimpleITK.Cast(image_to_write, SimpleITK.sitkUInt8)
+print('Ended python script...')
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.cpp b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.cpp
new file mode 100644
index 0000000000..0e6ad0ac8f
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.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.
+
+===================================================================*/
+
+// Blueberry
+#include
+#include
+
+// Qmitk
+#include "BoneSegmentationRework.h"
+
+// Qt
+#include
+#include
+#include
+
+// mitk image
+#include
+#include
+
+#include "internal/org_mitk_gui_qt_bonesegmentationrework_Activator.h"
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include"ImageTransferPython.h"
+
+const std::string BoneSegmentationRework::VIEW_ID = "org.mitk.views.bonesegmentationrework";
+
+BoneSegmentationRework::~BoneSegmentationRework()
+{
+ if (Py_IsInitialized())
+ {
+ Py_Finalize();
+ }
+}
+
+void BoneSegmentationRework::SetFocus()
+{
+ m_Controls.buttonPerformImageProcessing->setFocus();
+}
+
+void BoneSegmentationRework::CreateQtPartControl(QWidget *parent)
+{
+ m_Controls.setupUi(parent);
+ m_Controls.buttonPerformImageProcessing->setText("Start Bone Segmentation");
+ m_Controls.buttonPerformImageProcessing->setEnabled(false);
+
+ m_Controls.m_ImageSelector->SetDataStorage(GetDataStorage());
+ m_Controls.m_ImageSelector->SetPredicate(GetImagePredicate());
+
+ m_Controls.labelLoadTrainedNet->setText("Please load a trained network!");
+
+ // Segmentation Thread
+ connect(&m_SegmentationWatcher, SIGNAL(finished()), this, SLOT(DoBoneSegmentationProcessFinished()));
+
+ // Connects
+ connect(
+ m_Controls.buttonPerformImageProcessing, &QPushButton::clicked, this, &BoneSegmentationRework::DoImageProcessing);
+ connect(m_Controls.m_ButtonLoadTrainedNet, &QPushButton::clicked, this, &BoneSegmentationRework::DoLoadTrainedNet);
+ connect(this->m_Controls.m_ImageSelector,
+ static_cast(&QComboBox::currentIndexChanged),
+ this,
+ &BoneSegmentationRework::OnImageSelectorChanged);
+}
+
+void BoneSegmentationRework::OnImageSelectorChanged()
+{
+ auto selectedImageNode = m_Controls.m_ImageSelector->GetSelectedNode();
+ if (selectedImageNode != m_selectedImageNode)
+ {
+ m_selectedImageNode = selectedImageNode;
+ if (m_selectedImageNode.IsNotNull())
+ {
+ m_Controls.labelWarning->setVisible(false);
+ if (m_TrainedNet != "")
+ {
+ m_Controls.buttonPerformImageProcessing->setEnabled(true);
+ }
+ return;
+ }
+ m_Controls.labelWarning->setText("Please select an image!");
+ m_Controls.labelWarning->setVisible(true);
+ m_Controls.buttonPerformImageProcessing->setEnabled(false);
+ }
+}
+
+void BoneSegmentationRework::DoLoadTrainedNet()
+{
+ QString tempPath = QString::fromStdString(mitk::IOUtil::GetTempPathA());
+ QString pretrainedNetResourcesPath =
+ QFileDialog::getOpenFileName(nullptr, tr("Open File"), tempPath, tr("Images (*.pth.tar)"));
+
+ m_TrainedNet = pretrainedNetResourcesPath.toStdString();
+
+ if (m_TrainedNet != "")
+ {
+ m_Controls.labelLoadTrainedNet->setText("Network loaded!");
+ if (m_selectedImageNode.IsNotNull())
+ {
+ m_Controls.buttonPerformImageProcessing->setEnabled(true);
+ }
+ }
+}
+
+void BoneSegmentationRework::DoImageProcessing()
+{
+ m_Controls.labelWarning->setVisible(true);
+ m_Controls.labelWarning->setText("This might take a while.\nDepending ob your machine up to 20 minutes or more.");
+ m_Controls.buttonPerformImageProcessing->setEnabled(false);
+ m_Controls.m_ButtonLoadTrainedNet->setEnabled(false);
+ m_Controls.m_ImageSelector->setEnabled(false);
+ this->DoStartBoneSegmentationProcess();
+}
+
+void BoneSegmentationRework::DoStartBoneSegmentationProcess()
+{
+ MITK_INFO << "[Start] DoStartBoneSegmentationProcess()";
+ m_SegmentationFuture = QtConcurrent::run(this, &BoneSegmentationRework::DoRunPythonScript);
+ m_SegmentationWatcher.setFuture(m_SegmentationFuture);
+ MITK_INFO << "[END] DoStartBoneSegmentationProcess()";
+}
+
+void BoneSegmentationRework::DoRunPythonScript()
+{
+ QString pythonFileName(":/" + m_PythonFileName);
+ std::string fileName = mitk::StandardFileLocations::GetInstance()->FindFile(
+ "segment.py", "Plugins/org.mitk.gui.qt.bonesegmentationrework/resources");
+ std::replace(fileName.begin(), fileName.end(), '\\', '/');
+ MITK_INFO << "Python file to execute: " << fileName;
+ QString data;
+ QFile file(QString::fromUtf8(fileName.c_str()));
+ if (!file.open(QIODevice::ReadOnly))
+ {
+ qDebug() << "filenot opened" << endl;
+ }
+ else
+ {
+ qDebug() << "file opened" << endl;
+ data = file.readAll();
+ }
+
+ file.close();
+ std::string dataString = data.toStdString();
+ if (!Py_IsInitialized())
+ {
+ Py_Initialize();
+ }
+ try
+ {
+ std::string pythonEnv = ImageTransferPython::SetUpPythonEnvironment();
+ if (PyRun_SimpleString(pythonEnv.c_str()) == -1)
+ {
+ mitkThrow() << "An error occured while setting up the Python environment";
+ }
+ // Set path for the trained network in python
+ std::string networkPath = "seg_load_network_path=\"" + m_TrainedNet + "\"";
+ if (PyRun_SimpleString(networkPath.c_str()) == -1)
+ {
+ mitkThrow() << "An error occured while setting the network path in Python";
+ }
+ // Copy image for segmentation in Python
+ std::string copyImage = ImageTransferPython::CopyToPythonAsSimpleItkImage(
+ dynamic_cast(m_selectedImageNode->GetData()), "nrrd_image");
+ if (PyRun_SimpleString(copyImage.c_str()) == -1)
+ {
+ mitkThrow() << "An error occured while copying the input image path to Python";
+ }
+ // Execute the python script
+ if (PyRun_SimpleString(dataString.c_str()) == -1)
+ {
+ mitkThrow() << "An error occured while running the Python script";
+ }
+ //Get the result of the segmentation
+ m_OutputImage = ImageTransferPython::CopySimpleItkImageFromPython("image_to_write");
+
+ m_SuccessfulProcessing = true;
+ }
+ catch (const mitk::Exception &e)
+ {
+ MITK_ERROR << e.GetDescription();
+ m_SuccessfulProcessing = false;
+ return;
+ }
+}
+
+void BoneSegmentationRework::DoLoadOutputImage()
+{
+ try
+ {
+ mitk::DataNode::Pointer outputNode = mitk::DataNode::New();
+ outputNode->SetName("Bone_seg_" + m_selectedImageNode->GetName());
+ outputNode->SetData(m_OutputImage);
+ GetDataStorage().GetPointer()->Add(outputNode, m_selectedImageNode);
+ }
+ catch (...)
+ {
+ MITK_WARN << "Error loading output file. Maybe it does not exist.";
+ }
+}
+
+void BoneSegmentationRework::DoBoneSegmentationProcessFinished()
+{
+ if (!m_SuccessfulProcessing)
+ {
+ MITK_INFO << "Failed during calculation thread.";
+ QMessageBox::warning(nullptr,
+ "Error in segmentation",
+ "There was an error in the segmentation process. No resulting segmentation can be loaded.");
+ }
+ else
+ {
+ MITK_INFO << "Ended calculation thread.";
+ this->DoLoadOutputImage();
+ }
+ m_Controls.buttonPerformImageProcessing->setText("Start Bone Segmentation");
+ m_Controls.buttonPerformImageProcessing->setEnabled(true);
+ m_Controls.m_ButtonLoadTrainedNet->setEnabled(true);
+ m_Controls.labelWarning->setVisible(false);
+ m_Controls.m_ImageSelector->setEnabled(true);
+}
+
+mitk::NodePredicateBase::Pointer BoneSegmentationRework::GetImagePredicate()
+{
+ auto isImage = mitk::NodePredicateDataType::New("Image");
+ auto hasBinaryProperty = mitk::NodePredicateProperty::New("binary", mitk::BoolProperty::New(true));
+ auto isNotBinary = mitk::NodePredicateNot::New(hasBinaryProperty);
+ auto isNotBinaryImage = mitk::NodePredicateAnd::New(isImage, isNotBinary);
+ auto hasHelperObjectProperty = mitk::NodePredicateProperty::New("helper object", nullptr);
+ auto isNoHelperObject = mitk::NodePredicateNot::New(hasHelperObjectProperty);
+ auto isNoHelperObjectPredicate = isNoHelperObject.GetPointer();
+
+ auto isImageForImageStatistics = mitk::NodePredicateAnd::New(isNotBinaryImage, isNoHelperObjectPredicate);
+ return isImageForImageStatistics.GetPointer();
+}
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.h b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.h
new file mode 100644
index 0000000000..9c4b2a1c30
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationRework.h
@@ -0,0 +1,85 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+
+#ifndef BoneSegmentationRework_h
+#define BoneSegmentationRework_h
+
+#include
+
+#include
+
+#include "ui_BoneSegmentationReworkControls.h"
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+/**
+ \brief BoneSegmentationRework
+
+ \warning The BoneSegmentationRework plugin provides an automatic bone segmentation for CT images based on deep learning.
+ At this moment, only CT images can be segmented. The segmentation is done on 2D axial slices. The network was trained
+ using data from the multiple myeloma project. It was trained on a very limited amount of training data and needs to
+ be tested in "real world scenarios".
+
+ \sa QmitkAbstractView
+ \ingroup ${plugin_target}_internal
+*/
+class BoneSegmentationRework : public QmitkAbstractView
+{
+ // this is needed for all Qt objects that should have a Qt meta-object
+ // (everything that derives from QObject and wants to have signal/slots)
+ Q_OBJECT
+
+public:
+ static const std::string VIEW_ID;
+ void DoRunPythonScript();
+ ~BoneSegmentationRework();
+
+signals:
+ void Operate(QString);
+
+protected slots:
+ /// \brief Called when the user clicks the GUI button
+ void OnImageSelectorChanged();
+ void DoImageProcessing();
+ void DoStartBoneSegmentationProcess();
+ void DoBoneSegmentationProcessFinished();
+ void DoLoadTrainedNet();
+ void DoLoadOutputImage();
+
+protected:
+ virtual void CreateQtPartControl(QWidget *parent) override;
+ virtual void SetFocus() override;
+
+ // Predicate helper
+ mitk::NodePredicateBase::Pointer GetImagePredicate();
+ Ui::BoneSegmentationReworkControls m_Controls;
+ mitk::DataNode::Pointer m_selectedImageNode = nullptr;
+ std::string m_TrainedNet;
+ const QString m_PythonFileName="segment.py";
+ QFutureWatcher m_SegmentationWatcher;
+ QFuture m_SegmentationFuture;
+ bool m_SuccessfulProcessing;
+ mitk::Image::Pointer m_OutputImage;
+};
+
+#endif // BoneSegmentationRework_h
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationReworkControls.ui b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationReworkControls.ui
new file mode 100644
index 0000000000..423938e46a
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/BoneSegmentationReworkControls.ui
@@ -0,0 +1,88 @@
+
+
+ BoneSegmentationReworkControls
+
+
+
+ 0
+ 0
+ 222
+ 161
+
+
+
+
+ 0
+ 0
+
+
+
+ QmitkTemplate
+
+
+ -
+
+
+ Please load a trained network!
+
+
+
+ -
+
+
+ Load trained network
+
+
+
+ -
+
+
+ QLabel { color: rgb(255, 0, 0) }
+
+
+ Please select an image!
+
+
+
+ -
+
+
+ -
+
+
+ Do image processing
+
+
+ Do Something
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Expanding
+
+
+
+ 20
+ 220
+
+
+
+
+
+
+
+
+
+ QmitkDataStorageComboBoxWithSelectNone
+ QComboBox
+ QmitkDataStorageComboBoxWithSelectNone.h
+
+
+
+
+
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.cpp b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.cpp
new file mode 100644
index 0000000000..ac434a6780
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.cpp
@@ -0,0 +1,537 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+#include "ImageTransferPython.h"
+#include
+#include
+#include
+#include
+#include
+
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include
+#include
+
+std::string ImageTransferPython::SetUpPythonEnvironment()
+{
+ std::string programPath = QCoreApplication::applicationDirPath().toStdString() + "/";
+ QString pythonCommand;
+ pythonCommand.append(QString("import site, sys\n"));
+ pythonCommand.append(QString("import SimpleITK as sitk\n"));
+ pythonCommand.append(QString("import SimpleITK._SimpleITK as _SimpleITK\n"));
+ pythonCommand.append(QString("import numpy\n"));
+
+ pythonCommand.append(QString("sys.path.append('')\n"));
+ pythonCommand.append(QString("sys.path.append('%1')\n").arg(programPath.c_str()));
+ pythonCommand.append(QString("sys.path.append('%1')\n").arg(EXTERNAL_DIST_PACKAGES));
+ pythonCommand.append(QString("\nsite.addsitedir('%1')").arg(EXTERNAL_SITE_PACKAGES));
+
+ return pythonCommand.toStdString();
+}
+
+std::string ImageTransferPython::CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &stdvarName)
+{
+ QString varName = QString::fromStdString(stdvarName);
+ QString command;
+ unsigned int *imgDim = image->GetDimensions();
+ int npy_nd = 1;
+
+ // access python module
+ PyObject *pyMod = PyImport_AddModule("__main__");
+ // global dictionary
+ PyObject *pyDict = PyModule_GetDict(pyMod);
+ const mitk::Vector3D spacing = image->GetGeometry()->GetSpacing();
+ const mitk::Point3D origin = image->GetGeometry()->GetOrigin();
+ mitk::PixelType pixelType = image->GetPixelType();
+ itk::ImageIOBase::IOPixelType ioPixelType = image->GetPixelType().GetPixelType();
+ PyObject *npyArray = nullptr;
+ mitk::ImageReadAccessor racc(image);
+ void *array = const_cast(racc.GetData());
+
+ mitk::Vector3D xDirection;
+ mitk::Vector3D yDirection;
+ mitk::Vector3D zDirection;
+ const vnl_matrix_fixed &transform =
+ image->GetGeometry()->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix();
+
+ mitk::Vector3D s = image->GetGeometry()->GetSpacing();
+
+ // ToDo: Check if this is a collumn or row vector from the matrix.
+ // right now it works but not sure for rotated geometries
+ mitk::FillVector3D(xDirection, transform[0][0] / s[0], transform[0][1] / s[1], transform[0][2] / s[2]);
+ mitk::FillVector3D(yDirection, transform[1][0] / s[0], transform[1][1] / s[1], transform[1][2] / s[2]);
+ mitk::FillVector3D(zDirection, transform[2][0] / s[0], transform[2][1] / s[1], transform[2][2] / s[2]);
+
+ // save the total number of elements here (since the numpy array is one dimensional)
+ npy_intp *npy_dims = new npy_intp[1];
+ npy_dims[0] = imgDim[0];
+
+ /**
+ * Build a string in the format [1024,1028,1]
+ * to describe the dimensionality. This is needed for simple itk
+ * to know the dimensions of the image
+ */
+ QString dimensionString;
+ dimensionString.append(QString("["));
+ dimensionString.append(QString::number(imgDim[0]));
+ for (unsigned i = 1; i < 3; ++i)
+ // always three because otherwise the 3d-geometry gets destroyed
+ // (relevant for backtransformation of simple itk image to mitk.
+ {
+ dimensionString.append(QString(","));
+ dimensionString.append(QString::number(imgDim[i]));
+ npy_dims[0] *= imgDim[i];
+ }
+ dimensionString.append("]");
+
+ // the next line is necessary for vectorimages
+ npy_dims[0] *= pixelType.GetNumberOfComponents();
+
+ // default pixeltype: unsigned short
+ NPY_TYPES npy_type = NPY_USHORT;
+ std::string sitk_type = "sitkUInt8";
+ if (ioPixelType == itk::ImageIOBase::SCALAR)
+ {
+ if (pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE)
+ {
+ npy_type = NPY_DOUBLE;
+ sitk_type = "sitkFloat64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::FLOAT)
+ {
+ npy_type = NPY_FLOAT;
+ sitk_type = "sitkFloat32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::SHORT)
+ {
+ npy_type = NPY_SHORT;
+ sitk_type = "sitkInt16";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::CHAR)
+ {
+ npy_type = NPY_BYTE;
+ sitk_type = "sitkInt8";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::INT)
+ {
+ npy_type = NPY_INT;
+ sitk_type = "sitkInt32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::LONG)
+ {
+ npy_type = NPY_LONG;
+ sitk_type = "sitkInt64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::UCHAR)
+ {
+ npy_type = NPY_UBYTE;
+ sitk_type = "sitkUInt8";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::UINT)
+ {
+ npy_type = NPY_UINT;
+ sitk_type = "sitkUInt32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::ULONG)
+ {
+ npy_type = NPY_LONG;
+ sitk_type = "sitkUInt64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::USHORT)
+ {
+ npy_type = NPY_USHORT;
+ sitk_type = "sitkUInt16";
+ }
+ }
+ else if (ioPixelType == itk::ImageIOBase::VECTOR || ioPixelType == itk::ImageIOBase::RGB ||
+ ioPixelType == itk::ImageIOBase::RGBA)
+ {
+ if (pixelType.GetComponentType() == itk::ImageIOBase::DOUBLE)
+ {
+ npy_type = NPY_DOUBLE;
+ sitk_type = "sitkVectorFloat64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::FLOAT)
+ {
+ npy_type = NPY_FLOAT;
+ sitk_type = "sitkVectorFloat32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::SHORT)
+ {
+ npy_type = NPY_SHORT;
+ sitk_type = "sitkVectorInt16";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::CHAR)
+ {
+ npy_type = NPY_BYTE;
+ sitk_type = "sitkVectorInt8";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::INT)
+ {
+ npy_type = NPY_INT;
+ sitk_type = "sitkVectorInt32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::LONG)
+ {
+ npy_type = NPY_LONG;
+ sitk_type = "sitkVectorInt64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::UCHAR)
+ {
+ npy_type = NPY_UBYTE;
+ sitk_type = "sitkVectorUInt8";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::UINT)
+ {
+ npy_type = NPY_UINT;
+ sitk_type = "sitkVectorUInt32";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::ULONG)
+ {
+ npy_type = NPY_LONG;
+ sitk_type = "sitkVectorUInt64";
+ }
+ else if (pixelType.GetComponentType() == itk::ImageIOBase::USHORT)
+ {
+ npy_type = NPY_USHORT;
+ sitk_type = "sitkVectorUInt16";
+ }
+ }
+ else
+ {
+ MITK_WARN << "not a recognized pixeltype";
+ return false;
+ }
+
+ // creating numpy array
+ import_array1("true");
+ npyArray = PyArray_SimpleNewFromData(npy_nd, npy_dims, npy_type, array);
+
+ // add temp array it to the python dictionary to access it in python code
+ const int status =
+ PyDict_SetItemString(pyDict, QString("%1_numpy_array").arg(varName).toStdString().c_str(), npyArray);
+
+ // sanity check
+ if (status != 0)
+ return false;
+
+ command.append(QString("%1 = sitk.Image(%2,sitk.%3,%4)\n")
+ .arg(varName)
+ .arg(dimensionString)
+ .arg(QString(sitk_type.c_str()))
+ .arg(QString::number(pixelType.GetNumberOfComponents())));
+ command.append(QString("%1.SetSpacing([%2,%3,%4])\n")
+ .arg(varName)
+ .arg(QString::number(spacing[0]))
+ .arg(QString::number(spacing[1]))
+ .arg(QString::number(spacing[2])));
+ command.append(QString("%1.SetOrigin([%2,%3,%4])\n")
+ .arg(varName)
+ .arg(QString::number(origin[0]))
+ .arg(QString::number(origin[1]))
+ .arg(QString::number(origin[2])));
+ command.append(QString("%1.SetDirection([%2,%3,%4,%5,%6,%7,%8,%9,%10])\n")
+ .arg(varName)
+ .arg(QString::number(xDirection[0]))
+ .arg(QString::number(xDirection[1]))
+ .arg(QString::number(xDirection[2]))
+ .arg(QString::number(yDirection[0]))
+ .arg(QString::number(yDirection[1]))
+ .arg(QString::number(yDirection[2]))
+ .arg(QString::number(zDirection[0]))
+ .arg(QString::number(zDirection[1]))
+ .arg(QString::number(zDirection[2])));
+ // directly access the cpp api from the lib
+ command.append(QString("_SimpleITK._SetImageFromArray(%1_numpy_array,%1)\n").arg(varName));
+ command.append(QString("del %1_numpy_array").arg(varName));
+
+ return command.toStdString();
+}
+
+mitk::PixelType DeterminePixelType(const std::string &pythonPixeltype, unsigned long nrComponents, int dimensions)
+{
+ typedef itk::RGBPixel UCRGBPixelType;
+ typedef itk::RGBPixel USRGBPixelType;
+ typedef itk::RGBPixel FloatRGBPixelType;
+ typedef itk::RGBPixel DoubleRGBPixelType;
+ typedef itk::Image UCRGBImageType;
+ typedef itk::Image USRGBImageType;
+ typedef itk::Image FloatRGBImageType;
+ typedef itk::Image DoubleRGBImageType;
+ typedef itk::RGBAPixel UCRGBAPixelType;
+ typedef itk::RGBAPixel USRGBAPixelType;
+ typedef itk::RGBAPixel FloatRGBAPixelType;
+ typedef itk::RGBAPixel DoubleRGBAPixelType;
+ typedef itk::Image UCRGBAImageType;
+ typedef itk::Image USRGBAImageType;
+ typedef itk::Image FloatRGBAImageType;
+ typedef itk::Image DoubleRGBAImageType;
+
+ auto pixelType = mitk::MakePixelType(nrComponents);
+
+ if (nrComponents == 1)
+ {
+ if (pythonPixeltype.compare("float64") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("float32") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int16") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int8") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int32") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int64") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint8") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint32") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint64") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint16") == 0)
+ {
+ pixelType = mitk::MakePixelType(nrComponents);
+ }
+ else
+ {
+ mitkThrow() << "unknown scalar PixelType";
+ }
+ }
+ else if (nrComponents == 3 && dimensions == 2)
+ {
+ if (pythonPixeltype.compare("float64") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("float32") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("uint8") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("uint16") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ }
+ else if ((nrComponents == 4) && dimensions == 2)
+ {
+ if (pythonPixeltype.compare("float64") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("float32") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("uint8") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ else if (pythonPixeltype.compare("uint16") == 0)
+ {
+ pixelType = mitk::MakePixelType();
+ }
+ }
+ else
+ {
+ if (pythonPixeltype.compare("float64") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("float32") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int16") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int8") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int32") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("int64") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint8") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint16") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint32") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else if (pythonPixeltype.compare("uint64") == 0)
+ {
+ pixelType = mitk::MakePixelType>(nrComponents);
+ }
+ else
+ {
+ mitkThrow() << "unknown vectorial PixelType";
+ }
+ }
+
+ return pixelType;
+}
+
+mitk::Image::Pointer ImageTransferPython::CopySimpleItkImageFromPython(const std::string &stdvarName)
+{
+ if (!Py_IsInitialized())
+ {
+ MITK_INFO << "init python";
+ Py_Initialize();
+ }
+ double *ds = nullptr;
+ // access python module
+ PyObject *pyMod = PyImport_AddModule("__main__");
+ // global dictionarry
+ PyObject *pyDict = PyModule_GetDict(pyMod);
+ mitk::Image::Pointer mitkImage = mitk::Image::New();
+ mitk::Vector3D spacing;
+ mitk::Point3D origin;
+ QString command;
+ QString varName = QString::fromStdString(stdvarName);
+
+ command.append(QString("%1_numpy_array = sitk.GetArrayFromImage(%1)\n").arg(varName));
+ command.append(QString("%1_spacing = numpy.asarray(%1.GetSpacing())\n").arg(varName));
+ command.append(QString("%1_origin = numpy.asarray(%1.GetOrigin())\n").arg(varName));
+ command.append(QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName));
+ command.append(QString("%1_direction = numpy.asarray(%1.GetDirection())\n").arg(varName));
+ command.append(QString("%1_nrComponents = numpy.asarray(%1.GetNumberOfComponentsPerPixel())\n").arg(varName));
+ command.append(QString("%1_dtype = %1_numpy_array.dtype.name\n").arg(varName));
+
+ MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
+
+ if (PyRun_SimpleString(command.toStdString().c_str()) == -1)
+ {
+ mitkThrow() << "Something went wrong while getting the Image from Python";
+ }
+
+ PyObject *py_dtype = PyDict_GetItemString(pyDict, QString("%1_dtype").arg(varName).toStdString().c_str());
+ std::string dtype = PyString_AsString(py_dtype);
+ PyArrayObject *py_data =
+ (PyArrayObject *)PyDict_GetItemString(pyDict, QString("%1_numpy_array").arg(varName).toStdString().c_str());
+ PyArrayObject *py_spacing =
+ (PyArrayObject *)PyDict_GetItemString(pyDict, QString("%1_spacing").arg(varName).toStdString().c_str());
+ PyArrayObject *py_origin =
+ (PyArrayObject *)PyDict_GetItemString(pyDict, QString("%1_origin").arg(varName).toStdString().c_str());
+ PyArrayObject *py_direction =
+ (PyArrayObject *)PyDict_GetItemString(pyDict, QString("%1_direction").arg(varName).toStdString().c_str());
+
+ PyArrayObject *py_nrComponents =
+ (PyArrayObject *)PyDict_GetItemString(pyDict, QString("%1_nrComponents").arg(varName).toStdString().c_str());
+
+ unsigned int nr_Components = *(reinterpret_cast(PyArray_DATA(py_nrComponents)));
+
+ unsigned int nr_dimensions = PyArray_NDIM(py_data);
+ if (nr_Components > 1) // for VectorImages the last dimension in the numpy array are the vector components.
+ {
+ --nr_dimensions;
+ }
+
+ mitk::PixelType pixelType = DeterminePixelType(dtype, nr_Components, nr_dimensions);
+
+ unsigned int *dimensions = new unsigned int[nr_dimensions];
+ // fill backwards , nd data saves dimensions in opposite direction
+ for (unsigned i = 0; i < nr_dimensions; ++i)
+ {
+ dimensions[i] = PyArray_DIMS(py_data)[nr_dimensions - 1 - i];
+ }
+
+ mitkImage->Initialize(pixelType, nr_dimensions, dimensions);
+
+ mitkImage->SetChannel(PyArray_DATA(py_data));
+
+ ds = reinterpret_cast(PyArray_DATA(py_spacing));
+ spacing[0] = ds[0];
+ spacing[1] = ds[1];
+ spacing[2] = ds[2];
+
+ mitkImage->GetGeometry()->SetSpacing(spacing);
+
+ ds = reinterpret_cast(PyArray_DATA(py_origin));
+ origin[0] = ds[0];
+ origin[1] = ds[1];
+ origin[2] = ds[2];
+ mitkImage->GetGeometry()->SetOrigin(origin);
+
+ itk::Matrix py_transform;
+
+ ds = reinterpret_cast(PyArray_DATA(py_direction));
+ py_transform[0][0] = ds[0];
+ py_transform[0][1] = ds[1];
+ py_transform[0][2] = ds[2];
+
+ py_transform[1][0] = ds[3];
+ py_transform[1][1] = ds[4];
+ py_transform[1][2] = ds[5];
+
+ py_transform[2][0] = ds[6];
+ py_transform[2][1] = ds[7];
+ py_transform[2][2] = ds[8];
+
+ mitk::AffineTransform3D::Pointer affineTransform = mitkImage->GetGeometry()->GetIndexToWorldTransform();
+
+ itk::Matrix transform = py_transform * affineTransform->GetMatrix();
+
+ affineTransform->SetMatrix(transform);
+
+ mitkImage->GetGeometry()->SetIndexToWorldTransform(affineTransform);
+
+ // cleanup
+ command.clear();
+ command.append(QString("del %1_numpy_array\n").arg(varName));
+ command.append(QString("del %1_dtype\n").arg(varName));
+ command.append(QString("del %1_spacing\n").arg(varName));
+ command.append(QString("del %1_origin\n").arg(varName));
+ command.append(QString("del %1_direction\n").arg(varName));
+ command.append(QString("del %1_nrComponents\n").arg(varName));
+ MITK_DEBUG("PythonService") << "Issuing python command " << command.toStdString();
+ if (PyRun_SimpleString(command.toStdString().c_str()) == -1)
+ {
+ mitkThrow() << "Something went wrong while cleaning up the variables from getting the Image from Python";
+ }
+ delete[] dimensions;
+
+ MITK_INFO << "img dim" << mitkImage->GetDimension();
+ return mitkImage;
+}
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.h b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.h
new file mode 100644
index 0000000000..d9ff24a6a2
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/ImageTransferPython.h
@@ -0,0 +1,26 @@
+/*============================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center (DKFZ)
+All rights reserved.
+
+Use of this source code is governed by a 3-clause BSD license that can be
+found in the LICENSE file.
+
+============================================================================*/
+#ifndef ImageTransferPython_h
+#define ImageTransferPython_h
+
+#include
+#include
+
+class ImageTransferPython
+{
+ public:
+ static std::string SetUpPythonEnvironment();
+ static std::string CopyToPythonAsSimpleItkImage(mitk::Image *image, const std::string &stdvarName);
+ static mitk::Image::Pointer CopySimpleItkImageFromPython(const std::string &varName);
+};
+
+#endif
\ No newline at end of file
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.cpp b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.cpp
new file mode 100644
index 0000000000..ddda51cffc
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.cpp
@@ -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.
+
+===================================================================*/
+
+
+#include "org_mitk_gui_qt_bonesegmentationrework_Activator.h"
+#include "BoneSegmentationRework.h"
+#include
+
+US_INITIALIZE_MODULE
+
+ctkPluginContext *mitk::org_mitk_gui_qt_bonesegmentationrework_Activator::m_Context = nullptr;
+
+void mitk::org_mitk_gui_qt_bonesegmentationrework_Activator::start(ctkPluginContext *context)
+{
+ BERRY_REGISTER_EXTENSION_CLASS(BoneSegmentationRework, context)
+ this->m_Context = context;
+}
+
+void mitk::org_mitk_gui_qt_bonesegmentationrework_Activator::stop(ctkPluginContext *context)
+{
+ Q_UNUSED(context)
+ m_Context = nullptr;
+}
+
+ctkPluginContext *mitk::org_mitk_gui_qt_bonesegmentationrework_Activator::getContext()
+{
+ return m_Context;
+}
+
diff --git a/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.h b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.h
new file mode 100644
index 0000000000..6c2ad7e759
--- /dev/null
+++ b/Plugins/org.mitk.gui.qt.bonesegmentationrework/src/internal/org_mitk_gui_qt_bonesegmentationrework_Activator.h
@@ -0,0 +1,47 @@
+/*===================================================================
+
+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
+
+#include
+
+namespace mitk
+{
+
+ class org_mitk_gui_qt_bonesegmentationrework_Activator : public QObject, public ctkPluginActivator
+ {
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_bonesegmentationrework")
+ Q_INTERFACES(ctkPluginActivator)
+
+ public:
+ void start(ctkPluginContext *context) override;
+ void stop(ctkPluginContext *context) override;
+
+ static ctkPluginContext* getContext();
+
+ private:
+
+ static ctkPluginContext* m_Context;
+ }; // org_mitk_gui_qt_bonesegmentationrework_Activator
+
+ typedef org_mitk_gui_qt_bonesegmentationrework_Activator PluginActivator;
+
+}
+
+#endif // MITKPLUGINACTIVATOR_H