]> Creatis software - clitk.git/blob - vv/vvToolSegmentation.cxx
Add clitkImage2DicomSeries tool to write a Dicom Series from an image without a corre...
[clitk.git] / vv / vvToolSegmentation.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17   ===========================================================================**/
18
19 // vv
20 #include "vvToolSegmentation.h"
21 #include "vvSlicerManager.h"
22 #include "vvSlicer.h"
23 #include "vvToolInputSelectorWidget.h"
24 #include "vvImageWriter.h"
25
26 // clitk
27 #include "clitkConnectedComponentLabeling_ggo.h"
28 #include "clitkConnectedComponentLabelingGenericFilter.h"
29 #include "clitkRegionGrowing_ggo.h"
30 #include "clitkRegionGrowingGenericFilter.h"
31
32 // Qt
33 #include <QFileDialog>
34 #include <QMessageBox>
35
36 // vtk
37 #include <vtkVersion.h>
38 #include <vtkStreamingDemandDrivenPipeline.h>
39 #include <vtkInformation.h>
40 #include "vtkImageContinuousErode3D.h"
41 #include "vtkImageContinuousDilate3D.h"
42 #include "vtkRenderWindow.h"
43
44 //------------------------------------------------------------------------------
45 // Create the tool and automagically (I like this word) insert it in
46 // the main window menu.
47 ADD_TOOL(vvToolSegmentation);
48 //------------------------------------------------------------------------------
49
50
51 //------------------------------------------------------------------------------
52 void vvToolSegmentation::Initialize()
53 {
54   SetToolName("Segmentation");
55   SetToolMenuName("Interactive Segmentation");
56   SetToolIconFilename(":/common/icons/ducky.ico");
57   SetToolTip("Image interactive segmentation (trial).");
58   SetToolExperimental(true);
59 }
60 //------------------------------------------------------------------------------
61
62
63 //------------------------------------------------------------------------------
64 vvToolSegmentation::vvToolSegmentation(vvMainWindowBase * parent, Qt::WindowFlags f)
65   :vvToolWidgetBase(parent,f),
66    vvToolBase<vvToolSegmentation>(parent),
67    Ui::vvToolSegmentation()
68 {
69   // GUI Initialization
70   Ui_vvToolSegmentation::setupUi(mToolWidget);
71   setAttribute(Qt::WA_DeleteOnClose);
72
73   // Set how many inputs are needed for this tool
74   AddInputSelector("Select one image");
75   
76   // Init
77   mCurrentLabelUnderMousePointer = 0.0;
78   mCurrentMousePositionInMM.resize(3);
79   //  mCurrentMousePositionInPixel.resize(3);
80   mRefMaskImage = NULL;
81   mCurrentState = State_Default;
82   mKernelValue = 3; // FIXME must be odd. If even -> not symmetrical
83   mDefaultLUTColor = vtkSmartPointer<vtkLookupTable>::New();
84   mDefaultLUTColor->SetNumberOfTableValues(256);
85 #include "vvDefaultLut.h"
86   
87 }
88 //------------------------------------------------------------------------------
89
90
91 //------------------------------------------------------------------------------
92 vvToolSegmentation::~vvToolSegmentation()
93 {
94   DD("destructor");
95 }
96 //------------------------------------------------------------------------------
97
98
99 //------------------------------------------------------------------------------
100 bool vvToolSegmentation::close()
101 {
102   DD("remo ref");
103   if (mRefMaskActor) mRefMaskActor->RemoveActors();
104   DD("remo mask");
105   if (mCurrentMaskActor) mCurrentMaskActor->RemoveActors();
106   for(int i=0; i<mCurrentCCLActors.size(); i++) {
107     if (mCurrentCCLActors[i]) mCurrentCCLActors[i]->RemoveActors();
108   }
109   DD("wclose");
110   QWidget::close();  
111   mCurrentSlicerManager->Render();
112   return true;
113 }
114 //------------------------------------------------------------------------------
115
116
117 //------------------------------------------------------------------------------
118 void vvToolSegmentation::InputIsSelected(vvSlicerManager * m)
119 {
120   DD("InputIsSelected");
121   mCurrentSlicerManager = m;
122   mCurrentImage = mCurrentSlicerManager->GetImage();
123
124   // Refuse if non 3D image
125   if (mCurrentImage->GetNumberOfDimensions() != 3) {
126     QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
127     close();
128     return;
129   }
130
131   // Change gui
132   //mLabelInputInfo->setText(QString("%1").arg(m->GetFileName().c_str()));
133
134   // Open mask
135   OpenBinaryImage();
136   
137   // If cancel: stop
138   if (mRefMaskActor == NULL) {
139     close();
140     return;
141   }
142
143   // Update gui
144   mToolInputSelectionWidget->hide();
145
146   // Connect mouse position
147   connect(mCurrentSlicerManager, SIGNAL(MousePositionUpdatedSignal(int)),
148           this, SLOT(MousePositionChanged(int)));
149   connect(mCurrentSlicerManager, SIGNAL(KeyPressedSignal(std::string)),
150           this, SLOT(KeyPressed(std::string)));
151 }
152 //------------------------------------------------------------------------------
153
154
155 //------------------------------------------------------------------------------
156 void vvToolSegmentation::apply()
157 {
158   DD("apply");
159 }
160 //------------------------------------------------------------------------------
161
162
163 //------------------------------------------------------------------------------
164 void vvToolSegmentation::OpenBinaryImage()
165 {
166   DD("OpenBinaryImage");
167
168   // Load browser and select image
169   QString Extensions = "Images files ( *.mha *.mhd *.hdr *.his)";
170   Extensions += ";;All Files (*)";
171   QString filename =
172     QFileDialog::getOpenFileName(this,tr("Open binary image"),
173                                  mMainWindowBase->GetInputPathName(),Extensions);
174   DD(filename.toStdString());
175   if (filename.size() == 0) return;
176   
177   // Open Image
178   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
179   vvImageReader::Pointer reader = vvImageReader::New();
180   std::vector<std::string> filenames;
181   filenames.push_back(filename.toStdString());
182   reader->SetInputFilenames(filenames);
183   reader->Update(vvImageReader::IMAGE);
184   QApplication::restoreOverrideCursor();
185   
186   if (reader->GetLastError().size() != 0) {
187     std::cerr << "Error while reading " << filename.toStdString() << std::endl;
188     QString error = "Cannot open file \n";
189     error += reader->GetLastError().c_str();
190     QMessageBox::information(this,tr("Reading problem"),error);
191     return;
192   }
193
194   mRefMaskImage = reader->GetOutput();
195   int dim = mRefMaskImage->GetNumberOfDimensions();
196   if (dim != 3 ) {
197     QMessageBox::information(this,tr("Sorry only 3D yet"), tr("Sorry only 3D yet"));
198     close();
199     return;
200   }
201
202   reader = vvImageReader::New();
203   reader->SetInputFilenames(filenames);
204   reader->Update(vvImageReader::IMAGE);
205   mCurrentMaskImage = reader->GetOutput();
206
207   // Add a new roi actor for the current mask
208   mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false);
209   mCurrentMaskActor->Update(); // default color is red
210   UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC);  
211
212   // Add a mask actor for the reference
213   mRefMaskActor = CreateMaskActor(mRefMaskImage, 0, 1, true);
214   mRefMaskActor->SetContourVisible(true);
215   mRefMaskActor->SetVisible(false);
216   mRefMaskActor->SetContourColor(0,1,0); // green contour
217   mRefMaskActor->UpdateColor();
218   mRefMaskActor->Update();
219   UpdateMaskSize(mRefMaskImage, mRefMaskSizeInPixels, mRefMaskSizeInCC);  
220
221   // Update GUI
222   UpdateMaskSizeLabels();
223 }
224 //------------------------------------------------------------------------------
225
226
227 //------------------------------------------------------------------------------
228 void vvToolSegmentation::UpdateMaskSizeLabels()
229 {
230   QString s("%1 pix (%2 cm3)");
231   s = s.arg(mRefMaskSizeInPixels).arg(mRefMaskSizeInCC);
232   mRefMaskSizeLabel->setText(s);
233   QString s2("%1 pix (%2 cm3)");
234   s2 = s2.arg(mCurrentMaskSizeInPixels).arg(mCurrentMaskSizeInCC);
235   mCurrentMaskSizeLabel->setText(s2);
236 }
237 //------------------------------------------------------------------------------
238
239
240 //------------------------------------------------------------------------------
241 void vvToolSegmentation::UpdateMaskSize(vvImage::Pointer image, long & pix, double & cc)
242 {
243   pix = ComputeNumberOfPixels(image, GetForegroundValue());
244   double vol = image->GetSpacing()[0]*image->GetSpacing()[1]*image->GetSpacing()[2];
245   cc = pix * vol / (10*10*10);
246 }
247 //------------------------------------------------------------------------------
248
249
250 //------------------------------------------------------------------------------
251 long vvToolSegmentation::ComputeNumberOfPixels(vvImage::Pointer image, double value) 
252 {
253   int n=0;
254   vtkImageData * im = image->GetFirstVTKImageData();
255   char * pPix = (char*)im->GetScalarPointer(); // FIXME char ?
256   for(uint i=0; i<im->GetNumberOfPoints(); i++) {
257     if (pPix[i] == value) n++;
258   }
259   DD(n);
260   return n;
261 }
262 //------------------------------------------------------------------------------
263
264
265 //------------------------------------------------------------------------------
266 void vvToolSegmentation::KeyPressed(std::string KeyPress)
267
268   if (KeyPress == "G") {
269     RegionGrowing();
270   }
271   if (KeyPress == "e") {
272     Erode();
273   }
274   if (KeyPress == "d") {
275     Dilate(); // FIXME -> extend image BB !!
276   }
277   if (KeyPress == "L") {
278     Labelize(); 
279   }
280   if (KeyPress == "m") {
281     Merge(); 
282     UpdateAndRenderNewMask();
283   }
284   if (KeyPress == "s") { // Supress "Remove" one label
285     if (mCurrentState == State_CCL) RemoveLabel();
286   }
287   if (KeyPress == "t") { // display remove ref contour
288     mRefMaskActor->SetContourVisible(!mRefMaskActor->IsContourVisible());
289     mRefMaskActor->UpdateColor();
290     mCurrentSlicerManager->Render();
291   }
292   if (KeyPress == "w") {
293     vvImageWriter::Pointer writer = vvImageWriter::New();
294     writer->SetOutputFileName("a.mha");
295     writer->SetInput(mCurrentMaskImage);
296     writer->Update();
297   }
298 }
299 //------------------------------------------------------------------------------
300
301
302 //------------------------------------------------------------------------------
303 void vvToolSegmentation::RegionGrowing()
304 {
305   DD("RegionGrowing");
306   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
307   // Merge labels if needed
308   Merge();
309   // Get mouse location
310   DD(mCurrentLabelUnderMousePointer); 
311   DDV(mCurrentMousePositionInMM, 3);
312   //  DDV(mCurrentMousePositionInPixel, 3);
313
314   // Build RG filter parameters
315   typedef args_info_clitkRegionGrowing ArgsInfoType;
316   ArgsInfoType a;
317   cmdline_parser_clitkRegionGrowing_init(&a);
318   // FIXME parameters
319   a.type_arg = 4;  // FIXME set by gui 
320   DD(a.lower_arg);
321   a.lower_arg = 200;
322   a.upper_arg = 3000;
323   a.seed_given = 3;
324   a.seed_arg = new int[3];
325
326   DDV(mCurrentMousePositionInMM, 3);
327   vtkImageData * image = mCurrentImage->GetFirstVTKImageData();
328   double x = (mCurrentMousePositionInMM[0] - image->GetOrigin()[0]) / image->GetSpacing()[0];
329   double y = (mCurrentMousePositionInMM[1] - image->GetOrigin()[1]) / image->GetSpacing()[1];
330   double z = (mCurrentMousePositionInMM[2] - image->GetOrigin()[2]) / image->GetSpacing()[2];
331   a.seed_arg[0] = x;
332   a.seed_arg[1] = y;
333   a.seed_arg[2] = z;
334   a.verbose_flag = 1;
335
336   // Build RG filter parameters
337   typedef clitk::RegionGrowingGenericFilter<args_info_clitkRegionGrowing> FilterType;
338   FilterType::Pointer filter = FilterType::New();
339   filter->SetArgsInfo(a);
340   filter->SetInputVVImage(mCurrentImage);
341   filter->SetIOVerbose(true);  
342   filter->Update();
343   mCurrentMaskImage = filter->GetOutputVVImage();
344   DD("filter done");
345
346   mCurrentMaskActor->RemoveActors();
347   mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false);
348   mCurrentMaskActor->Update(); // default color is red
349   UpdateAndRenderNewMask();
350   UpdateMaskSizeLabels();
351   DD("end");
352   
353   // mouse pointer
354   QApplication::restoreOverrideCursor();
355 }  
356 //------------------------------------------------------------------------------
357
358
359 //------------------------------------------------------------------------------
360 void vvToolSegmentation::Merge()
361 {
362   if (mCurrentState != State_CCL) return;
363   
364   DD("Merge");
365   // Remove actors
366   for(int i=0; i<mCurrentCCLActors.size(); i++) {
367     if (mCurrentCCLActors[i]) {
368       mCurrentCCLActors[i]->SetVisible(false);
369       mCurrentCCLActors[i]->RemoveActors();
370     }
371   }
372   mCurrentCCLActors.clear();
373
374   // Compute new mask
375   vtkImageData * ccl  = mCurrentCCLImage->GetFirstVTKImageData();
376   vtkImageData * mask = mCurrentMaskImage->GetFirstVTKImageData();
377   int * pCCL = (int*)ccl->GetScalarPointer();
378   char * pPix = (char*)mask->GetScalarPointer();
379   for(uint i=0; i<ccl->GetNumberOfPoints(); i++) {
380     if (pCCL[i] == 0) pPix[i] = GetBackgroundValue(); // copy BG. In CCL BG is always 0
381   }
382
383   // Display new mask and remove ccl
384   mCurrentCCLImage->Reset();
385   mCurrentMaskActor->RemoveActors(); // kill it
386   mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); // renew
387   mCurrentMaskActor->Update();
388   mCurrentMaskActor->SetVisible(true); 
389   // mCurrentSlicerManager->Render();
390   mCurrentState = State_Default;
391 }
392 //------------------------------------------------------------------------------
393
394
395 //------------------------------------------------------------------------------
396 void vvToolSegmentation::Erode()
397 {
398   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
399   // Merge labels if needed
400   Merge();
401   // Get image and start erosion
402   vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
403   erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
404   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
405 #if VTK_MAJOR_VERSION <= 5
406   erode->SetInput(image);
407 #else
408   erode->SetInputData(image);
409 #endif
410   erode->Update();
411   image->DeepCopy(erode->GetOutput());
412 #if VTK_MAJOR_VERSION <= 5
413   image->Update();
414 #else
415   //image->Update();
416 #endif
417   UpdateAndRenderNewMask();
418   erode->Delete();
419   QApplication::restoreOverrideCursor();
420 }
421 //------------------------------------------------------------------------------
422
423
424 //------------------------------------------------------------------------------
425 void vvToolSegmentation::Dilate()
426 {
427   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
428   // Merge labels if needed
429   Merge();
430   // Get image and start dilatation
431   vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
432   dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
433   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
434 #if VTK_MAJOR_VERSION <= 5
435   dilate->SetInput(image);
436 #else
437   dilate->SetInputData(image);
438 #endif
439   dilate->Update();
440   image->DeepCopy(dilate->GetOutput());
441 #if VTK_MAJOR_VERSION <= 5
442   image->Update();
443 #else
444   //image->Update();
445 #endif
446   UpdateAndRenderNewMask();
447   dilate->Delete();
448   QApplication::restoreOverrideCursor();
449 }
450 //------------------------------------------------------------------------------
451
452
453 //------------------------------------------------------------------------------
454 void vvToolSegmentation::UpdateAndRenderNewMask()
455 {
456   bool visible = mCurrentMaskActor->IsVisible();
457   bool cvisible = mCurrentMaskActor->IsContourVisible();
458   mCurrentMaskActor->SetVisible(false);
459   mCurrentMaskActor->SetContourVisible(false);
460   mCurrentMaskActor->UpdateImage();
461   mCurrentMaskActor->SetVisible(visible);
462   mCurrentMaskActor->SetContourVisible(cvisible);
463
464   mCurrentSlicerManager->Render();
465   UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC);
466   UpdateMaskSizeLabels();
467 }
468 //------------------------------------------------------------------------------
469
470 //------------------------------------------------------------------------------
471 void vvToolSegmentation::Labelize()
472 {
473   if (mCurrentState == State_CCL) return; // Do nothing in this case
474   DD("Labelize");
475   // Waiting cursos
476   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
477   mCurrentMaskActor->SetVisible(false);
478   
479   // Build CCL filter
480   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
481   typedef args_info_clitkConnectedComponentLabeling ArgsInfoType;
482   ArgsInfoType a;
483   cmdline_parser_clitkConnectedComponentLabeling_init(&a);
484   a.inputBG_arg = GetBackgroundValue();
485   a.full_flag = false;  // FIXME set by gui
486   a.minSize_arg = 100;  // FIXME set by gui 
487   typedef clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType> FilterType;
488   FilterType::Pointer filter = FilterType::New();
489   filter->SetArgsInfo(a);
490   filter->SetInputVVImage(mCurrentMaskImage); // FIXME Check type is ok ? convert float ?
491   filter->SetIOVerbose(true);  
492   filter->Update();
493   DD(filter->GetOriginalNumberOfObjects());
494   DD(filter->GetSizeOfObjectsInPixels().size());
495   mCurrentCCLImage = filter->GetOutputVVImage();
496   DDV(filter->GetSizeOfObjectsInPixels(), filter->GetSizeOfObjectsInPixels().size());
497   DD("filter done");
498
499   /*
500   // DEBUG
501   vvImageWriter::Pointer writer = vvImageWriter::New();
502   writer->SetInput(mCurrentCCLImage);
503   writer->SetOutputFileName("bidon-ccl.mha");
504   writer->Update(); 
505   DD(mCurrentCCLImage->IsScalarTypeInteger());
506   */
507   
508   // Create actors 
509   int n = filter->GetSizeOfObjectsInPixels().size();
510   mCurrentCCLActors.clear();
511   for(int i=1; i<=std::min(n,10); i++) { // Start at 1 because 0 is BG. FIXME max by gui
512     QSharedPointer<vvROIActor> actor = CreateMaskActor(mCurrentCCLImage, i, i+1, false); 
513     mCurrentCCLActors.push_back( actor );
514     actor->Update();    
515   }
516   //  mCurrentMaskActor->Update();
517   mCurrentSlicerManager->Render();
518   
519   // UpdateAndRender();
520   mCurrentState = State_CCL;
521   QApplication::restoreOverrideCursor();
522 }
523 //------------------------------------------------------------------------------
524
525 //------------------------------------------------------------------------------
526 QSharedPointer<vvROIActor> vvToolSegmentation::CreateMaskActor(vvImage::Pointer image, int i, int colorID, bool BGMode)
527 {
528   static int depth = 1;
529   depth += 1;
530   QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
531   double * color = mDefaultLUTColor->GetTableValue(colorID % mDefaultLUTColor->GetNumberOfTableValues ());
532   std::vector<double> c;
533   c.push_back(color[0]);
534   c.push_back(color[1]);
535   c.push_back(color[2]);
536   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
537   roi->SetFromBinaryImage(image, i, std::string("toto"), c, std::string("titi"));
538   if (BGMode) {
539     actor->SetBGMode(true);
540   }
541   else {
542     roi->SetForegroundValueLabelImage(i); // FG mode
543     actor->SetBGMode(false); // FG mode
544   }
545   actor->SetROI(roi);
546   actor->SetSlicerManager(mCurrentSlicerManager);
547   actor->Initialize(depth+i, true); // +1 to start at 1 not 0
548   actor->SetContourVisible(false);
549   actor->SetVisible(true);
550   return actor;
551 }
552 //------------------------------------------------------------------------------
553
554
555 //------------------------------------------------------------------------------
556 void vvToolSegmentation::MousePositionChanged(int slicer)
557 {
558   // DD("MousePositionChanged ");
559   // DD(slicer);
560   double x = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[0];
561   double y = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[1];
562   double z = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[2];
563   mCurrentMousePositionInMM[0] = x;
564   mCurrentMousePositionInMM[1] = y;
565   mCurrentMousePositionInMM[2] = z;
566   // DDV(mCurrentMousePositionInMM, 3);
567
568   //  vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
569   vtkImageData * image = mCurrentMaskImage->GetFirstVTKImageData();
570   double Xover = (x - image->GetOrigin()[0]) / image->GetSpacing()[0];
571   double Yover = (y - image->GetOrigin()[1]) / image->GetSpacing()[1];
572   double Zover = (z - image->GetOrigin()[2]) / image->GetSpacing()[2];
573   int ix, iy, iz;
574   
575   // mCurrentMousePositionInPixel[0] = Xover;
576   // mCurrentMousePositionInPixel[1] = Yover;
577   // mCurrentMousePositionInPixel[2] = Zover;
578   // DDV(mCurrentMousePositionInPixel, 3);
579 #if VTK_MAJOR_VERSION <= 5
580   if (Xover >= image->GetWholeExtent()[0] &&
581       Xover <= image->GetWholeExtent()[1] &&
582       Yover >= image->GetWholeExtent()[2] &&
583       Yover <= image->GetWholeExtent()[3] &&
584       Zover >= image->GetWholeExtent()[4] &&
585       Zover <= image->GetWholeExtent()[5]) {
586     if (mCurrentState == State_Default) { // inside the mask
587       mCurrentLabelUnderMousePointer = 1;
588       return; 
589     }
590     else { // inside the label image
591       vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
592       mCurrentLabelUnderMousePointer = 
593         mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0);
594       return;
595     }
596   }
597   else {
598     // DD("out of mask");
599     mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL
600   }
601 #else
602   if (Xover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[0] &&
603       Xover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[1] &&
604       Yover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[2] &&
605       Yover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[3] &&
606       Zover >= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[4] &&
607       Zover <= image->GetInformation()->Get(vtkDataObject::DATA_EXTENT())[5]) {
608     if (mCurrentState == State_Default) { // inside the mask
609       mCurrentLabelUnderMousePointer = 1;
610       return; 
611     }
612     else { // inside the label image
613       vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
614       mCurrentLabelUnderMousePointer = 
615         mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0);
616       return;
617     }
618   }
619   else {
620     // DD("out of mask");
621     mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL
622   }
623 #endif
624 }
625 //------------------------------------------------------------------------------
626
627
628 //------------------------------------------------------------------------------
629 void vvToolSegmentation::RemoveLabel() {
630   DD("RemoveLabel");
631   if (mCurrentLabelUnderMousePointer == 0) return;
632   // First actor=0 and is label 1. Label 0 is not an actor, it is BG
633   int actorNumber = mCurrentLabelUnderMousePointer-1; 
634   // Set actor invisible
635   mCurrentCCLActors[actorNumber]->SetVisible(false);
636   mCurrentSlicerManager->Render();
637   // Set image label
638   vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
639   int * pPix = (int*)image->GetScalarPointer();
640   int n = 0;
641   for(uint i=0; i<image->GetNumberOfPoints(); i++) {
642     if (pPix[i] == mCurrentLabelUnderMousePointer) pPix[i] = 0;
643     if (pPix[i] != 0) n++; // count the number of pixels in the foreground
644   }
645   // Update mask size
646   mCurrentMaskSizeInPixels = n;
647   mCurrentMaskSizeInCC = mCurrentMaskImage->GetSpacing()[0] * mCurrentMaskImage->GetSpacing()[1] * mCurrentMaskImage->GetSpacing()[2] * n / (10*10*10);
648   UpdateMaskSizeLabels();
649 }
650 //------------------------------------------------------------------------------