diff --git a/Plugins/org.mitk.gui.qt.bonesegmentation/resources/segment.py b/Plugins/org.mitk.gui.qt.bonesegmentation/resources/segment.py index 7675fd7f8d..583f2487b4 100644 --- a/Plugins/org.mitk.gui.qt.bonesegmentation/resources/segment.py +++ b/Plugins/org.mitk.gui.qt.bonesegmentation/resources/segment.py @@ -1,374 +1,374 @@ 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] #!/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 dir_path = os.path.dirname(os.path.realpath(__file__)) seg_load_network_path = os.path.join(dir_path, 'trained_bone_seg_unet.pth.tar') device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') # print(sys.argv) model = UNet(num_classes=num_classes, in_channels=1) model.load_state_dict(torch.load( seg_load_network_path, map_location=device)) print(device) -nrrd_image = SimpleITK.ReadImage(os.path.join(dir_path, 'temp_CT_1.nrrd')) +nrrd_image = SimpleITK.ReadImage(os.path.join(dir_path, 'temp_CT.nrrd')) # nrrd_image = SimpleITK.ReadImage(sys.argv[1]) model.eval() model.to(device) result = [] first = True print('Segmenting...') # nrrd_image = in_image input_image_array = SimpleITK.GetArrayFromImage(nrrd_image) with torch.no_grad(): start = 0 end = start+batch_size while end <= input_image_array.shape[0]: pred = model(torch.from_numpy(np.expand_dims( input_image_array[start:end], axis=1).astype(np.float32)).to(device)) if first: result = pred.detach().data.cpu() first = False else: result = torch.cat((result, pred.detach().data.cpu())) print(result.shape) start = end end = start + batch_size result = torch.argmax(result, dim=1, keepdim=True) array_to_write = result.data.numpy().squeeze() 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()) -SimpleITK.WriteImage(SimpleITK.Cast(image_to_write, SimpleITK.sitkUInt8), os.path.join(dir_path, 'temp_CT_output.nrrd')) +SimpleITK.WriteImage(SimpleITK.Cast(image_to_write, SimpleITK.sitkUInt8), os.path.join(dir_path, 'temp_bone_seg.nrrd')) print('Ended python script...') diff --git a/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.cpp b/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.cpp index 8835a710fd..e004f7af45 100644 --- a/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.cpp +++ b/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.cpp @@ -1,195 +1,192 @@ /*=================================================================== 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 "BoneSegmentation.h" // Qt #include +#include // mitk image #include #include -#include const std::string BoneSegmentation::VIEW_ID = "org.mitk.views.bonesegmentation"; void BoneSegmentation::SetFocus() { m_Controls.buttonPerformImageProcessing->setFocus(); } void BoneSegmentation::CreateQtPartControl(QWidget *parent) { - m_BoneSegmentationPythonProcess = new QProcess(); m_Controls.setupUi(parent); + m_ProcessBoneSegmentationPython = new QProcess(); m_Controls.buttonPerformImageProcessing->setText("Start Bone Segmentation"); m_Controls.buttonPerformImageProcessing->setEnabled(false); - connect(m_Controls.buttonPerformImageProcessing, &QPushButton::clicked, this, &BoneSegmentation::DoImageProcessing); - connect(m_BoneSegmentationPythonProcess, SIGNAL(finished(int, QProcess::ExitStatus )),this, SLOT(DoBoneSegmentationProcessFinished())); - connect(&m_Thread, SIGNAL(started()), this, SLOT(DoSaveTempNrrd())); - connect(&m_Thread, SIGNAL(finished()), this, SLOT(DoStartBoneSegmentationProcess())); - // connect(this, SIGNAL(FinishedSaveTempNrrd()), this, SLOT(DoStartBoneSegmentationProcess())); - auto isImagePredicate = GetImagePredicate(); m_Controls.m_ImageSelector->SetDataStorage(GetDataStorage()); - m_Controls.m_ImageSelector->SetPredicate(isImagePredicate); + m_Controls.m_ImageSelector->SetPredicate(GetImagePredicate()); + // Connects + connect(m_Controls.buttonPerformImageProcessing, &QPushButton::clicked, this, &BoneSegmentation::DoImageProcessing); + connect(m_ProcessBoneSegmentationPython, SIGNAL(finished(int, QProcess::ExitStatus )),this, SLOT(DoBoneSegmentationProcessFinished())); + connect(&m_ThreadSaveTempNrrdImage, SIGNAL(started()), this, SLOT(DoSaveTempNrrd())); + connect(&m_ThreadSaveTempNrrdImage, SIGNAL(finished()), this, SLOT(DoStartBoneSegmentationProcess())); connect(this->m_Controls.m_ImageSelector, static_cast(&QComboBox::currentIndexChanged), this, &BoneSegmentation::OnImageSelectorChanged); } void BoneSegmentation::OnImageSelectorChanged() { auto selectedImageNode = m_Controls.m_ImageSelector->GetSelectedNode(); if (selectedImageNode != m_selectedImageNode) { m_selectedImageNode = selectedImageNode; if (m_selectedImageNode.IsNotNull()) { m_Controls.labelWarning->setVisible(false); 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 BoneSegmentation::DoSaveTempNrrd() { - if (!m_selectedImageNode) - { - // Nothing selected. Inform the user and return - QMessageBox::information(nullptr, "Template", "Please load and select an image before starting image processing."); - return; - } + if (!m_selectedImageNode) + { + // Nothing selected. Inform the user and return + QMessageBox::information(nullptr, "Template", "Please load and select an image before starting image processing."); + return; + } - // a node itself is not very useful, we need its data item (the image) - mitk::BaseData *data = m_selectedImageNode->GetData(); - if (data) + mitk::BaseData *data = m_selectedImageNode->GetData(); + if (data) + { + // test if this data item is an image or not (could also be a surface or something totally different) + mitk::Image *mitk_image = dynamic_cast(data); + if (mitk_image) { - // test if this data item is an image or not (could also be a surface or something totally different) - mitk::Image *mitk_image = dynamic_cast(data); - if (mitk_image) + std::stringstream message; + std::string name; + message << "Performing image processing for image "; + if (m_selectedImageNode->GetName(name)) { - std::stringstream message; - std::string name; - message << "Performing image processing for image "; - if (m_selectedImageNode->GetName(name)) - { - // a property called "name" was found for this DataNode - message << "'" << name << "'"; - } - message << "."; - MITK_INFO << message.str(); - - MITK_INFO << "[START] StartPythonProcess()"; - - std::string file_name = mitk::IOUtil::GetTempPath() + "temp_CT_1.nrrd"; - mitk::IOUtil::Save(mitk_image, file_name); + // a property called "name" was found for this DataNode + message << "'" << name << "'"; } + message << "."; + MITK_INFO << message.str(); + + MITK_INFO << "[START] StartPythonProcess()"; + + std::string file_name = mitk::IOUtil::GetTempPath() + m_TempNrrdFile; + mitk::IOUtil::Save(mitk_image, file_name); + MITK_INFO << "Temporary NRRD image saved!"; } + } - m_Thread.quit(); + m_ThreadSaveTempNrrdImage.quit(); } - void BoneSegmentation::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_ImageSelector->setEnabled(false); - m_Thread.start(); + m_ThreadSaveTempNrrdImage.start(); } void BoneSegmentation::DoStartBoneSegmentationProcess() { - MITK_INFO << "[Start] DoStartBoneSegmentationProcess()"; - QString fileName(":/segment.py"); - QString pythonFileName = QString::fromStdString(mitk::IOUtil::GetTempPath() + "segment.py"); + MITK_INFO << "[Start] DoStartBoneSegmentationProcess()"; + + // Copy python file and pretrained net to /tmp/ folder + QString fileName(":/" + m_PythonFileName); + QString pythonFileName = QString::fromStdString(mitk::IOUtil::GetTempPath()) + m_PythonFileName; - QFile::copy(fileName, pythonFileName); + QFile::copy(fileName, pythonFileName); - QString pretrainedNetResourcesPath(":/trained_bone_seg_unet.pth.tar"); - QString pretrainedNetTmpPath = QString::fromStdString(mitk::IOUtil::GetTempPath() + "trained_bone_seg_unet.pth.tar"); - bool test = QFile::copy(pretrainedNetResourcesPath, pretrainedNetTmpPath); + QString pretrainedNetResourcesPath(":/trained_bone_seg_unet.pth.tar"); + QString pretrainedNetTmpPath = QString::fromStdString(mitk::IOUtil::GetTempPath() + "trained_bone_seg_unet.pth.tar"); + QFile::copy(pretrainedNetResourcesPath, pretrainedNetTmpPath); - if(test) - MITK_WARN << "Bla"; - QString programCall("python"); - QStringList arguments = QStringList() << pythonFileName; + QString programCall("python"); + QStringList arguments = QStringList() << pythonFileName; - MITK_INFO << programCall; - m_BoneSegmentationPythonProcess->start(programCall, arguments); + MITK_INFO << programCall; + m_ProcessBoneSegmentationPython->start(programCall, arguments); - MITK_INFO << "[END] DoStartBoneSegmentationProcess()"; + MITK_INFO << "[END] DoStartBoneSegmentationProcess()"; } void BoneSegmentation::DoBoneSegmentationProcessFinished() { - MITK_INFO << "Ended calculation thread."; - m_Controls.buttonPerformImageProcessing->setText("Start Bone Segmentation"); - m_Controls.buttonPerformImageProcessing->setEnabled(true); + MITK_INFO << "Ended calculation thread."; - try - { - mitk::IOUtil::Load(mitk::IOUtil::GetTempPath() + "temp_CT_output.nrrd", *GetDataStorage()); - GetDataStorage().GetPointer()->GetNamedNode("temp_CT_output")->SetName("Bone_seg_" + m_selectedImageNode->GetName()); - } - catch(...) - { - MITK_WARN << "Error loading output file. Maybe it does not exist." ; - } + try + { + mitk::IOUtil::Load(mitk::IOUtil::GetTempPath() + m_TempBoneSegFile + ".nrrd", *GetDataStorage()); + GetDataStorage().GetPointer()->GetNamedNode(m_TempBoneSegFile)->SetName("Bone_seg_" + m_selectedImageNode->GetName()); + } + catch(...) + { + MITK_WARN << "Error loading output file. Maybe it does not exist." ; + } - std::string temp_CT = mitk::IOUtil::GetTempPath() + "temp_CT_1.nrrd"; - if(remove(temp_CT.c_str()) != 0) - MITK_WARN << "Error deleting file" ; - else - MITK_INFO << "File successfully deleted" ; + std::string temp_CT = mitk::IOUtil::GetTempPath() + m_TempNrrdFile; + if(remove(temp_CT.c_str()) != 0) + MITK_WARN << "Error deleting file" ; + else + MITK_INFO << "File successfully deleted" ; - std::string temp_output = mitk::IOUtil::GetTempPath() + "temp_CT_output.nrrd"; - if(remove(temp_output.c_str()) != 0) - MITK_WARN << "Error deleting file" ; - else - MITK_INFO << "File successfully deleted" ; + std::string temp_output = mitk::IOUtil::GetTempPath() + m_TempBoneSegFile; + if(remove(temp_output.c_str()) != 0) + MITK_WARN << "Error deleting file" ; + else + MITK_INFO << "File successfully deleted" ; - m_Controls.labelWarning->setVisible(false); - m_Controls.m_ImageSelector->setEnabled(true); + m_Controls.buttonPerformImageProcessing->setText("Start Bone Segmentation"); + m_Controls.buttonPerformImageProcessing->setEnabled(true); + m_Controls.labelWarning->setVisible(false); + m_Controls.m_ImageSelector->setEnabled(true); } mitk::NodePredicateBase::Pointer BoneSegmentation::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.bonesegmentation/src/internal/BoneSegmentation.h b/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.h index 99a84c8206..0f5209bd0c 100644 --- a/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.h +++ b/Plugins/org.mitk.gui.qt.bonesegmentation/src/internal/BoneSegmentation.h @@ -1,79 +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. ===================================================================*/ #ifndef BoneSegmentation_h #define BoneSegmentation_h #include #include #include "ui_BoneSegmentationControls.h" #include #include #include #include #include #include #include /** \brief BoneSegmentation \warning The BoneSegmentation 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 BoneSegmentation : 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; signals: void FinishedSaveTempNrrd(); protected slots: /// \brief Called when the user clicks the GUI button void OnImageSelectorChanged(); void DoSaveTempNrrd(); void DoImageProcessing(); void DoStartBoneSegmentationProcess(); void DoBoneSegmentationProcessFinished(); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; // Predicate helper mitk::NodePredicateBase::Pointer GetImagePredicate(); Ui::BoneSegmentationControls m_Controls; mitk::DataNode::ConstPointer m_selectedImageNode = nullptr; - QProcess* m_BoneSegmentationPythonProcess; - QThread m_Thread; + QProcess* m_ProcessBoneSegmentationPython; + QThread m_ThreadSaveTempNrrdImage; + + const QString m_PythonFileName="segment.py"; + const std::string m_TempNrrdFile="temp_CT.nrrd"; + const std::string m_TempBoneSegFile="temp_bone_seg"; }; #endif // BoneSegmentation_h