X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=vv%2FvvToolSegmentation.cxx;h=63ff9b150f6cac958826bb87e83b9473310b9c0a;hb=0722e563db4e7b4493e4c697f75fb6f6aee93ebb;hp=873a099af18b4a398da00394bed01c45df0daead;hpb=6f76702afbff9ce0af70f887cd8a4e4d4bdd173a;p=clitk.git diff --git a/vv/vvToolSegmentation.cxx b/vv/vvToolSegmentation.cxx index 873a099..63ff9b1 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" @@ -26,14 +26,20 @@ // clitk #include "clitkConnectedComponentLabeling_ggo.h" #include "clitkConnectedComponentLabelingGenericFilter.h" +#include "clitkRegionGrowing_ggo.h" +#include "clitkRegionGrowingGenericFilter.h" // Qt #include #include // vtk +#include +#include +#include #include "vtkImageContinuousErode3D.h" #include "vtkImageContinuousDilate3D.h" +#include "vtkRenderWindow.h" //------------------------------------------------------------------------------ // Create the tool and automagically (I like this word) insert it in @@ -68,8 +74,11 @@ vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlag AddInputSelector("Select one image"); // Init + mCurrentLabelUnderMousePointer = 0.0; + mCurrentMousePositionInMM.resize(3); + // mCurrentMousePositionInPixel.resize(3); mRefMaskImage = NULL; - mCurrentMode = Mode_Default; + mCurrentState = State_Default; mKernelValue = 3; // FIXME must be odd. If even -> not symmetrical mDefaultLUTColor = vtkSmartPointer::New(); mDefaultLUTColor->SetNumberOfTableValues(256); @@ -90,13 +99,15 @@ vvToolSegmentation::~vvToolSegmentation() //------------------------------------------------------------------------------ bool vvToolSegmentation::close() { - DD("close"); - mRefMaskActor->RemoveActors(); - DD("la"); - mCurrentMaskActor->RemoveActors(); - DD("here"); + DD("remo ref"); + if (mRefMaskActor) mRefMaskActor->RemoveActors(); + DD("remo mask"); + if (mCurrentMaskActor) mCurrentMaskActor->RemoveActors(); + for(int i=0; iRemoveActors(); + } + DD("wclose"); QWidget::close(); - DD("toto"); mCurrentSlicerManager->Render(); return true; } @@ -135,6 +146,8 @@ void vvToolSegmentation::InputIsSelected(vvSlicerManager * m) // Connect mouse position connect(mCurrentSlicerManager, SIGNAL(MousePositionUpdatedSignal(int)), this, SLOT(MousePositionChanged(int))); + connect(mCurrentSlicerManager, SIGNAL(KeyPressedSignal(std::string)), + this, SLOT(KeyPressed(std::string))); } //------------------------------------------------------------------------------ @@ -191,60 +204,190 @@ void vvToolSegmentation::OpenBinaryImage() reader->Update(vvImageReader::IMAGE); mCurrentMaskImage = reader->GetOutput(); - // Add a new roi actor - mRefMaskActor = CreateMaskActor(mRefMaskImage, 0, 0, true); + // Add a new roi actor for the current mask + mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); + mCurrentMaskActor->Update(); // default color is red + UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC); + + // 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(); + UpdateMaskSize(mRefMaskImage, mRefMaskSizeInPixels, mRefMaskSizeInCC); + + // Update GUI + UpdateMaskSizeLabels(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::UpdateMaskSizeLabels() +{ + QString s("%1 pix (%2 cm3)"); + s = s.arg(mRefMaskSizeInPixels).arg(mRefMaskSizeInCC); + mRefMaskSizeLabel->setText(s); + QString s2("%1 pix (%2 cm3)"); + s2 = s2.arg(mCurrentMaskSizeInPixels).arg(mCurrentMaskSizeInCC); + mCurrentMaskSizeLabel->setText(s2); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::UpdateMaskSize(vvImage::Pointer image, long & pix, double & cc) +{ + pix = ComputeNumberOfPixels(image, GetForegroundValue()); + double vol = image->GetSpacing()[0]*image->GetSpacing()[1]*image->GetSpacing()[2]; + cc = pix * vol / (10*10*10); +} +//------------------------------------------------------------------------------ - mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 1, false); - mCurrentMaskActor->SetOverlayColor(1,0,0); // red roi - mRefMaskActor->UpdateColor(); - mCurrentMaskActor->Update(); - // Prepare widget to get keyboard event. With this method, the key - // only work when the mouse focus is on the dialog - DD("here installe"); - this->installEventFilter(this); - //grabKeyboard(); +//------------------------------------------------------------------------------ +long vvToolSegmentation::ComputeNumberOfPixels(vvImage::Pointer image, double value) +{ + int n=0; + vtkImageData * im = image->GetFirstVTKImageData(); + char * pPix = (char*)im->GetScalarPointer(); // FIXME char ? + for(uint i=0; iGetNumberOfPoints(); i++) { + if (pPix[i] == value) n++; + } + DD(n); + return n; +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::KeyPressed(std::string KeyPress) +{ + if (KeyPress == "G") { + RegionGrowing(); + } + if (KeyPress == "e") { + Erode(); + } + if (KeyPress == "d") { + Dilate(); // FIXME -> extend image BB !! + } + if (KeyPress == "L") { + Labelize(); + } + if (KeyPress == "m") { + Merge(); + UpdateAndRenderNewMask(); + } + 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); + writer->Update(); + } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ -//void vvToolSegmentation::keyPressEvent(QKeyEvent * event) -bool vvToolSegmentation::eventFilter(QObject *object, QEvent * e) +void vvToolSegmentation::RegionGrowing() { - // DD("key"); - //vvToolWidgetBase::keyPressEvent(event); + DD("RegionGrowing"); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + // Merge labels if needed + Merge(); + // Get mouse location + DD(mCurrentLabelUnderMousePointer); + DDV(mCurrentMousePositionInMM, 3); + // DDV(mCurrentMousePositionInPixel, 3); + + // Build RG filter parameters + typedef args_info_clitkRegionGrowing ArgsInfoType; + ArgsInfoType a; + cmdline_parser_clitkRegionGrowing_init(&a); + // FIXME parameters + a.type_arg = 4; // FIXME set by gui + DD(a.lower_arg); + a.lower_arg = 200; + a.upper_arg = 3000; + a.seed_given = 3; + a.seed_arg = new int[3]; + + DDV(mCurrentMousePositionInMM, 3); + vtkImageData * image = mCurrentImage->GetFirstVTKImageData(); + double x = (mCurrentMousePositionInMM[0] - image->GetOrigin()[0]) / image->GetSpacing()[0]; + double y = (mCurrentMousePositionInMM[1] - image->GetOrigin()[1]) / image->GetSpacing()[1]; + double z = (mCurrentMousePositionInMM[2] - image->GetOrigin()[2]) / image->GetSpacing()[2]; + a.seed_arg[0] = x; + a.seed_arg[1] = y; + a.seed_arg[2] = z; + a.verbose_flag = 1; + + // Build RG filter parameters + typedef clitk::RegionGrowingGenericFilter FilterType; + FilterType::Pointer filter = FilterType::New(); + filter->SetArgsInfo(a); + filter->SetInputVVImage(mCurrentImage); + filter->SetIOVerbose(true); + filter->Update(); + mCurrentMaskImage = filter->GetOutputVVImage(); + DD("filter done"); + + mCurrentMaskActor->RemoveActors(); + mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); + mCurrentMaskActor->Update(); // default color is red + UpdateAndRenderNewMask(); + UpdateMaskSizeLabels(); + DD("end"); - if (/*object == form &&*/ e->type() == QEvent::KeyPress) { - QKeyEvent * event = static_cast(e); - - if (event->text() == "e") { - Erode(); - } - if (event->text() == "d") { - Dilate(); // FIXME -> extend image BB !! - } - if (event->text() == "l") { - Labelize(); - } - if (event->text() == "r") { // "Remove" one label - if (mCurrentMode == Mode_CCL) RemoveLabel(); - } - if (event->text() == "s") { - vvImageWriter::Pointer writer = vvImageWriter::New(); - writer->SetOutputFileName("a.mha"); - writer->SetInput(mCurrentMaskImage); - writer->Update(); + // mouse pointer + QApplication::restoreOverrideCursor(); +} +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +void vvToolSegmentation::Merge() +{ + if (mCurrentState != State_CCL) return; + + DD("Merge"); + // Remove actors + for(int i=0; iSetVisible(false); + mCurrentCCLActors[i]->RemoveActors(); } - //mMainWindow->keyPressEvent(event); - vvToolWidgetBase::keyPressEvent(event); - } - return QObject::eventFilter(object, e); + } + 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] = GetBackgroundValue(); // copy BG. In CCL BG is always 0 + } + + // 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; } //------------------------------------------------------------------------------ @@ -253,13 +396,24 @@ bool vvToolSegmentation::eventFilter(QObject *object, QEvent * e) 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]; +#if VTK_MAJOR_VERSION <= 5 erode->SetInput(image); +#else + erode->SetInputData(image); +#endif erode->Update(); image->DeepCopy(erode->GetOutput()); +#if VTK_MAJOR_VERSION <= 5 image->Update(); +#else + //image->Update(); +#endif UpdateAndRenderNewMask(); erode->Delete(); QApplication::restoreOverrideCursor(); @@ -271,13 +425,24 @@ 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]; +#if VTK_MAJOR_VERSION <= 5 dilate->SetInput(image); +#else + dilate->SetInputData(image); +#endif dilate->Update(); image->DeepCopy(dilate->GetOutput()); +#if VTK_MAJOR_VERSION <= 5 image->Update(); +#else + //image->Update(); +#endif UpdateAndRenderNewMask(); dilate->Delete(); QApplication::restoreOverrideCursor(); @@ -297,28 +462,32 @@ void vvToolSegmentation::UpdateAndRenderNewMask() mCurrentMaskActor->SetContourVisible(cvisible); mCurrentSlicerManager->Render(); + UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC); + UpdateMaskSizeLabels(); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ 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.inputBG_arg = GetBackgroundValue(); 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); + filter->SetInputVVImage(mCurrentMaskImage); // FIXME Check type is ok ? convert float ? filter->SetIOVerbose(true); filter->Update(); DD(filter->GetOriginalNumberOfObjects()); @@ -338,18 +507,17 @@ void vvToolSegmentation::Labelize() // Create actors int n = filter->GetSizeOfObjectsInPixels().size(); - for(int i=1; i actor = CreateMaskActor(mCurrentCCLImage, i, i+1, false); mCurrentCCLActors.push_back( actor ); actor->Update(); } - mCurrentMaskActor->SetVisible(false); - mCurrentMaskActor->Update(); + // mCurrentMaskActor->Update(); mCurrentSlicerManager->Render(); // UpdateAndRender(); - mCurrentMode = Mode_CCL; + mCurrentState = State_CCL; QApplication::restoreOverrideCursor(); } //------------------------------------------------------------------------------ @@ -371,7 +539,6 @@ QSharedPointer vvToolSegmentation::CreateMaskActor(vvImage::Pointer actor->SetBGMode(true); } else { - DD("FG mode"); roi->SetForegroundValueLabelImage(i); // FG mode actor->SetBGMode(false); // FG mode } @@ -388,33 +555,72 @@ QSharedPointer vvToolSegmentation::CreateMaskActor(vvImage::Pointer //------------------------------------------------------------------------------ void vvToolSegmentation::MousePositionChanged(int slicer) { - if (mCurrentMode == Mode_Default) return; // Do nothing in this case - + // DD("MousePositionChanged "); + // DD(slicer); 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(); + mCurrentMousePositionInMM[0] = x; + mCurrentMousePositionInMM[1] = y; + mCurrentMousePositionInMM[2] = z; + // DDV(mCurrentMousePositionInMM, 3); + + // vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData(); + vtkImageData * image = mCurrentMaskImage->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; + // mCurrentMousePositionInPixel[0] = Xover; + // mCurrentMousePositionInPixel[1] = Yover; + // mCurrentMousePositionInPixel[2] = Zover; + // DDV(mCurrentMousePositionInPixel, 3); +#if VTK_MAJOR_VERSION <= 5 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]) { - double valueOver = - 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); + if (mCurrentState == State_Default) { // inside the mask + mCurrentLabelUnderMousePointer = 1; + return; + } + else { // inside the label image + vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData(); + mCurrentLabelUnderMousePointer = + mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0); + return; + } } else { // DD("out of mask"); + mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL } - +#else + if (Xover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[0] && + Xover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[1] && + Yover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[2] && + Yover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[3] && + Zover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[4] && + Zover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[5]) { + if (mCurrentState == State_Default) { // inside the mask + mCurrentLabelUnderMousePointer = 1; + return; + } + else { // inside the label image + vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData(); + mCurrentLabelUnderMousePointer = + mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0); + return; + } + } + else { + // DD("out of mask"); + mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL + } +#endif } //------------------------------------------------------------------------------ @@ -422,5 +628,23 @@ void vvToolSegmentation::MousePositionChanged(int slicer) //------------------------------------------------------------------------------ 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(); + int n = 0; + for(uint i=0; iGetNumberOfPoints(); i++) { + if (pPix[i] == mCurrentLabelUnderMousePointer) pPix[i] = 0; + if (pPix[i] != 0) n++; // count the number of pixels in the foreground + } + // Update mask size + mCurrentMaskSizeInPixels = n; + mCurrentMaskSizeInCC = mCurrentMaskImage->GetSpacing()[0] * mCurrentMaskImage->GetSpacing()[1] * mCurrentMaskImage->GetSpacing()[2] * n / (10*10*10); + UpdateMaskSizeLabels(); } //------------------------------------------------------------------------------