X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvToolROIManager.cxx;h=7f544a5e31f8d1493b21fa080daa66ca1f4bc845;hb=3fd15028ab81e6746d3af96695526d7d973a26c8;hp=77a65d3543c37ee3db2d4fac2e76b500ac24b4fa;hpb=29c90b5fbd7ecd5d8375e02b7a03734c4fdbc806;p=clitk.git diff --git a/vv/vvToolROIManager.cxx b/vv/vvToolROIManager.cxx index 77a65d3..7f544a5 100644 --- a/vv/vvToolROIManager.cxx +++ b/vv/vvToolROIManager.cxx @@ -22,6 +22,8 @@ #include "vvROIActor.h" #include "vvSlicer.h" #include "vvROIActor.h" +#include "vvMeshReader.h" +#include "vvStructSelector.h" // Qt #include @@ -41,20 +43,54 @@ ADD_TOOL(vvToolROIManager); //------------------------------------------------------------------------------ vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f): - // vvToolWidgetBase(parent, f), - // if Qt::Widget -> No dialog in this case (in tab) ; PB = "invisible widget on menu" ! - // if "f" normal widget - QWidget(parent->GetTab()->widget(4)), + QWidget(parent->GetTab()), vvToolBase(parent), Ui::vvToolROIManager() { - // Insert the current QWidget into the tab layout (required) - QWidget * mother = qFindChild(parent->GetTab(), "ROItab"); - mother->layout()->addWidget(this); + // Store parent + mMainWindow = parent; + + // Assume the initial tab ROI index is 2 + mIndexFirstTab = 2; + + // Get the ROI Tab + QWidget * tab = qFindChild(parent->GetTab(), "ROItab"); + + // Set it as current + parent->GetTab()->setCurrentIndex(mIndexFirstTab); + + // Check if widget already used + if (tab->layout()->isEmpty()) { + tab->layout()->addWidget(this); + } + else { + close(); + return; + } // Build the UI Ui_vvToolROIManager::setupUi(this); setAttribute(Qt::WA_DeleteOnClose); + mTree->clear(); + mTree->header()->resizeSection(0, 30); + mGroupBoxROI->setEnabled(false); + + // Temporary disable "Load dicom" button + frame_4->hide(); + + // Set default LUT + mDefaultLUTColor = vtkSmartPointer::New(); + for(int i=0; iGetNumberOfTableValues(); i++) { + double r = (rand()/(RAND_MAX+1.0)); + double v = (rand()/(RAND_MAX+1.0)); + double b = (rand()/(RAND_MAX+1.0)); + mDefaultLUTColor->SetTableValue(i, r, v, b); + } +#include "vvDefaultLut.h" + + // Initialization + mNumberOfVisibleROI = 0; + mNumberOfVisibleContourROI = 0; // Select the current image as the target int i = parent->GetSlicerManagerCurrentIndex(); @@ -65,8 +101,20 @@ vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f) this, SLOT(AnImageIsBeingClosed(vvSlicerManager *))); connect(parent, SIGNAL(SelectedImageHasChanged(vvSlicerManager *)), this, SLOT(SelectedImageHasChanged(vvSlicerManager *))); - - // mMainWindowBase->GetTab()->setTabIcon(mTabNumber, GetToolIcon()); + connect(mOpenBinaryButton, SIGNAL(clicked()), this, SLOT(OpenBinaryImage())); + connect(mOpenDicomButton, SIGNAL(clicked()), this, SLOT(OpenDicomImage())); + connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree())); + connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool))); + connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int))); + connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor())); + connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool))); + connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor())); + connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int))); + connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int))); + connect(mReloadButton, SIGNAL(clicked()), this, SLOT(ReloadCurrentROI())); + connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int))); + connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool))); + connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close())); } //------------------------------------------------------------------------------ @@ -74,7 +122,6 @@ vvToolROIManager::vvToolROIManager(vvMainWindowBase * parent, Qt::WindowFlags f) //------------------------------------------------------------------------------ vvToolROIManager::~vvToolROIManager() { - std::cout << "vvToolROIManager::~vvToolROIManager()" << std::endl; } //------------------------------------------------------------------------------ @@ -94,14 +141,24 @@ void vvToolROIManager::Initialize() { //------------------------------------------------------------------------------ void vvToolROIManager::InputIsSelected(vvSlicerManager *m) { - std::cout << "vvToolROIManager::InputIsSelected()" << std::endl; mSlicerManager = m; - // Signal/slot - connect(mCloseButton, SIGNAL(clicked()), this, SLOT(close())); - // Initialization + mSlicerManager = m; + mCurrentImage = mSlicerManager->GetImage(); + + // Refuse if 4D + if (mCurrentImage->GetNumberOfDimensions() != 3) { + QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet")); + close(); + return; + } + // Change gui + mLabelInputInfo->setText(QString("%1").arg(m->GetFileName().c_str())); + + // Auto display browser to select new contours + OpenBinaryImage(); } //------------------------------------------------------------------------------ @@ -109,14 +166,465 @@ void vvToolROIManager::InputIsSelected(vvSlicerManager *m) //------------------------------------------------------------------------------ void vvToolROIManager::AnImageIsBeingClosed(vvSlicerManager * m) { - if (m == mSlicerManager) close(); + if (m == mSlicerManager) { + close(); + return; + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::close() +{ + // Update to delete actors + UpdateAllContours(); + QWidget::close(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void vvToolROIManager::SelectedImageHasChanged(vvSlicerManager * m) { - if (m != mSlicerManager) hide(); - else show(); + if (m != mSlicerManager) hide(); + else { + show(); + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::OpenBinaryImage() +{ + // Open images + QString Extensions = "Images files ( *.mha *.mhd *.hdr *.his)"; + Extensions += ";;All Files (*)"; + QStringList filename = + QFileDialog::getOpenFileNames(this,tr("Open binary image"), + mMainWindowBase->GetInputPathName(),Extensions); + if (filename.size() == 0) return; + + // For each selected file, open the image + for(int i=0; i filenames; + filenames.push_back(filename[i].toStdString()); + reader->SetInputFilenames(filenames); + reader->Update(vvImageReader::IMAGE); + QApplication::restoreOverrideCursor(); + + if (reader->GetLastError().size() != 0) { + std::cerr << "Error while reading " << filename[i].toStdString() << std::endl; + QString error = "Cannot open file \n"; + error += reader->GetLastError().c_str(); + QMessageBox::information(this,tr("Reading problem"),error); + return; + } + vvImage::Pointer binaryImage = reader->GetOutput(); + AddImage(binaryImage, filename[i].toStdString(), mBackgroundValueSpinBox->value(), + (!mBGModeCheckBox->isChecked())); + mOpenedBinaryImage.push_back(binaryImage); + } + + // Update the contours + UpdateAllContours(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::OpenDicomImage() +{ + DD("OpenDicomImage"); + QString Extensions = "Dicom Files ( *.dcm RS*)"; + Extensions += ";;All Files (*)"; + QString file = QFileDialog::getOpenFileName(this,tr("Merge Images"), + mMainWindow->GetInputPathName(), + Extensions); + if (file.isNull()) return; + + // AddDCStructContour(index, file); + vvMeshReader reader; + reader.SetFilename(file.toStdString()); + vvStructSelector selector; + selector.SetStructures(reader.GetROINames()); + // selector.EnablePropagationCheckBox(); FIXME Disable + + // FIXME : change text -> allow to save binary image + + if (selector.exec()) { + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + reader.SetSelectedItems(selector.getSelectedItems()); + reader.SetImage(mSlicerManager->GetImage()); + reader.Update(); + + // std::vector contours=reader.GetOutput(); + // for (std::vector::iterator i=contours.begin(); + // i!=contours.end(); i++) + // AddContour(index,*i,selector.PropagationEnabled()); + QApplication::restoreOverrideCursor(); + } + + + +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::AddImage(vvImage * binaryImage, std::string filename, + double BG, bool modeBG) +{ + // Check Dimension + int dim = mCurrentImage->GetNumberOfDimensions(); + int bin_dim = binaryImage->GetNumberOfDimensions(); + if (dim < bin_dim) { + std::ostringstream os; + os << "Error. Loaded binary image is " << bin_dim + << "D while selected image is " << dim << "D" << std::endl; + QMessageBox::information(this,tr("Reading problem"),os.str().c_str()); + return; + } + + // Compute roi index + int n = mROIList.size(); + + // Compute the name of the new ROI + std::ostringstream oss; + oss << vtksys::SystemTools::GetFilenameName(vtksys::SystemTools::GetFilenameWithoutLastExtension(filename)); + std::string name = oss.str(); + + // Set color + std::vector color; + color.push_back(1); + color.push_back(0); + color.push_back(0); + + // Create ROI + clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New(); + roi->SetFromBinaryImage(binaryImage, n, name, color, filename); + + // Add a new roi to the list + mROIList.push_back(roi); + + // Set BG or FG mode + if (modeBG) + roi->SetBackgroundValueLabelImage(BG); + else + roi->SetForegroundValueLabelImage(BG); + + // Change color + if (nGetNumberOfTableValues ()) { + double * color = mDefaultLUTColor->GetTableValue(n % mDefaultLUTColor->GetNumberOfTableValues ()); + roi->SetDisplayColor(color[0], color[1], color[2]); + } + + // Add a new roi actor + QSharedPointer actor = QSharedPointer(new vvROIActor); + actor->SetBGMode(modeBG); + actor->SetROI(roi); + actor->SetSlicerManager(mSlicerManager); + actor->Initialize(n+1); // depth is n+1 to start at 1 + mROIActorsList.push_back(actor); + + // CheckBox for "All" + if (actor->IsVisible()) mNumberOfVisibleROI++; + if (actor->IsContourVisible()) mNumberOfVisibleContourROI++; + + // Add ROI in tree + mTreeWidgetList.push_back(QSharedPointer(new QTreeWidgetItem(mTree))); + QTreeWidgetItem * w = mTreeWidgetList.back().data(); + w->setText(0, QString("%1").arg(roi->GetROINumber())); + w->setText(1, QString("%1").arg(roi->GetName().c_str())); + w->setText(3, QString("%1").arg(actor->GetDepth())); + QBrush brush(QColor(roi->GetDisplayColor()[0]*255, + roi->GetDisplayColor()[1]*255, + roi->GetDisplayColor()[2]*255)); + brush.setStyle(Qt::SolidPattern); + w->setBackground(2, brush); + mMapROIToTreeWidget[roi] = w; + mMapTreeWidgetToROI[w] = roi; + mTree->resizeColumnToContents(0); + mTree->resizeColumnToContents(1); + + // Update + UpdateAllROIStatus(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::UpdateAllContours() +{ + // Render loaded ROIs (the first is sufficient) + for(unsigned int i=0; iUpdate(); + } + for(int i=0; iGetNumberOfSlicers(); i++) { + mSlicerManager->GetSlicer(i)->Render(); + } +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::UpdateAllROIStatus() { + int nbVisible = 0; + int nb = mROIList.size(); + for(int i=0; iIsVisible()) { + nbVisible++; + } + } + + // change the states + disconnect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int))); + disconnect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool))); + if (nbVisible == nb) mCheckBoxShowAll->setCheckState(Qt::Checked); + else { + if (nbVisible == 0) mCheckBoxShowAll->setCheckState(Qt::Unchecked); + else mCheckBoxShowAll->setCheckState(Qt::PartiallyChecked); + } + connect(mContourCheckBoxShowAll, SIGNAL(toggled(bool)), this, SLOT(AllVisibleContourROIToggled(bool))); + connect(mCheckBoxShowAll, SIGNAL(stateChanged(int)), this, SLOT(AllVisibleROIToggled(int))); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::SelectedItemChangedInTree() { + // Search which roi is selected + QList l = mTree->selectedItems(); + if (l.size() == 0) { + // mCurrentROIActor = 0; + mCurrentROI = NULL; + mGroupBoxROI->setEnabled(false); + return; + } + QTreeWidgetItem * w = l[0]; + if (mMapTreeWidgetToROI.find(w) == mMapTreeWidgetToROI.end()) { + // mCurrentROIActor = 0; + mCurrentROI = NULL; + mGroupBoxROI->setEnabled(false); + return; + } + if (w == NULL) return; + clitk::DicomRT_ROI * roi = mMapTreeWidgetToROI[w]; + if (roi == NULL) return; // sometimes it is called while there is no roi anymore + // Get selected roi actor + int n = roi->GetROINumber(); + QSharedPointer actor = mROIActorsList[n]; + mCurrentROI = roi; + mCurrentROIActor = actor; + + // Warning -> avoid unuseful Render here by disconnect slider + // Update GUI + disconnect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree())); + disconnect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool))); + disconnect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int))); + disconnect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor())); + disconnect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool))); + disconnect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor())); + disconnect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int))); + disconnect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int))); + + mGroupBoxROI->setEnabled(true); + mROInameLabel->setText(roi->GetName().c_str()); + mCheckBoxShow->setChecked(actor->IsVisible()); + mContourCheckBoxShow->setChecked(actor->IsContourVisible()); + mContourWidthSpinBox->setValue(actor->GetContourWidth()); + mDepthSpinBox->setValue(actor->GetDepth()); + w->setText(3, QString("%1").arg(actor->GetDepth())); + mOpacitySlider->setValue((int)lrint(actor->GetOpacity()*100)); + mOpacitySpinBox->setValue((int)lrint(actor->GetOpacity()*100)); + + connect(mTree, SIGNAL(itemSelectionChanged()), this, SLOT(SelectedItemChangedInTree())); + connect(mCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleROIToggled(bool))); + connect(mOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(OpacityChanged(int))); + connect(mChangeColorButton, SIGNAL(clicked()), this, SLOT(ChangeColor())); + connect(mContourCheckBoxShow, SIGNAL(toggled(bool)), this, SLOT(VisibleContourROIToggled(bool))); + connect(mChangeContourColorButton, SIGNAL(clicked()), this, SLOT(ChangeContourColor())); + connect(mContourWidthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeContourWidth(int))); + connect(mDepthSpinBox, SIGNAL(valueChanged(int)), this, SLOT(ChangeDepth(int))); + + + // Set the current color to the selected ROI name + mROInameLabel->setAutoFillBackground(true);// # This is important!! + mROInameLabel->setStyleSheet("QLabel { background-color : red; color : blue; }"); + QColor color = QColor(mCurrentROI->GetDisplayColor()[0]*255, + mCurrentROI->GetDisplayColor()[1]*255, + mCurrentROI->GetDisplayColor()[2]*255); + QString values = QString("%1, %2, %3").arg(color.red()).arg(color.green()).arg(color.blue()); + mROInameLabel->setStyleSheet("QLabel { background-color: rgb("+values+"); }"); + + + mGroupBoxROI->setEnabled(true); + // is this needed ? + // actor->Update(); + // Final rendering + // mCurrentSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::VisibleROIToggled(bool b) { + if (mCurrentROIActor == NULL) return; + if (b == mCurrentROIActor->IsVisible()) return; // nothing to do + mCurrentROIActor->SetVisible(b); + UpdateAllROIStatus(); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::VisibleContourROIToggled(bool b) { + if (mCurrentROIActor == NULL) return; + if (mCurrentROIActor->IsContourVisible() == b) return; // nothing to do + mCurrentROIActor->SetContourVisible(b); + mCurrentROIActor->UpdateColor(); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::OpacityChanged(int v) { + if (mCurrentROIActor == NULL) return; + mCurrentROIActor->SetOpacity((double)v/100.0); + mCurrentROIActor->UpdateColor(); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::AllVisibleROIToggled(int b) { + bool status = false; + if ((mCheckBoxShowAll->checkState() == Qt::Checked) || + (mCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true; + + for(uint i=0; iSetVisible(status); + } + if (status) mCheckBoxShowAll->setCheckState(Qt::Checked); + else mCheckBoxShowAll->setCheckState(Qt::Unchecked); + mCheckBoxShow->setChecked(status); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::AllVisibleContourROIToggled(bool b) { + bool status = false; + if ((mContourCheckBoxShowAll->checkState() == Qt::Checked) || + (mContourCheckBoxShowAll->checkState() == Qt::PartiallyChecked)) status = true; + // Update current + for(uint i=0; iSetContourVisible(status); + } + // Update current selection + if (status) mContourCheckBoxShowAll->setCheckState(Qt::Checked); + else mContourCheckBoxShowAll->setCheckState(Qt::Unchecked); + mContourCheckBoxShow->setChecked(status); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::ChangeColor() { + if (mCurrentROIActor == NULL) return; + QColor color; + color.setRgbF(mCurrentROIActor->GetROI()->GetDisplayColor()[0], + mCurrentROIActor->GetROI()->GetDisplayColor()[1], + mCurrentROIActor->GetROI()->GetDisplayColor()[2]); + QColor c = QColorDialog::getColor(color, this, "Choose the ROI color"); + mCurrentROIActor->GetROI()->SetDisplayColor(c.redF(), c.greenF(), c.blueF()); + mCurrentROIActor->UpdateColor(); + + QTreeWidgetItem * w = mMapROIToTreeWidget[mCurrentROI]; + QBrush brush(QColor(mCurrentROI->GetDisplayColor()[0]*255, + mCurrentROI->GetDisplayColor()[1]*255, + mCurrentROI->GetDisplayColor()[2]*255)); + brush.setStyle(Qt::SolidPattern); + w->setBackground(2, brush); + // Render + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::ChangeContourColor() { + if (mCurrentROIActor == NULL) return; + QColor color; + color.setRgbF(mCurrentROIActor->GetContourColor()[0], + mCurrentROIActor->GetContourColor()[1], + mCurrentROIActor->GetContourColor()[2]); + QColor c = QColorDialog::getColor(color, this, "Choose the contour color"); + mCurrentROIActor->SetContourColor(c.redF(), c.greenF(), c.blueF()); + mCurrentROIActor->UpdateColor(); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::ChangeContourWidth(int n) { + if (mCurrentROIActor == NULL) return; + mCurrentROIActor->SetContourWidth(n); + mCurrentROIActor->UpdateColor(); + mSlicerManager->Render(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::ChangeDepth(int n) { + if (mCurrentROIActor == NULL) return; + mCurrentROIActor->SetDepth(n); + mCurrentROIActor->UpdateImage(); + mSlicerManager->Render(); + QList l = mTree->selectedItems(); + QTreeWidgetItem * w = l[0]; + w->setText(3, QString("%1").arg(mCurrentROIActor->GetDepth())); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolROIManager::ReloadCurrentROI() { + + // Remove all contours/overlay first + bool visible = mCurrentROIActor->IsVisible(); + bool cvisible = mCurrentROIActor->IsContourVisible(); + mCurrentROIActor->SetVisible(false); + mCurrentROIActor->SetContourVisible(false); + mSlicerManager->Render(); + + // Reload image + vvImageReader::Pointer reader = vvImageReader::New(); + reader->SetInputFilename(mCurrentROI->GetFilename()); + reader->Update(vvImageReader::IMAGE); + if (reader->GetLastError() != "") { + QMessageBox::information(mMainWindowBase, tr("Sorry, error. Could not reload"), + reader->GetLastError().c_str()); + return; + } + + mCurrentROI->GetImage()->Reset();//GetFirstVTKImageData()->ReleaseData(); + mCurrentROI->SetImage(reader->GetOutput()); + + // Update visu + mCurrentROIActor->UpdateImage(); + mCurrentROIActor->SetVisible(visible); + mCurrentROIActor->SetContourVisible(cvisible); + mSlicerManager->Render(); } //------------------------------------------------------------------------------