]> Creatis software - clitk.git/blob - vv/vvToolSegmentation.cxx
Add RegionGrowing
[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   DD("end");
348   
349   // mouse pointer
350   QApplication::restoreOverrideCursor();
351 }  
352 //------------------------------------------------------------------------------
353
354
355 //------------------------------------------------------------------------------
356 void vvToolSegmentation::Merge()
357 {
358   if (mCurrentState != State_CCL) return;
359   
360   DD("Merge");
361   // Remove actors
362   for(int i=0; i<mCurrentCCLActors.size(); i++) {
363     if (mCurrentCCLActors[i]) {
364       mCurrentCCLActors[i]->SetVisible(false);
365       mCurrentCCLActors[i]->RemoveActors();
366     }
367   }
368   mCurrentCCLActors.clear();
369
370   // Compute new mask
371   vtkImageData * ccl  = mCurrentCCLImage->GetFirstVTKImageData();
372   vtkImageData * mask = mCurrentMaskImage->GetFirstVTKImageData();
373   int * pCCL = (int*)ccl->GetScalarPointer();
374   char * pPix = (char*)mask->GetScalarPointer();
375   for(uint i=0; i<ccl->GetNumberOfPoints(); i++) {
376     if (pCCL[i] == 0) pPix[i] = GetBackgroundValue(); // copy BG. In CCL BG is always 0
377   }
378
379   // Display new mask and remove ccl
380   mCurrentCCLImage->Reset();
381   mCurrentMaskActor->RemoveActors(); // kill it
382   mCurrentMaskActor = CreateMaskActor(mCurrentMaskImage, 1, 0, false); // renew
383   mCurrentMaskActor->Update();
384   mCurrentMaskActor->SetVisible(true); 
385   // mCurrentSlicerManager->Render();
386   mCurrentState = State_Default;
387 }
388 //------------------------------------------------------------------------------
389
390
391 //------------------------------------------------------------------------------
392 void vvToolSegmentation::Erode()
393 {
394   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
395   // Merge labels if needed
396   Merge();
397   // Get image and start erosion
398   vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
399   erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
400   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
401   erode->SetInput(image);
402   erode->Update();
403   image->DeepCopy(erode->GetOutput());
404   image->Update();
405   UpdateAndRenderNewMask();
406   erode->Delete();
407   QApplication::restoreOverrideCursor();
408 }
409 //------------------------------------------------------------------------------
410
411
412 //------------------------------------------------------------------------------
413 void vvToolSegmentation::Dilate()
414 {
415   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
416   // Merge labels if needed
417   Merge();
418   // Get image and start dilatation
419   vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
420   dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
421   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
422   dilate->SetInput(image);
423   dilate->Update();
424   image->DeepCopy(dilate->GetOutput());
425   image->Update();
426   UpdateAndRenderNewMask();
427   dilate->Delete();
428   QApplication::restoreOverrideCursor();
429 }
430 //------------------------------------------------------------------------------
431
432
433 //------------------------------------------------------------------------------
434 void vvToolSegmentation::UpdateAndRenderNewMask()
435 {
436   bool visible = mCurrentMaskActor->IsVisible();
437   bool cvisible = mCurrentMaskActor->IsContourVisible();
438   mCurrentMaskActor->SetVisible(false);
439   mCurrentMaskActor->SetContourVisible(false);
440   mCurrentMaskActor->UpdateImage();
441   mCurrentMaskActor->SetVisible(visible);
442   mCurrentMaskActor->SetContourVisible(cvisible);
443
444   mCurrentSlicerManager->Render();
445   UpdateMaskSize(mCurrentMaskImage, mCurrentMaskSizeInPixels, mCurrentMaskSizeInCC);
446   UpdateMaskSizeLabels();
447 }
448 //------------------------------------------------------------------------------
449
450 //------------------------------------------------------------------------------
451 void vvToolSegmentation::Labelize()
452 {
453   if (mCurrentState == State_CCL) return; // Do nothing in this case
454   DD("Labelize");
455   // Waiting cursos
456   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
457   mCurrentMaskActor->SetVisible(false);
458   
459   // Build CCL filter
460   vtkImageData* image = mCurrentMaskImage->GetVTKImages()[0];
461   typedef args_info_clitkConnectedComponentLabeling ArgsInfoType;
462   ArgsInfoType a;
463   cmdline_parser_clitkConnectedComponentLabeling_init(&a);
464   a.inputBG_arg = GetBackgroundValue();
465   a.full_flag = false;  // FIXME set by gui
466   a.minSize_arg = 100;  // FIXME set by gui 
467   typedef clitk::ConnectedComponentLabelingGenericFilter<ArgsInfoType> FilterType;
468   FilterType::Pointer filter = FilterType::New();
469   filter->SetArgsInfo(a);
470   filter->SetInputVVImage(mCurrentMaskImage); // FIXME Check type is ok ? convert float ?
471   filter->SetIOVerbose(true);  
472   filter->Update();
473   DD(filter->GetOriginalNumberOfObjects());
474   DD(filter->GetSizeOfObjectsInPixels().size());
475   mCurrentCCLImage = filter->GetOutputVVImage();
476   DDV(filter->GetSizeOfObjectsInPixels(), filter->GetSizeOfObjectsInPixels().size());
477   DD("filter done");
478
479   /*
480   // DEBUG
481   vvImageWriter::Pointer writer = vvImageWriter::New();
482   writer->SetInput(mCurrentCCLImage);
483   writer->SetOutputFileName("bidon-ccl.mha");
484   writer->Update(); 
485   DD(mCurrentCCLImage->IsScalarTypeInteger());
486   */
487   
488   // Create actors 
489   int n = filter->GetSizeOfObjectsInPixels().size();
490   mCurrentCCLActors.clear();
491   for(int i=1; i<=std::min(n,10); i++) { // Start at 1 because 0 is BG. FIXME max by gui
492     QSharedPointer<vvROIActor> actor = CreateMaskActor(mCurrentCCLImage, i, i+1, false); 
493     mCurrentCCLActors.push_back( actor );
494     actor->Update();    
495   }
496   //  mCurrentMaskActor->Update();
497   mCurrentSlicerManager->Render();
498   
499   // UpdateAndRender();
500   mCurrentState = State_CCL;
501   QApplication::restoreOverrideCursor();
502 }
503 //------------------------------------------------------------------------------
504
505 //------------------------------------------------------------------------------
506 QSharedPointer<vvROIActor> vvToolSegmentation::CreateMaskActor(vvImage::Pointer image, int i, int colorID, bool BGMode)
507 {
508   static int depth = 1;
509   depth += 1;
510   QSharedPointer<vvROIActor> actor = QSharedPointer<vvROIActor>(new vvROIActor);
511   double * color = mDefaultLUTColor->GetTableValue(colorID % mDefaultLUTColor->GetNumberOfTableValues ());
512   std::vector<double> c;
513   c.push_back(color[0]);
514   c.push_back(color[1]);
515   c.push_back(color[2]);
516   clitk::DicomRT_ROI::Pointer roi = clitk::DicomRT_ROI::New();
517   roi->SetFromBinaryImage(image, i, std::string("toto"), c, std::string("titi"));
518   if (BGMode) {
519     actor->SetBGMode(true);
520   }
521   else {
522     roi->SetForegroundValueLabelImage(i); // FG mode
523     actor->SetBGMode(false); // FG mode
524   }
525   actor->SetROI(roi);
526   actor->SetSlicerManager(mCurrentSlicerManager);
527   actor->Initialize(depth+i, true); // +1 to start at 1 not 0
528   actor->SetContourVisible(false);
529   actor->SetVisible(true);
530   return actor;
531 }
532 //------------------------------------------------------------------------------
533
534
535 //------------------------------------------------------------------------------
536 void vvToolSegmentation::MousePositionChanged(int slicer)
537 {
538   // DD("MousePositionChanged ");
539   // DD(slicer);
540   double x = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[0];
541   double y = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[1];
542   double z = mCurrentSlicerManager->GetSlicer(slicer)->GetCurrentPosition()[2];
543   mCurrentMousePositionInMM[0] = x;
544   mCurrentMousePositionInMM[1] = y;
545   mCurrentMousePositionInMM[2] = z;
546   // DDV(mCurrentMousePositionInMM, 3);
547
548   //  vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
549   vtkImageData * image = mCurrentMaskImage->GetFirstVTKImageData();
550   double Xover = (x - image->GetOrigin()[0]) / image->GetSpacing()[0];
551   double Yover = (y - image->GetOrigin()[1]) / image->GetSpacing()[1];
552   double Zover = (z - image->GetOrigin()[2]) / image->GetSpacing()[2];
553   int ix, iy, iz;
554   
555   // mCurrentMousePositionInPixel[0] = Xover;
556   // mCurrentMousePositionInPixel[1] = Yover;
557   // mCurrentMousePositionInPixel[2] = Zover;
558   // DDV(mCurrentMousePositionInPixel, 3);
559
560   if (Xover >= image->GetWholeExtent()[0] &&
561       Xover <= image->GetWholeExtent()[1] &&
562       Yover >= image->GetWholeExtent()[2] &&
563       Yover <= image->GetWholeExtent()[3] &&
564       Zover >= image->GetWholeExtent()[4] &&
565       Zover <= image->GetWholeExtent()[5]) {
566     if (mCurrentState == State_Default) { // inside the mask
567       mCurrentLabelUnderMousePointer = 1;
568       return; 
569     }
570     else { // inside the label image
571       vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
572       mCurrentLabelUnderMousePointer = 
573         mCurrentSlicerManager->GetSlicer(0)->GetScalarComponentAsDouble(image, Xover, Yover, Zover, ix, iy, iz, 0);
574       return;
575     }
576   }
577   else {
578     // DD("out of mask");
579     mCurrentLabelUnderMousePointer = 0; // BG is always 0 in CCL
580   }
581 }
582 //------------------------------------------------------------------------------
583
584
585 //------------------------------------------------------------------------------
586 void vvToolSegmentation::RemoveLabel() {
587   DD("RemoveLabel");
588   if (mCurrentLabelUnderMousePointer == 0) return;
589   // First actor=0 and is label 1. Label 0 is not an actor, it is BG
590   int actorNumber = mCurrentLabelUnderMousePointer-1; 
591   // Set actor invisible
592   mCurrentCCLActors[actorNumber]->SetVisible(false);
593   mCurrentSlicerManager->Render();
594   // Set image label
595   vtkImageData * image = mCurrentCCLImage->GetFirstVTKImageData();
596   int * pPix = (int*)image->GetScalarPointer();
597   int n = 0;
598   for(uint i=0; i<image->GetNumberOfPoints(); i++) {
599     if (pPix[i] == mCurrentLabelUnderMousePointer) pPix[i] = 0;
600     if (pPix[i] != 0) n++; // count the number of pixels in the foreground
601   }
602   // Update mask size
603   mCurrentMaskSizeInPixels = n;
604   mCurrentMaskSizeInCC = mCurrentMaskImage->GetSpacing()[0] * mCurrentMaskImage->GetSpacing()[1] * mCurrentMaskImage->GetSpacing()[2] * n / (10*10*10);
605   UpdateMaskSizeLabels();
606 }
607 //------------------------------------------------------------------------------