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