diff --git a/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.cpp b/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.cpp index 6a06bb8740..d3f2c8a787 100644 --- a/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.cpp +++ b/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.cpp @@ -1,640 +1,733 @@ /*=================================================================== 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 // Qt #include #include #include #include // Qmitk #include "QmitkActiveLearning.h" #include // MITK #include #include #include #include #include #include #include #include +#include // ITK #include +#include +#include #include #include // Returns true if list has at least one entry and all entries are valid mitk::Images, otherwise false static bool SelectionAllImages(const QList& nodes) { if (nodes.empty()) { return false; } for (const auto& node : nodes) { if(!(node.IsNotNull() && dynamic_cast(node->GetData()) != nullptr)) return false; } return true; } // QColor to mitk::Color static mitk::Color QColorToMitkColor(const QColor& qcolor) { mitk::Color color; color.SetRed((float)qcolor.red() / 255); color.SetGreen((float)qcolor.green() / 255); color.SetBlue((float)qcolor.blue() / 255); return color; } // For debugging static void PrintAllLabels(mitk::LabelSetImage* image) { for (auto it=image->GetActiveLabelSet()->IteratorBegin(); it!=image->GetActiveLabelSet()->IteratorConstEnd(); ++it) { MITK_INFO << "Key: " << it->first << " - Name: " << it->second->GetName() << " - Value: " << it->second->GetValue() << " - Color: " << it->second->GetColor(); } } // Make values of labels a consistent range static void FillLabelValues(mitk::LabelSetImage* image) { int value(0); for (auto it=image->GetActiveLabelSet()->IteratorBegin(); it!=image->GetActiveLabelSet()->IteratorConstEnd(); ++it) { it->second->SetValue(value); value++; } image->GetActiveLabelSet()->SetActiveLabel(0); } // Fill image with zeros static void FillWithZeros(mitk::Image* image) { unsigned int size = image->GetPixelType().GetSize(); for (unsigned int i=0; iGetDimension(); i++) { size *= image->GetDimension(i); } for (unsigned int t=0; tGetTimeSteps(); t++) { mitk::ImageWriteAccessor accessor(image, image->GetVolumeData(0)); memset(accessor.GetData(), 0, size); } } +/* ================================================================== + * FEATURES + * =============================================================== */ + +template +static void GaussianSmoothing(const itk::Image* inputImage, float sigma, mitk::Image::Pointer outputImage) +{ + typedef itk::Image ImageType; + auto filter = itk::DiscreteGaussianImageFilter::New(); + filter->SetInput(inputImage); + filter->SetVariance(sigma*sigma); + filter->Update(); + mitk::GrabItkImageMemory(filter->GetOutput(), outputImage); +} + +template +static void GaussianGradientMagnitude(const itk::Image* inputImage, float sigma, mitk::Image::Pointer outputImage) +{ + typedef itk::Image ImageType; + auto filter = itk::GradientMagnitudeRecursiveGaussianImageFilter::New(); + filter->SetInput(inputImage); + filter->SetSigma(sigma); + filter->Update(); + mitk::GrabItkImageMemory(filter->GetOutput(), outputImage); +} + +template +static void LaplacianOfGaussian(const itk::Image* inputImage, float sigma, mitk::Image::Pointer outputImage) +{ + typedef itk::Image ImageType; + auto filter = itk::LaplacianRecursiveGaussianImageFilter::New(); + filter->SetInput(inputImage); + filter->SetSigma(sigma); + filter->Update(); + mitk::GrabItkImageMemory(filter->GetOutput(), outputImage); +} + +template +static void StructureTensorEigenvalues(const itk::Image* inputImage, float sigma, std::vector outputImages) +{ + typedef itk::Image ImageType; + auto filter = itk::StructureTensorEigenvalueImageFilter::New(); + filter->SetInput(inputImage); + filter->SetInnerScale(sigma); + filter->SetOuterScale(sigma); + filter->Update(); + for (unsigned int i=0; iGetNumberOfOutputs(); i++) + { + mitk::GrabItkImageMemory(filter->GetOutput(i), outputImages[i]); + } +} + +template +static void HessianEigenvalues(const itk::Image* inputImage, float sigma, std::vector outputImages) +{ + typedef itk::Image ImageType; + auto filter = itk::HessianMatrixEigenvalueImageFilter::New(); + filter->SetInput(inputImage); + filter->SetSigma(sigma); + filter->Update(); + for (unsigned int i=0; iGetNumberOfOutputs(); i++) + { + mitk::GrabItkImageMemory(filter->GetOutput(i), outputImages[i]); + } +} + /* ================================================================== * PUBLIC SLOTS * =============================================================== */ void ActiveLearning::Initialize() { // Get selected nodes and check again if these are all images - auto nodes = this->GetDataManagerSelection(); - if (!SelectionAllImages(nodes)) return; + m_Nodes = this->GetDataManagerSelection(); + if (!SelectionAllImages(m_Nodes)) return; m_Controls.m_InitializePushButton->setDisabled(true); // Set names to the label (again) - QString nameList = QString::fromStdString(nodes[0]->GetName()); - if (nodes.length() >= 2) + QString nameList = QString::fromStdString(m_Nodes[0]->GetName()); + if (m_Nodes.length() >= 2) { - for (int i=1; i"); - nameList += QString::fromStdString(nodes[i]->GetName()); + nameList += QString::fromStdString(m_Nodes[i]->GetName()); } } m_Controls.m_InitializeLabel->setText(nameList); // ======================================= // ANNOTATION IMAGE // ======================================= m_AnnotationImage = mitk::LabelSetImage::New(); try { - auto referenceImage = dynamic_cast(nodes[0]->GetData()); + auto referenceImage = dynamic_cast(m_Nodes[0]->GetData()); m_AnnotationImage->Initialize(referenceImage); } catch (mitk::Exception& e) { MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(m_Parent, "Error", "Could not initialize annotation image"); return; } FillWithZeros(m_AnnotationImage); m_AnnotationNode = mitk::DataNode::New(); m_AnnotationNode->SetData(m_AnnotationImage); m_AnnotationNode->SetName("Labels"); m_AnnotationNode->SetColor(1., 1., 1.); // m_AnnotationNode->SetBoolProperty("helper object", true); - m_AnnotationImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(nodes[0]->GetName().c_str())); + m_AnnotationImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(m_Nodes[0]->GetName().c_str())); m_AnnotationImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New("Labels")); - this->GetDataStorage()->Add(m_AnnotationNode, nodes[0]); + this->GetDataStorage()->Add(m_AnnotationNode, m_Nodes[0]); // ======================================= // PREDICTION IMAGE // ======================================= m_PredictionImage = mitk::Image::New(); try { - mitk::Image::Pointer referenceImage = dynamic_cast(nodes[0]->GetData()); + mitk::Image::Pointer referenceImage = dynamic_cast(m_Nodes[0]->GetData()); m_PredictionImage->Initialize(referenceImage); } catch (mitk::Exception& e) { MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(m_Parent, "Error", "Could not initialize prediction image"); return; } FillWithZeros(m_PredictionImage); m_PredictionNode = mitk::DataNode::New(); m_PredictionNode->SetData(m_PredictionImage); m_PredictionNode->SetName("Predictions"); m_PredictionNode->SetColor(1., 1., 1.); // m_PredictionNode->SetBoolProperty("helper object", true); // m_PredictionImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(nodes[0]->GetName().c_str())); // m_PredictionImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New("Predictions")); - this->GetDataStorage()->Add(m_PredictionNode, nodes[0]); + this->GetDataStorage()->Add(m_PredictionNode, m_Nodes[0]); // ======================================= // SEGMENTATION IMAGE // ======================================= m_SegmentationImage = mitk::LabelSetImage::New(); try { - auto referenceImage = dynamic_cast(nodes[0]->GetData()); + auto referenceImage = dynamic_cast(m_Nodes[0]->GetData()); m_SegmentationImage->Initialize(referenceImage); } catch (mitk::Exception& e) { MITK_ERROR << "Exception caught: " << e.GetDescription(); QMessageBox::information(m_Parent, "Error", "Could not initialize segmentation image"); return; } FillWithZeros(m_SegmentationImage); m_SegmentationNode = mitk::DataNode::New(); m_SegmentationNode->SetData(m_SegmentationImage); m_SegmentationNode->SetName("Segmentation"); m_SegmentationNode->SetColor(1., 1., 1.); // m_PredictionNode->SetBoolProperty("helper object", true); - m_SegmentationImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(nodes[0]->GetName().c_str())); + m_SegmentationImage->GetExteriorLabel()->SetProperty("name.parent", mitk::StringProperty::New(m_Nodes[0]->GetName().c_str())); m_SegmentationImage->GetExteriorLabel()->SetProperty("name.image", mitk::StringProperty::New("Segmentation")); - this->GetDataStorage()->Add(m_SegmentationNode, nodes[0]); + this->GetDataStorage()->Add(m_SegmentationNode, m_Nodes[0]); // Calculate features - std::vector rawImages; - for (const auto& node : nodes) + for (const auto node : m_Nodes) { - rawImages.push_back(dynamic_cast(node->GetData())); + mitk::Image::Pointer currentImage = dynamic_cast(node->GetData()); + QFuture>> future; + future = QtConcurrent::run(this, &ActiveLearning::CalculateFeatures, currentImage); + auto futureWatcher = new QFutureWatcher>>(); + futureWatcher->setFuture(future); + connect(futureWatcher, SIGNAL(finished()), this, SLOT(OnInitializationFinished())); + m_FeatureCalculationWatchers.push_back(futureWatcher); } - m_FeatureCalculationFuture = QtConcurrent::run(this, &ActiveLearning::CalculateFeatures, rawImages); - m_FeatureCalculationWatcher.setFuture(m_FeatureCalculationFuture); // Interactor auto activeLearningLib = us::ModuleRegistry::GetModule("MitkCLActiveLearning"); m_Interactor = mitk::ActiveLearningInteractor::New(); m_Interactor->LoadStateMachine("Paint.xml", activeLearningLib); m_Interactor->SetEventConfig("PaintConfig.xml", activeLearningLib); m_Interactor->SetDataNode(m_AnnotationNode); // Automatically add first label OnAddLabelPushButtonClicked(); m_Controls.m_LabelControlsFrame->setVisible(true); m_Controls.m_InitializePushButton->setHidden(true); m_Active = true; } /* ================================================================== * PUBLIC * =============================================================== */ ActiveLearning::ActiveLearning() : m_Parent(nullptr), m_AnnotationImage(nullptr), + m_AnnotationNode(nullptr), + m_PredictionImage(nullptr), + m_PredictionNode(nullptr), + m_SegmentationImage(nullptr), + m_SegmentationNode(nullptr), m_Active(false) { } ActiveLearning::~ActiveLearning() { } void ActiveLearning::CreateQtPartControl( QWidget *parent ) { m_Controls.setupUi(parent); m_Parent = parent; // Label model m_LabelListModel = new QStandardItemModel(0, 3, this); m_Controls.m_LabelTableView->setModel(m_LabelListModel); m_Controls.m_LabelTableView->horizontalHeader()->setDefaultSectionSize(20); m_Controls.m_LabelTableView->verticalHeader()->setDefaultSectionSize(20); NotEditableDelegate* itemDelegate = new NotEditableDelegate(parent); m_Controls.m_LabelTableView->setItemDelegateForColumn(1, itemDelegate); connect(m_Controls.m_LabelTableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnColorIconDoubleClicked(QModelIndex))); connect(m_Controls.m_LabelTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(OnLabelListSelectionChanged(QItemSelection, QItemSelection))); connect(m_LabelListModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this, SLOT(OnLabelNameChanged(QModelIndex, QModelIndex))); // Buttons connect(m_Controls.m_InitializePushButton, SIGNAL(clicked()), this, SLOT(Initialize())); connect(m_Controls.m_AddLabelPushButton, SIGNAL(clicked()), this, SLOT(OnAddLabelPushButtonClicked())); connect(m_Controls.m_RemoveLabelPushButton, SIGNAL(clicked()), this, SLOT(OnRemoveLabelPushButtonClicked())); connect(m_Controls.m_PaintToolButton, SIGNAL(clicked()), this, SLOT(OnPaintToolButtonClicked())); connect(m_Controls.m_EraseToolButton, SIGNAL(clicked()), this, SLOT(OnEraseToolButtonClicked())); - // Future watchers - connect(&m_FeatureCalculationWatcher, SIGNAL(finished()), - this, SLOT(OnInitializationFinished())); - // Set start configuration m_Controls.m_LabelControlsFrame->setVisible(false); SetInitializeReady(false); } void ActiveLearning::ResetLabels() { // Remove all labels but the first for (auto it=m_AnnotationImage->GetActiveLabelSet()->IteratorBegin(); it!=m_AnnotationImage->GetActiveLabelSet()->IteratorConstEnd(); it++) { if (it->first != 0) { m_AnnotationImage->GetActiveLabelSet()->RemoveLabel(it->first); } } // Fill with labels from list for (int i=0; irowCount(); i++) { QString name = m_LabelListModel->item(i, 2)->text(); m_LabelListModel->item(i, 1)->setText(QString::number(i + 1)); QColor color = m_LabelListModel->item(i)->background().color(); m_AnnotationImage->GetActiveLabelSet()->AddLabel(name.toStdString(), QColorToMitkColor(color)); } } -std::vector ActiveLearning::CalculateFeatures(std::vector inputVector) +std::vector > ActiveLearning::CalculateFeatures(const mitk::Image::Pointer inputImage) { + std::vector> result; + // TODO: Get features from preference page std::vector sigmas = {0.7, 1.6}; - const int dim = inputVector[0]->GetDimension(); - typedef itk::Image FeatureImageType; - std::vector rawVectorITK; - std::vector outputVector; - - // Cast input images to float - for (auto it = inputVector.begin(); it != inputVector.end(); it++) + for (auto sigma : sigmas) { - FeatureImageType::Pointer currentITK; - mitk::Image::Pointer currentMITK; - mitk::CastToItkImage(*it, currentITK); - rawVectorITK.push_back(currentITK); - mitk::CastToMitkImage(currentITK, currentMITK); - outputVector.push_back(currentMITK); + std::stringstream ss; + + auto gaussImage = mitk::Image::New(); + AccessByItk_n(inputImage, GaussianSmoothing, (sigma, gaussImage)); + ss << "GaussianSmoothing (" << std::fixed << std::setprecision(2) << sigma << ")"; + result.push_back(std::pair(gaussImage, ss.str())); + ss.str(""); + + auto gradMagImage = mitk::Image::New(); + AccessByItk_n(inputImage, GaussianGradientMagnitude, (sigma, gradMagImage)); + ss << "GaussianGradientMagnitude (" << std::fixed << std::setprecision(2) << sigma << ")"; + result.push_back(std::pair(gradMagImage, ss.str())); + ss.str(""); } - // Gaussian Smoothing - auto gaussianSmoothing = itk::DiscreteGaussianImageFilter::New(); - for (auto image = rawVectorITK.begin(); image != rawVectorITK.end(); image++) - { - for (auto sigma = sigmas.begin(); sigma != sigmas.end(); sigma++) - { - gaussianSmoothing->SetInput(*image); - gaussianSmoothing->SetVariance(*sigma); - gaussianSmoothing->Update(); - mitk::Image::Pointer currentImage; - mitk::CastToMitkImage(gaussianSmoothing->GetOutput(), currentImage); - outputVector.push_back(currentImage); - } - } - - return outputVector; + return result; } const std::string ActiveLearning::VIEW_ID = "org.mitk.views.activelearning"; /* ================================================================== * PROTECTED SLOTS * =============================================================== */ void ActiveLearning::OnAddLabelPushButtonClicked() { QString labelName = QString("Label ") + QString::number(m_AnnotationImage->GetActiveLabelSet()->ReverseIteratorBegin()->first + 1); QColor labelColor = Qt::GlobalColor(m_LabelListModel->rowCount() % 12 + 7); // We only want Qt default colors 7 to 18 // Create icon QStandardItem* colorSquare = new QStandardItem; colorSquare->setBackground(labelColor); colorSquare->setEditable(false); QPixmap colorPixmap(20, 20); colorPixmap.fill(labelColor); colorSquare->setIcon(QIcon(colorPixmap)); // Key is the highest existing key + 1 int value = (int)m_AnnotationImage->GetActiveLabelSet()->ReverseIteratorBegin()->first + 1; QStandardItem* valueItem = new QStandardItem(); valueItem->setText(QString::number(value)); // Create label item QStandardItem* label = new QStandardItem(labelName); // Add to image m_AnnotationImage->GetActiveLabelSet()->AddLabel(labelName.toStdString(), QColorToMitkColor(labelColor)); PrintAllLabels(m_AnnotationImage); // Make list and insert QList list; list.append(colorSquare); list.append(valueItem); list.append(label); m_LabelListModel->appendRow(list); // If this is the first label, we activate the paint button // We also have to set the data node color for this one, because for 1 values that color seems to define the rendered color if (m_LabelListModel->rowCount() == 1) { OnPaintToolButtonClicked(); m_AnnotationNode->SetColor(QColorToMitkColor(labelColor)); } // Select newly added label m_Controls.m_LabelTableView->selectRow(m_LabelListModel->rowCount() - 1); } void ActiveLearning::OnRemoveLabelPushButtonClicked() { QItemSelectionModel* selection = m_Controls.m_LabelTableView->selectionModel(); if (selection->hasSelection()) { unsigned int removeIndex = selection->selectedRows().first().row(); QString removeMessage = QString("Remove label '") + m_LabelListModel->item(removeIndex, 2)->text() + QString("'?"); QMessageBox::StandardButton removeReply; removeReply = QMessageBox::question(m_Parent, "Remove Label", removeMessage, QMessageBox::Yes | QMessageBox::No); if (removeReply == QMessageBox::Yes) { // if there are no annotations, reset labels if (m_Interactor->IsUsed()) { std::vector labels; labels.push_back(m_LabelListModel->item(removeIndex, 1)->text().toInt()); m_AnnotationImage->RemoveLabels(labels); m_LabelListModel->removeRow(removeIndex); } else { m_LabelListModel->removeRow(removeIndex); ResetLabels(); } PrintAllLabels(m_AnnotationImage); } } } void ActiveLearning::OnPaintToolButtonClicked() { m_Controls.m_PaintToolButton->setChecked(true); QItemSelectionModel* selection = m_Controls.m_LabelTableView->selectionModel(); int row(0); if (selection->hasSelection()) { row = selection->selectedRows().first().row(); } else { m_Controls.m_LabelTableView->selectRow(0); } m_Interactor->SetPaintingPixelValue(m_LabelListModel->item(row, 1)->text().toInt()); m_AnnotationImage->GetActiveLabelSet()->SetActiveLabel(m_LabelListModel->item(row, 1)->text().toInt()); } void ActiveLearning::OnEraseToolButtonClicked() { m_Controls.m_EraseToolButton->setChecked(true); m_Interactor->SetPaintingPixelValue(0); m_AnnotationImage->GetActiveLabelSet()->SetActiveLabel(0); } void ActiveLearning::OnActivateGuidancePushButtonToggled(bool toggled) { } void ActiveLearning::OnSaveSegmentationPushButtonClicked() { } void ActiveLearning::OnSavePredictionsPushButtonClicked() { } void ActiveLearning::OnExportSegmentationPushButtonClicked() { } void ActiveLearning::OnExportPredictionsPushButtonClicked() { } void ActiveLearning::OnColorIconDoubleClicked(const QModelIndex& index) { // Check if click is really from color icon if (index.column() != 0) { return; } else { // Color change dialog QColor setColor = QColorDialog::getColor(m_LabelListModel->itemFromIndex(index)->background().color(), m_Parent, "Select Label Color"); if (setColor.isValid()) { m_LabelListModel->itemFromIndex(index)->setBackground(setColor); QPixmap colorPixmap(20, 20); colorPixmap.fill(setColor); m_LabelListModel->itemFromIndex(index)->setIcon(QIcon(colorPixmap)); // Set color on label m_AnnotationImage->GetActiveLabelSet()->GetLabel(m_LabelListModel->item(index.row(), 1)->text().toInt())->SetColor(QColorToMitkColor(setColor)); m_AnnotationImage->GetActiveLabelSet()->UpdateLookupTable(m_LabelListModel->item(index.row(), 1)->text().toInt()); PrintAllLabels(m_AnnotationImage); // If this is the label with value 1 we have to change the data node color if (m_LabelListModel->item(index.row(), 1)->text().toInt() == 1) { m_AnnotationNode->SetColor(QColorToMitkColor(setColor)); } } } } void ActiveLearning::OnLabelListSelectionChanged(const QItemSelection& selected, const QItemSelection& /*deselected*/) { if (selected.empty()) return; // This assumes that only one item can be selected (single selection table view) try { int labelValue = m_LabelListModel->item(selected.indexes()[0].row(), 1)->text().toInt(); m_Interactor->SetPaintingPixelValue(labelValue); m_AnnotationImage->GetActiveLabelSet()->SetActiveLabel(labelValue); } catch (...) { m_Interactor->SetPaintingPixelValue(0); m_AnnotationImage->GetActiveLabelSet()->SetActiveLabel(0); } } void ActiveLearning::OnLabelNameChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/) { auto item = m_LabelListModel->itemFromIndex(topLeft); if (item->column() != 2) return; m_AnnotationImage->GetActiveLabelSet()->GetLabel(m_LabelListModel->item(item->row(), 1)->text().toInt())->SetName(item->text().toStdString()); } void ActiveLearning::OnInitializationFinished() { - m_FeatureImageVector = m_FeatureCalculationWatcher.result(); + // Check if all futures are finished + for (auto watcher : m_FeatureCalculationWatchers) + { + if (watcher->isFinished() == false) {return;} + } + + // Empty feature vector + m_FeatureImageVector.clear(); + + // Insert features into feature vector and data storage + for (unsigned int i=0; iresult(); + for (unsigned int j=0; jSetData(result[j].first); + node->SetName(result[j].second); + node->SetBoolProperty("helper object", true); + node->SetVisibility(false); + this->GetDataStorage()->Add(node, m_Nodes[i]); + } + } + + // Show controls m_Controls.m_LabelControlsFrame->setVisible(true); m_Controls.m_InitializePushButton->setHidden(true); MITK_INFO << "Features: " << m_FeatureImageVector.size(); + + // Delete watchers + for (auto watcher : m_FeatureCalculationWatchers) + { + delete watcher; + } + m_FeatureCalculationWatchers.clear(); } /* ================================================================== * PROTECTED * =============================================================== */ void ActiveLearning::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& nodes) { if (!SelectionAllImages(nodes)) { SetInitializeReady(false); return; } if (nodes.length() >= 2) { // First selection is the reference (could be any other) mitk::Image::Pointer referenceImage = dynamic_cast(nodes[0]->GetData()); mitk::BaseGeometry* referenceGeometry = referenceImage->GetTimeGeometry()->GetGeometryForTimeStep(0); // Adjust for multiple timesteps for (int i=1; i(nodes[i]->GetData()); mitk::BaseGeometry* currentGeometry = currentImage->GetTimeGeometry()->GetGeometryForTimeStep(0); // Adjust for multiple timesteps if (!mitk::Equal(*currentGeometry, *referenceGeometry, mitk::eps, true)) { SetInitializeReady(false); return; } } } // All nodes have the same geometry, allow init SetInitializeReady(true); } void ActiveLearning::SetFocus() { } /* ================================================================== * PRIVATE * =============================================================== */ void ActiveLearning::SetInitializeReady(bool ready) { if (ready) { // get selection, check again just to be sure auto nodes = this->GetDataManagerSelection(); if (!SelectionAllImages(nodes)) return; m_Controls.m_InitializePushButton->setEnabled(true); if (!m_Active) { QString nameList = QString::fromStdString(nodes[0]->GetName()); if (nodes.length() >= 2) { for (int i=1; i"); nameList += QString::fromStdString(nodes[i]->GetName()); } } m_Controls.m_InitializeLabel->setText(nameList); } } else { m_Controls.m_InitializePushButton->setDisabled(true); if (!m_Active) { m_Controls.m_InitializeLabel->setText("Selected images must have matching geometries"); } } } diff --git a/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.h b/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.h index d40a37cda7..7db3301237 100644 --- a/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.h +++ b/Plugins/org.mitk.gui.qt.activelearning/src/internal/QmitkActiveLearning.h @@ -1,137 +1,137 @@ /*=================================================================== 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 ActiveLearning_h #define ActiveLearning_h #include #include #include "ui_QmitkActiveLearningControls.h" // Qt #include #include #include #include // MITK #include #include /** \brief ActiveLearning \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ // Just a helper class class NotEditableDelegate : public QItemDelegate { Q_OBJECT public: explicit NotEditableDelegate(QObject* parent = nullptr) : QItemDelegate(parent) {} protected: QWidget* createEditor(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const {return Q_NULLPTR;} }; class ActiveLearning : public QmitkAbstractView { Q_OBJECT public slots: void Initialize(); public: ActiveLearning(); ~ActiveLearning(); void CreateQtPartControl(QWidget *parent) override; void ResetLabels(); - std::vector CalculateFeatures(std::vector inputVector); + std::vector> CalculateFeatures(const mitk::Image::Pointer inputImage); static const std::string VIEW_ID; QStandardItemModel* m_LabelListModel; protected slots: void OnAddLabelPushButtonClicked(); void OnRemoveLabelPushButtonClicked(); void OnPaintToolButtonClicked(); void OnEraseToolButtonClicked(); void OnActivateGuidancePushButtonToggled(bool toggled); void OnSaveSegmentationPushButtonClicked(); void OnSavePredictionsPushButtonClicked(); void OnExportSegmentationPushButtonClicked(); void OnExportPredictionsPushButtonClicked(); void OnColorIconDoubleClicked(const QModelIndex& index); void OnLabelListSelectionChanged(const QItemSelection& selected, const QItemSelection& /*deselected*/); void OnLabelNameChanged(const QModelIndex& topLeft, const QModelIndex& /*bottomRight*/); void OnInitializationFinished(); protected: void OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& nodes) override; void SetFocus() override; Ui::ActiveLearningControls m_Controls; QWidget* m_Parent; mitk::LabelSetImage::Pointer m_AnnotationImage; mitk::DataNode::Pointer m_AnnotationNode; mitk::Image::Pointer m_PredictionImage; mitk::DataNode::Pointer m_PredictionNode; mitk::LabelSetImage::Pointer m_SegmentationImage; mitk::DataNode::Pointer m_SegmentationNode; std::vector m_FeatureImageVector; - QFuture> m_FeatureCalculationFuture; - QFutureWatcher> m_FeatureCalculationWatcher; + std::vector>>*> m_FeatureCalculationWatchers; private: void SetInitializeReady(bool ready); bool m_Active; mitk::ActiveLearningInteractor::Pointer m_Interactor; + QList m_Nodes; }; #endif // ActiveLearning_h