X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvToolSegmentation.cxx;h=9bd9365e105eff6babee4b76147a2727be54e4ff;hb=e34e0e0eb662c6c7fa3681f53aac959fef4b4f73;hp=0ceeb61ac50537301c16e10fb586435f5b494339;hpb=916bb609956d9a3aa8e642dccd3fd8c46261b684;p=clitk.git diff --git a/vv/vvToolSegmentation.cxx b/vv/vvToolSegmentation.cxx index 0ceeb61..9bd9365 100644 --- a/vv/vvToolSegmentation.cxx +++ b/vv/vvToolSegmentation.cxx @@ -14,7 +14,7 @@ - BSD See included LICENSE.txt file - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html -===========================================================================**/ + ===========================================================================**/ // vv #include "vvToolSegmentation.h" @@ -23,6 +23,10 @@ #include "vvToolInputSelectorWidget.h" #include "vvImageWriter.h" +// clitk +#include "clitkConnectedComponentLabeling_ggo.h" +#include "clitkConnectedComponentLabelingGenericFilter.h" + // Qt #include #include @@ -30,7 +34,8 @@ // vtk #include "vtkImageContinuousErode3D.h" #include "vtkImageContinuousDilate3D.h" - +#include "vtkRenderWindow.h" + //------------------------------------------------------------------------------ // Create the tool and automagically (I like this word) insert it in // the main window menu. @@ -64,7 +69,13 @@ vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlag AddInputSelector("Select one image"); // Init + mRefMaskImage = NULL; + mCurrentState = State_Default; mKernelValue = 3; // FIXME must be odd. If even -> not symmetrical + mDefaultLUTColor = vtkSmartPointer::New(); + mDefaultLUTColor->SetNumberOfTableValues(256); +#include "vvDefaultLut.h" + } //------------------------------------------------------------------------------ @@ -73,9 +84,6 @@ vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlag vvToolSegmentation::~vvToolSegmentation() { DD("destructor"); - mRefMaskActor->RemoveActors(); - QWidget::close(); - mCurrentSlicerManager->Render(); } //------------------------------------------------------------------------------ @@ -83,8 +91,15 @@ vvToolSegmentation::~vvToolSegmentation() //------------------------------------------------------------------------------ bool vvToolSegmentation::close() { - DD("close"); - mRefMaskActor->RemoveActors(); + DD("remo ref"); + if (mRefMaskActor) mRefMaskActor->RemoveActors(); + DD("remo mask"); + if (mCurrentMaskActor) mCurrentMaskActor->RemoveActors(); + for(int i=0; iRemoveActors(); + } + DD("wclose"); QWidget::close(); mCurrentSlicerManager->Render(); return true; @@ -111,6 +126,21 @@ void vvToolSegmentation::InputIsSelected(vvSlicerManager * m) // Open mask OpenBinaryImage(); + + // If cancel: stop + if (mRefMaskActor == NULL) { + close(); + return; + } + + // Update gui + mToolInputSelectionWidget->hide(); + + // Connect mouse position + connect(mCurrentSlicerManager, SIGNAL(MousePositionUpdatedSignal(int)), + this, SLOT(MousePositionChanged(int))); + connect(mCurrentSlicerManager, SIGNAL(KeyPressedSignal(std::string)), + this, SLOT(KeyPressed(std::string))); } //------------------------------------------------------------------------------ @@ -167,50 +197,45 @@ void vvToolSegmentation::OpenBinaryImage() reader->Update(vvImageReader::IMAGE); mCurrentMaskImage = reader->GetOutput(); - // Add a new roi actor - mRefMaskActor = QSharedPointer(new vvROIActor); - mCurrentMaskActor = QSharedPointer(new vvROIActor); - std::vector color; - color.push_back(1); - color.push_back(0); - color.push_back(0); - clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New(); - roi->SetFromBinaryImage(mRefMaskImage, 1, std::string("toto"), color, filename.toStdString()); - mRefMaskActor->SetBGMode(true); - mRefMaskActor->SetROI(roi); - mRefMaskActor->SetSlicerManager(mCurrentSlicerManager); - mRefMaskActor->Initialize(10, true); + // Add a new roi actor for the current mask + mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); + mCurrentMaskActor->Update(); // default color is red + + // Add a mask actor for the reference + mRefMaskActor = CreateMaskActor(mRefMaskImage, 0, 1, true); mRefMaskActor->SetContourVisible(true); mRefMaskActor->SetVisible(false); + mRefMaskActor->SetContourColor(0,1,0); // green contour + mRefMaskActor->UpdateColor(); mRefMaskActor->Update(); - - clitk::DicomRT_ROI::Pointer roi2 = clitk::DicomRT_ROI::New(); - roi2->SetFromBinaryImage(mCurrentMaskImage, 1, std::string("toto"), color, filename.toStdString()); - mCurrentMaskActor->SetBGMode(true); - mCurrentMaskActor->SetROI(roi2); - mCurrentMaskActor->SetSlicerManager(mCurrentSlicerManager); - mCurrentMaskActor->Initialize(10, true); - mCurrentMaskActor->Update(); - - // Prepare widget to get keyboard event - grabKeyboard(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -void vvToolSegmentation::keyPressEvent(QKeyEvent * event) -{ - vvToolWidgetBase::keyPressEvent(event); - //DD("key"); - - if (event->text() == "e") { +void vvToolSegmentation::KeyPressed(std::string KeyPress) +{ + if (KeyPress == "e") { Erode(); } - if (event->text() == "d") { + if (KeyPress == "d") { Dilate(); // FIXME -> extend image BB !! } - if (event->text() == "s") { + if (KeyPress == "L") { + Labelize(); + } + if (KeyPress == "m") { + Merge(); + } + if (KeyPress == "s") { // Supress "Remove" one label + if (mCurrentState == State_CCL) RemoveLabel(); + } + if (KeyPress == "t") { // display remove ref contour + mRefMaskActor->SetContourVisible(!mRefMaskActor->IsContourVisible()); + mRefMaskActor->UpdateColor(); + mCurrentSlicerManager->Render(); + } + if (KeyPress == "w") { vvImageWriter::Pointer writer = vvImageWriter::New(); writer->SetOutputFileName("a.mha"); writer->SetInput(mCurrentMaskImage); @@ -220,10 +245,49 @@ void vvToolSegmentation::keyPressEvent(QKeyEvent * event) //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +void vvToolSegmentation::Merge() +{ + if (mCurrentState != State_CCL) return; + + DD("Merge"); + // Remove actors + for(int i=0; iSetVisible(false); + mCurrentCCLActors[i]->RemoveActors(); + } + } + mCurrentCCLActors.clear(); + + // Compute new mask + vtkImageData * ccl = mCurrentCCLImage->GetFirstVTKImageData(); + vtkImageData * mask = mCurrentMaskImage->GetFirstVTKImageData(); + int * pCCL = (int*)ccl->GetScalarPointer(); + char * pPix = (char*)mask->GetScalarPointer(); + for(uint i=0; iGetNumberOfPoints(); i++) { + if (pCCL[i] == 0) pPix[i] = 0; // copy BG + } + + // Display new mask and remove ccl + mCurrentCCLImage->Reset(); + mCurrentMaskActor->RemoveActors(); // kill it + mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); // renew + mCurrentMaskActor->Update(); + mCurrentMaskActor->SetVisible(true); + mCurrentSlicerManager->Render(); + mCurrentState = State_Default; +} +//------------------------------------------------------------------------------ + + //------------------------------------------------------------------------------ void vvToolSegmentation::Erode() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + // Merge labels if needed + Merge(); + // Get image and start erosion vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New(); erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue); vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0]; @@ -231,7 +295,7 @@ void vvToolSegmentation::Erode() erode->Update(); image->DeepCopy(erode->GetOutput()); image->Update(); - UpdateAndRender(); + UpdateAndRenderNewMask(); erode->Delete(); QApplication::restoreOverrideCursor(); } @@ -242,6 +306,9 @@ void vvToolSegmentation::Erode() void vvToolSegmentation::Dilate() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + // Merge labels if needed + Merge(); + // Get image and start dilatation vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New(); dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue); vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0]; @@ -249,7 +316,7 @@ void vvToolSegmentation::Dilate() dilate->Update(); image->DeepCopy(dilate->GetOutput()); image->Update(); - UpdateAndRender(); + UpdateAndRenderNewMask(); dilate->Delete(); QApplication::restoreOverrideCursor(); } @@ -257,18 +324,154 @@ void vvToolSegmentation::Dilate() //------------------------------------------------------------------------------ -void vvToolSegmentation::UpdateAndRender() +void vvToolSegmentation::UpdateAndRenderNewMask() { bool visible = mCurrentMaskActor->IsVisible(); bool cvisible = mCurrentMaskActor->IsContourVisible(); mCurrentMaskActor->SetVisible(false); mCurrentMaskActor->SetContourVisible(false); - // mCurrentSlicerManager->Render(); - - //mCurrentMaskActor->RemoveActors(); mCurrentMaskActor->UpdateImage(); mCurrentMaskActor->SetVisible(visible); mCurrentMaskActor->SetContourVisible(cvisible); + mCurrentSlicerManager->Render(); } //------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +void vvToolSegmentation::Labelize() +{ + if (mCurrentState == State_CCL) return; // Do nothing in this case + DD("Labelize"); + // Waiting cursos + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + mCurrentMaskActor->SetVisible(false); + + // Build CCL filter + vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0]; + typedef args_info_clitkConnectedComponentLabeling ArgsInfoType; + ArgsInfoType a; + cmdline_parser_clitkConnectedComponentLabeling_init(&a); + a.inputBG_arg = 0; + a.full_flag = false; // FIXME set by gui + a.minSize_arg = 100; // FIXME set by gui + typedef clitk::ConnectedComponentLabelingGenericFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetArgsInfo(a); + filter->SetInputVVImage(mCurrentMaskImage); // FIXME Check type is ok ? convert float ? + filter->SetIOVerbose(true); + filter->Update(); + DD(filter->GetOriginalNumberOfObjects()); + DD(filter->GetSizeOfObjectsInPixels().size()); + mCurrentCCLImage = filter->GetOutputVVImage(); + DDV(filter->GetSizeOfObjectsInPixels(), filter->GetSizeOfObjectsInPixels().size()); + DD("filter done"); + + /* + // DEBUG + vvImageWriter::Pointer writer = vvImageWriter::New(); + writer->SetInput(mCurrentCCLImage); + writer->SetOutputFileName("bidon-ccl.mha"); + writer->Update(); + DD(mCurrentCCLImage->IsScalarTypeInteger()); + */ + + // Create actors + int n = filter->GetSizeOfObjectsInPixels().size(); + mCurrentCCLActors.clear(); + for(int i=1; i<=std::min(n,10); i++) { // Start at 1 because 0 is BG. FIXME max by gui + QSharedPointer actor = CreateMaskActor(mCurrentCCLImage, i, i+1, false); + mCurrentCCLActors.push_back( actor ); + actor->Update(); + } + // mCurrentMaskActor->Update(); + mCurrentSlicerManager->Render(); + + // UpdateAndRender(); + mCurrentState = State_CCL; + QApplication::restoreOverrideCursor(); +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +QSharedPointer vvToolSegmentation::CreateMaskActor(vvImage::Pointer image, int i, int colorID, bool BGMode) +{ + static int depth = 1; + depth += 1; + QSharedPointer actor = QSharedPointer(new vvROIActor); + double * color = mDefaultLUTColor->GetTableValue(colorID % mDefaultLUTColor->GetNumberOfTableValues ()); + std::vector c; + c.push_back(color[0]); + c.push_back(color[1]); + c.push_back(color[2]); + clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New(); + roi->SetFromBinaryImage(image, i, std::string("toto"), c, std::string("titi")); + if (BGMode) { + actor->SetBGMode(true); + } + else { + roi->SetForegroundValueLabelImage(i); // FG mode + actor->SetBGMode(false); // FG mode + } + actor->SetROI(roi); + actor->SetSlicerManager(mCurrentSlicerManager); + actor->Initialize(depth+i, true); // +1 to start at 1 not 0 + actor->SetContourVisible(false); + actor->SetVisible(true); + return actor; +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::MousePositionChanged(int slicer) +{ + if (mCurrentState == State_Default) return; // Do nothing in this case + + double x = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[0]; + double y = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[1]; + double z = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[2]; + vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData(); + double Xover = (x - image->GetOrigin()[0]) / image->GetSpacing()[0]; + double Yover = (y - image->GetOrigin()[1]) / image->GetSpacing()[1]; + double Zover = (z - image->GetOrigin()[2]) / image->GetSpacing()[2]; + int ix, iy, iz; + + if (Xover >= image->GetWholeExtent()[0] && + Xover <= image->GetWholeExtent()[1] && + Yover >= image->GetWholeExtent()[2] && + Yover <= image->GetWholeExtent()[3] && + Zover >= image->GetWholeExtent()[4] && + Zover <= image->GetWholeExtent()[5]) { + mCurrentLabelUnderMousePointer = + mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0); + // DD(Xover); DD(Yover); DD(Zover); + // DD(ix); DD(iy); DD(iz); + // DD(valueOver); + } + else { + // DD("out of mask"); + mCurrentLabelUnderMousePointer = 0; + } + // DD(mCurrentLabelUnderMousePointer); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::RemoveLabel() { + DD("RemoveLabel"); + if (mCurrentLabelUnderMousePointer == 0) return; + // First actor=0 and is label 1. Label 0 is not an actor, it is BG + int actorNumber = mCurrentLabelUnderMousePointer-1; + // Set actor invisible + mCurrentCCLActors[actorNumber]->SetVisible(false); + mCurrentSlicerManager->Render(); + // Set image label + vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData(); + int * pPix = (int*)image->GetScalarPointer(); + for(uint i=0; iGetNumberOfPoints(); i++) { + if (pPix[i] == mCurrentLabelUnderMousePointer) pPix[i] = 0; + } +} +//------------------------------------------------------------------------------