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