diff --git a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/MitkRegionIterator.h b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/MitkRegionIterator.h index 775ce2f7c1..13c0587375 100644 --- a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/MitkRegionIterator.h +++ b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/MitkRegionIterator.h @@ -1,117 +1,133 @@ /*=================================================================== 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 MitkRegionIterator_h #define MitkRegionIterator_h template class MitkRegionIterator { private: ImageType* m_Image; int m_Radius; + float m_Spacing_x, m_Spacing_y, m_Spacing_z; public: MitkRegionIterator(ImageType* image, int radius) :m_Image(image), m_Radius(radius) {} void SetRadius(int radius) { m_Radius = radius; } + void SetSpacing(float x, float y, float z) + { + m_Spacing_x = x; + m_Spacing_y = y; + m_Spacing_z = z; + } + int GetMeanPixelValueForRegion(IndexType seedIndex) { int mean = 0; int sum = 0; int count = 0; + int radius_x = m_Radius / m_Spacing_x; + int radius_y = m_Radius / m_Spacing_y; + int radius_z = m_Radius / m_Spacing_z; + //x-Direction - for (int i = -m_Radius; i <= m_Radius; i++) + for (int i = -radius_x; i <= radius_x; i++) { IndexType localSeedIndex; localSeedIndex[0] = seedIndex[0] + i; //y-Direction - for (int j = -m_Radius; j <= m_Radius; j++) + for (int j = -radius_y; j <= radius_y; j++) { localSeedIndex[1] = seedIndex[1] + j; //z-Direction - for (int k = -m_Radius; k <= m_Radius; k++) + for (int k = -radius_z; k <= radius_z; k++) { localSeedIndex[2] = seedIndex[2] + k; //MITK_INFO << m_Image->GetPixel(localSeedIndex); sum += m_Image->GetPixel(localSeedIndex); count++; } } } mean = sum / count; return mean; } int GetThresholdByStdDivMethod(IndexType seedIndex) { int thresholdRange = 0; double* pixelValueVector = new double[1000]; int count = 0; double sum = 0; + int radius_x = m_Radius / m_Spacing_x; + int radius_y = m_Radius / m_Spacing_y; + int radius_z = m_Radius / m_Spacing_z; + //x-Direction - for (int i = -m_Radius; i <= m_Radius; i++) + for (int i = -radius_x; i <= radius_x; i++) { IndexType localSeedIndex; localSeedIndex[0] = seedIndex[0] + i; //y-Direction - for (int j = -m_Radius; j <= m_Radius; j++) + for (int j = -radius_y; j <= radius_y; j++) { localSeedIndex[1] = seedIndex[1] + j; //z-Direction - for (int k = -m_Radius; k <= m_Radius; k++) + for (int k = -radius_z; k <= radius_z; k++) { localSeedIndex[2] = seedIndex[2] + k; int currentValue = m_Image->GetPixel(localSeedIndex); sum += currentValue; pixelValueVector[count++] = currentValue; //MITK_INFO << m_Image->GetPixel(localSeedIndex); } } } int mean = sum / count; int quadraticSum = 0; for (int i = 0; i < count; i++) { double helper = (pixelValueVector[i] - mean)*(pixelValueVector[i] - mean); quadraticSum += helper; } double SD = std::sqrt(quadraticSum / count); thresholdRange = SD; return thresholdRange; } }; #endif //MitkRegionIterator_h \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.cpp b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.cpp index 429b4d140a..bb35e94178 100644 --- a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.cpp +++ b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.cpp @@ -1,406 +1,443 @@ /*=================================================================== 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 "QmitkRegionGrowingView.h" //! [cpp-includes] // Qmitk #include "QmitkPointListWidget.h" #include "QmitkRenderWindow.h" // MITK #include "mitkColorProperty.h" #include "mitkITKImageImport.h" #include "mitkImageAccessByItk.h" #include "mitkImageCast.h" #include "mitkProperties.h" #include "itkMaskImageFilter.h" #include "itkRegionOfInterestImageFilter.h" #include "itkNeighborhoodConnectedImageFilter.h" // ITK #include //! [cpp-includes] // Qt #include #include "MitkRegionIterator.h" const std::string QmitkRegionGrowingView::VIEW_ID = "org.mitk.views.example.regiongrowing"; QmitkRegionGrowingView::QmitkRegionGrowingView() : m_PointListWidget(NULL), m_ThresholdMethod(ThresholdMethod::easy) { } void QmitkRegionGrowingView::SetFocus() { m_Controls->buttonPerformImageProcessing->setFocus(); } void QmitkRegionGrowingView::CreateQtPartControl(QWidget *parent) { m_Controls = new Ui::QmitkRegionGrowingViewControls; // create GUI widgets from the Qt Designer's .ui file m_Controls->setupUi(parent); //add different methods for threshold determination m_Controls->comboBoxThresholdMethod->addItem("easy"); m_Controls->comboBoxThresholdMethod->addItem("stddiv"); connect(m_Controls->buttonPerformImageProcessing, SIGNAL(clicked()), this, SLOT(OnStartRegionGrowing())); connect(m_Controls->checkBoxCustomRange, SIGNAL(clicked(bool)), this, SLOT(OnUseCustomRange(bool))); connect(m_Controls->pushButtonClearPointList, SIGNAL(clicked()), this, SLOT(OnClearPointSet())); connect(m_Controls->comboBoxThresholdMethod, SIGNAL(currentIndexChanged(int)), this, SLOT(OnSetThresholdMethod(int))); + connect(m_Controls->pushButtonAddPointList, SIGNAL(clicked()), this, SLOT(OnAddPointSet())); //! [cpp-createqtpartcontrol] // create a QmitkPointListWidget and add it to the widget created from .ui file m_PointListWidget = new QmitkPointListWidget(); m_Controls->verticalLayout->addWidget(m_PointListWidget, 1); // retrieve a possibly existing IRenderWindowPart if (mitk::IRenderWindowPart *renderWindowPart = GetRenderWindowPart()) { // let the point set widget know about the render window part (crosshair updates) RenderWindowPartActivated(renderWindowPart); } mitk::DataNode::Pointer pointSetNode = this->GetDataStorage()->GetNamedNode("seed points for region growing"); m_PointSet = mitk::PointSet::New(); if (pointSetNode == nullptr) { // create a new DataNode containing a PointSet with some interaction pointSetNode = mitk::DataNode::New(); pointSetNode->SetData(mitk::PointSet::New()); pointSetNode->SetName("seed points for region growing"); pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true)); pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024)); pointSetNode->SetProperty("globalObject_RWM", mitk::BoolProperty::New(true)); // add the pointset to the data storage (for rendering and access by other modules) GetDataStorage()->Add(pointSetNode); } // tell the GUI widget about the point set m_PointListWidget->SetPointSetNode(pointSetNode); //! [cpp-createqtpartcontrol] m_Controls->buttonPerformImageProcessing->setEnabled(false); + m_Controls->pushButtonAddPointList->setEnabled(false); + m_Controls->progressBar->setMinimum(0); + m_Controls->progressBar->setMaximum(0); + m_Controls->progressBar->hide(); } void QmitkRegionGrowingView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList &nodes) { // iterate all selected objects, adjust warning visibility foreach (mitk::DataNode::Pointer node, nodes) { if (node.IsNotNull() && dynamic_cast(node->GetData())) { m_Controls->labelWarning->setVisible(false); m_Controls->buttonPerformImageProcessing->setEnabled(true); return; } + else if (node.IsNotNull() && dynamic_cast(node->GetData())) + { + m_Controls->pushButtonAddPointList->setEnabled(true); + return; + } } m_Controls->labelWarning->setVisible(true); m_Controls->buttonPerformImageProcessing->setEnabled(false); + m_Controls->pushButtonAddPointList->setEnabled(false); } void QmitkRegionGrowingView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) { // let the point set widget know about the slice navigation controllers // in the active render window part (crosshair updates) foreach (QmitkRenderWindow *renderWindow, renderWindowPart->GetQmitkRenderWindows().values()) { m_PointListWidget->AddSliceNavigationController(renderWindow->GetSliceNavigationController()); } } void QmitkRegionGrowingView::RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) { foreach (QmitkRenderWindow *renderWindow, renderWindowPart->GetQmitkRenderWindows().values()) { m_PointListWidget->RemoveSliceNavigationController(renderWindow->GetSliceNavigationController()); } } void QmitkRegionGrowingView::OnStartRegionGrowing() { + m_Controls->progressBar->show(); + m_Controls->progressBar->setValue(0); + QList nodes = this->GetDataManagerSelection(); if (nodes.empty()) return; mitk::DataNode *node = nodes.front(); if (!node) { // Nothing selected. Inform the user and return QMessageBox::information(NULL, "Template", "Please load and select an image before starting image processing."); return; } // here we have a valid mitk::DataNode // a node itself is not very useful, we need its data item (the image) mitk::BaseData *data = node->GetData(); if (data) { // test if this data item is an image or not (could also be a surface or something totally different) mitk::Image *image = dynamic_cast(data); if (image) { //! [cpp-doimageprocessing] // So we have an image. Let's see if the user has set some seed points already if (m_PointListWidget->GetPointSet()->GetSize() == 0) { // no points there. Not good for region growing QMessageBox::information(NULL, "Region growing functionality", "Please set some seed points inside the image first.\n" "(hold Shift key and click left mouse button inside the image.)"); return; } // actually perform region growing. Here we have both an image and some seed points AccessByItk_1( image, ItkImageProcessing, image->GetGeometry()) // some magic to call the correctly templated function - //! [cpp-doimageprocessing] + //! [cpp-doimageprocessing] } } + + m_Controls->progressBar->hide(); } void QmitkRegionGrowingView::OnUseCustomRange(bool useCustomRange) { m_Controls->spinBoxMax->setEnabled(useCustomRange); m_Controls->spinBoxMin->setEnabled(useCustomRange); } +void QmitkRegionGrowingView::OnAddPointSet() +{ + QList pointSetNodeList = this->GetDataManagerSelection(); + + mitk::DataNode::Pointer pointSetNode = pointSetNodeList.first(); + //mitk::DataNode::Pointer pointSetNode = this->GetDataStorage()->GetNamedNode("seed points for region growing"); + + // tell the GUI widget about the point set + m_PointListWidget->SetPointSetNode(pointSetNode); +} + void QmitkRegionGrowingView::OnClearPointSet() { QMessageBox::StandardButton reply; reply = QMessageBox::question(nullptr, "Test", "Are you sure?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (reply == QMessageBox::Yes) { m_PointListWidget->GetPointSet()->Clear(); } else { //Clearing point set canceled } } //! [cpp-itkimageaccess] template void QmitkRegionGrowingView::ItkImageProcessing(itk::Image *itkImage, mitk::BaseGeometry *imageGeometry) { typedef itk::Image InputImageType; //typedef typename InputImageType::IndexType IndexType; typedef typename InputImageType::RegionType RegionType; typedef typename InputImageType::RegionType::IndexType IndexType; typedef typename InputImageType::RegionType::SizeType SizeType; // instantiate an ITK region growing filter, set its parameters typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); typedef itk::NeighborhoodConnectedImageFilter NeighborhoodConnectedImageFilterType; NeighborhoodConnectedImageFilterType::Pointer neighborhoodConnectedFilter = NeighborhoodConnectedImageFilterType::New(); // determine a thresholding interval IndexType seedIndex; mitk::PointSet::PointsContainer *points = m_PointListWidget->GetPointSet()->GetPointSet()->GetPoints(); + int iteration = 0; + m_Controls->progressBar->setMaximum(points->Size()); for (mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); pointsIterator != points->End(); ++pointsIterator) { + m_Controls->progressBar->setValue((int) iteration++); + // first test if this point is inside the image at all if (!imageGeometry->IsInside(pointsIterator.Value())) { continue; } TPixel min(std::numeric_limits::max()); TPixel max(std::numeric_limits::min()); if (m_Controls->checkBoxCustomRange->isChecked()) { max = m_Controls->spinBoxMax->value(); min = m_Controls->spinBoxMin->value(); } // convert world coordinates to image indices imageGeometry->WorldToIndex(pointsIterator.Value(), seedIndex); //================================================= MitkRegionIterator mitkRegionIterator(itkImage, 1); int thresholdRange = 0; //================================================= // get the pixel value at this point TPixel currentPixelValue = itkImage->GetPixel(seedIndex); if (!m_Controls->checkBoxCustomRange->isChecked()) { switch (m_ThresholdMethod) { case 0: // adjust minimum and maximum values if (currentPixelValue > max) max = currentPixelValue; if (currentPixelValue < min) min = currentPixelValue; thresholdRange = 130; break; case 1: // adjust minimum and maximum values if (currentPixelValue > max) max = currentPixelValue; if (currentPixelValue < min) min = currentPixelValue; //regionGrower->SetConnectivity(RegionGrowingFilterType::ConnectivityEnumType::FaceConnectivity); - mitkRegionIterator.SetRadius(3); + mitkRegionIterator.SetRadius(4); + mitkRegionIterator.SetSpacing( + itkImage->GetSpacing()[0], + itkImage->GetSpacing()[1], + itkImage->GetSpacing()[2]); thresholdRange = mitkRegionIterator.GetThresholdByStdDivMethod(seedIndex); break; } if (min < thresholdRange) { - min = 1; + min = 0; } else { min -= thresholdRange; } max += thresholdRange; } m_Controls->spinBoxMin->setValue(min); m_Controls->spinBoxMax->setValue(max); MITK_INFO << "Values between min:" << min << " and max:" << max; regionGrower->SetInput(itkImage); //not possible to set requested region for regiongrower. It is set to LargestPossibleRegion in Update() //regionGrower->GetOutput()->SetRequestedRegion(region); //regionGrower->GetOutput()->UpdateOutputInformation(); // set thresholds and execute filter regionGrower->AddSeed(seedIndex); regionGrower->SetLower(min); regionGrower->SetUpper(max); regionGrower->SetConnectivity(RegionGrowingFilterType::FaceConnectivity); regionGrower->Update(); int regionGrowingDiameter = 20; //Define region for regiongrowing IndexType centerIndex = seedIndex; centerIndex[0] -= regionGrowingDiameter / 2; centerIndex[1] -= regionGrowingDiameter / 2; centerIndex[2] -= regionGrowingDiameter / 4; //Set maximum region fpr regiongrowing SizeType size; size.Fill(regionGrowingDiameter); size[0] = regionGrowingDiameter; size[1] = regionGrowingDiameter; size[2] = regionGrowingDiameter/2; RegionType region(centerIndex, size); region.Crop(itkImage->GetLargestPossibleRegion()); typedef itk::RegionOfInterestImageFilter< InputImageType, InputImageType > ROIFilterType; ROIFilterType::Pointer roiFilter = ROIFilterType::New(); roiFilter->SetRegionOfInterest(region); roiFilter->SetInput(regionGrower->GetOutput()); roiFilter->Update(); roiFilter->UpdateLargestPossibleRegion(); //neighborhoodConnectedFilter->SetInput(itkImage); //neighborhoodConnectedFilter->SetLower(min); //neighborhoodConnectedFilter->SetUpper(max); //InputImageType::SizeType radius; //radius[0] = 1; //radius[1] = 1; //radius[2] = 1; //neighborhoodConnectedFilter->SetRadius(radius); //neighborhoodConnectedFilter->SetSeed(seedIndex); //neighborhoodConnectedFilter->SetReplaceValue(255); //neighborhoodConnectedFilter->Update(); mitk::Image::Pointer resultImage; mitk::CastToMitkImage(roiFilter->GetOutput(), resultImage); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(resultImage); // set some properties newNode->SetProperty("binary", mitk::BoolProperty::New(true)); newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); newNode->SetProperty("color", mitk::ColorProperty::New(1.0, 0.0, 0.0)); newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); newNode->SetProperty("layer", mitk::IntProperty::New(1)); newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); newNode->SetProperty("globalObject_RWM", mitk::BoolProperty::New(true)); // add result to data tree this->GetDataStorage()->Add(newNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); regionGrower->ClearSeeds(); } + + m_Controls->progressBar->setValue(points->Size()); } //! [cpp-itkimageaccess] void QmitkRegionGrowingView::OnSetThresholdMethod(int index) { int currentIndex = m_Controls->comboBoxThresholdMethod->currentIndex(); switch (currentIndex) { case 0: m_ThresholdMethod = ThresholdMethod::easy; break; case 1: m_ThresholdMethod = ThresholdMethod::stddiv; break; default: m_ThresholdMethod = ThresholdMethod::easy; break; } } diff --git a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.h b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.h index 37892b22fb..062f39dad1 100644 --- a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.h +++ b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingView.h @@ -1,104 +1,106 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkRegionGrowingView_h #define QmitkRegionGrowingView_h #include #include #include "ui_QmitkRegionGrowingViewControls.h" //! [includes] #include "mitkIRenderWindowPartListener.h" #include "mitkPointSet.h" #include class QmitkPointListWidget; //! [includes] /** \brief QmitkRegionGrowingView \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class QmitkRegionGrowingView : public QmitkAbstractView, public mitk::IRenderWindowPartListener { // 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; QmitkRegionGrowingView(); protected slots: /// \brief Called when the user clicks the GUI button void OnStartRegionGrowing(); void OnUseCustomRange(bool useCustomRange); + void OnAddPointSet(); + void OnClearPointSet(); void OnSetThresholdMethod(int index); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList &nodes) override; //! [render-window-part-listener] void RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) override; void RenderWindowPartDeactivated(mitk::IRenderWindowPart *renderWindowPart) override; //! [render-window-part-listener] Ui::QmitkRegionGrowingViewControls* m_Controls; private: //! [itkimageprocessing] /** \brief ITK image processing function This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of a given MITK image and calls this function for further processing (in our case region growing) */ template void ItkImageProcessing(itk::Image *itkImage, mitk::BaseGeometry *imageGeometry); //! [itkimageprocessing] //template //void iterateOverNeighborhood(itk::Image *itkImage, IndexType seedIndex, int radius); //! [members] /// \brief This is the actual seed point data object mitk::PointSet::Pointer m_PointSet; QmitkPointListWidget *m_PointListWidget; //! [members] enum ThresholdMethod { easy, stddiv } m_ThresholdMethod; }; #endif // QmitkRegionGrowingView_h diff --git a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui index b345d6c345..d4a9a81ac6 100644 --- a/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui @@ -1,111 +1,131 @@ QmitkRegionGrowingViewControls 0 0 - 222 - 161 + 289 + 215 0 0 QmitkTemplate QLabel { color: rgb(255, 0, 0) } Please select an image! Customize Range ClearPoint List + + + + Add selected + + + Min false 99999 Max false 99999 Do image processing Start Region Growing! + + + + true + + + 24 + + + false + + +