1 #ifndef _vvSegmentationDialog_CXX
2 #define _vvSegmentationDialog_CXX
4 /*=========================================================================
7 Module: $RCSfile: vvSegmentationDialog.cxx,v $
9 Date: $Date: 2010/01/06 13:31:58 $
10 Version: $Revision: 1.1 $
11 Author : David Sarrut (david.sarrut@gmail.com)
14 Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
15 CREATIS-LRMN http://www.creatis.insa-lyon.fr
17 This program is free software: you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation, version 3 of the License.
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 =========================================================================*/
33 #include "vvSegmentationDialog.h"
34 #include "vvProgressDialog.h"
35 #include "vvImageWriter.h"
36 #include "vvLandmarks.h"
37 #include "vvInteractorStyleNavigator.h"
40 #include "vtkMarchingCubes.h"
41 #include "vtkMarchingSquares.h"
42 #include "vtkImageClip.h"
43 #include "vtkCamera.h"
44 #include "vtkRenderer.h"
45 #include "vtkProperty.h"
46 #include "vtkLookupTable.h"
47 #include "vtkClipPolyData.h"
48 #include "vtkImageToPolyDataFilter.h"
49 #include "vtkLookupTable.h"
50 #include "vtkDoubleArray.h"
51 #include "vtkPointData.h"
52 #include "vtkCellData.h"
53 #include "vtkImageMapToWindowLevelColors.h"
54 #include "vtkImageContinuousErode3D.h"
55 #include "vtkImageContinuousDilate3D.h"
56 #include "vtkImageLogic.h"
57 #include "vtkInteractorStyleTrackballCamera.h"
58 #include "vtkImageSeedConnectivity.h"
59 #include "vtkConnectivityFilter.h"
60 #include "vtkPolyData.h"
61 #include <vtkPolyDataMapper.h>
62 #include <vtkImageData.h>
63 #include "vtkInformation.h"
64 #include "vtkInformationVector.h"
65 #include "vtkStreamingDemandDrivenPipeline.h"
66 #include <vtkPolyDataWriter.h>
68 #include <QMessageBox>
70 //====================================================================
71 vvSegmentationDialog::vvSegmentationDialog(QWidget * parent, Qt::WindowFlags f)
72 :QDialog(parent,f), Ui::vvSegmentationDialog() {
76 mManager = new vvSlicerManager(1);
78 mClipper = vtkImageClip::New();
79 mSquares1 = vtkMarchingSquares::New();
80 mSquaresMapper1 = vtkPolyDataMapper::New();
81 mSquaresActor1 = vtkActor::New();
83 mSquares2 = vtkMarchingSquares::New();
84 mSquaresMapper2 = vtkPolyDataMapper::New();
85 mSquaresActor2 = vtkActor::New();
87 //m3DMapper = vtkPolyDataMapper::New();
88 //m3DActor = vtkActor::New();
89 m3DExtractor = vtkMarchingCubes::New();
93 mBinaireImages.clear();
96 connect(clipping1Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
97 connect(clipping2Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
98 connect(binaryButton,SIGNAL(clicked()),this,SLOT(BinariseSurface()));
99 connect(saveButton,SIGNAL(clicked()),this,SLOT(Save()));
100 connect(erodeButton,SIGNAL(clicked()),this,SLOT(Erode()));
101 connect(dilateButton,SIGNAL(clicked()),this,SLOT(Dilate()));
102 connect(dimButton,SIGNAL(clicked()),this,SLOT(ChangeDimRendering()));
103 connect(kernelSpinBox,SIGNAL(valueChanged(int)),this,SLOT(KernelValueChanged(int)));
105 binaryButton->setEnabled(0);
106 erodeButton->setEnabled(0);
107 dilateButton->setEnabled(0);
108 infoLabel->setText("Select Up and Down threshold before clicking binarise !");
111 vvSegmentationDialog::~vvSegmentationDialog()
115 mSquaresActor1->Delete();
116 mSquaresMapper1->Delete();
119 mSquaresActor2->Delete();
120 mSquaresMapper2->Delete();
123 //m3DMapper->Delete();
124 //m3DActor->Delete();
125 m3DExtractor->Delete();
127 for (unsigned int i = 0; i < mBinaireImages.size(); i++)
128 mBinaireImages[i]->Delete();
130 for (unsigned int i = 0; i < m3DActors.size(); i++)
131 m3DActors[i]->Delete();
133 for (unsigned int i = 0; i < m3DMappers.size(); i++)
134 m3DMappers[i]->Delete();
139 //----------------------------------------------------------------------------
140 // This templated function executes the filter for any type of data.
141 // Handles the one input operations
143 void vvImageBinarize(vtkImageData *in1Data, T *in1Ptr,
144 int outExt[6],int clampMin, int clampMax)
146 int idxR, idxY, idxZ;
148 vtkIdType inIncX, inIncY, inIncZ;
151 // find the region to loop over
153 (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents();
154 // What a pain. Maybe I should just make another filter.
156 maxY = outExt[3] - outExt[2];
157 maxZ = outExt[5] - outExt[4];
159 // Get increments to march through data
160 in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
162 for (idxZ = 0; idxZ <= maxZ; idxZ++)
164 for (idxY = 0; idxY <= maxY; idxY++)
166 for (idxR = 0; idxR < rowLength; idxR++)
168 if (static_cast<double>(*in1Ptr) > clampMin && static_cast<double>(*in1Ptr) <= clampMax)
169 *in1Ptr = static_cast<T>(1);
171 *in1Ptr = static_cast<T>(0);
180 void vvSegmentationDialog::SetImage(vvImage::Pointer image)
183 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
184 mManager->SetImage(image);
185 mManager->SetSlicerWindow(0,viewWidget->GetRenderWindow());
186 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
187 mManager->SetInteractorStyleNavigator(0,style);
191 mManager->GetImage()->GetScalarRange(range);
192 mManager->GetSlicer(0)->SetColorWindow(range[1]-range[0]);
193 mManager->GetSlicer(0)->SetColorLevel((range[1]+range[0])/2);
195 clipping1Slider->setMinimum(range[0]);
196 clipping1Slider->setMaximum(range[1]);
197 clipping2Slider->setMinimum(range[0]);
198 clipping2Slider->setMaximum(range[1]);
199 clipping1Slider->setValue(range[0]);
200 clipping2Slider->setValue(range[1]);
202 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
203 mSquares1->SetValue(0,clipping1Slider->value());
204 mSquares2->SetValue(0,clipping2Slider->value());
205 mSquares1->SetInput(mClipper->GetOutput());
206 mSquares2->SetInput(mClipper->GetOutput());
208 mSquaresMapper1->SetInput(mSquares1->GetOutput());
209 mSquaresMapper2->SetInput(mSquares2->GetOutput());
210 mSquaresMapper1->ScalarVisibilityOff();
211 mSquaresMapper2->ScalarVisibilityOff();
213 mSquaresActor1->SetMapper(mSquaresMapper1);
214 mSquaresActor2->SetMapper(mSquaresMapper2);
215 mSquaresActor1->GetProperty()->SetColor(1.0,0,0);
216 mSquaresActor2->GetProperty()->SetColor(0,0,1.0);
217 mSquaresActor1->SetPickable(0);
218 mSquaresActor2->SetPickable(0);
220 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor1);
221 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor2);
226 UpdateSlice(0,mManager->GetSlicer(0)->GetSlice());
228 connect(mManager,SIGNAL(UpdateTSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
229 connect(mManager,SIGNAL(UpdateSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
230 connect(mManager,SIGNAL(UpdateSliceRange(int,int,int,int,int)),this,SLOT(UpdateSlice(int, int)));
231 connect(mManager,SIGNAL(LandmarkAdded()),this,SLOT(InsertSeed()));
232 QApplication::restoreOverrideCursor();
235 void vvSegmentationDialog::UpdateSlice(int slicer,int slices)
237 int slice = mManager->GetSlicer(0)->GetSlice();
238 int tslice = mManager->GetSlicer(0)->GetTSlice();
239 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
240 int* extent = mManager->GetSlicer(0)->GetImageActor()->GetDisplayExtent();
241 mClipper->SetOutputWholeExtent(extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
243 for (i = 0; i < 6;i = i+2)
245 if (extent[i] == extent[i+1])
254 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice)
256 mSquaresActor1->SetPosition(1,0,0);
257 mSquaresActor2->SetPosition(1,0,0);
261 mSquaresActor1->SetPosition(-1,0,0);
262 mSquaresActor2->SetPosition(-1,0,0);
266 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice)
268 mSquaresActor1->SetPosition(0,1,0);
269 mSquaresActor2->SetPosition(0,1,0);
273 mSquaresActor1->SetPosition(0,-1,0);
274 mSquaresActor2->SetPosition(0,-1,0);
278 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice)
280 mSquaresActor1->SetPosition(0,0,1);
281 mSquaresActor2->SetPosition(0,0,1);
285 mSquaresActor1->SetPosition(0,0,-1);
286 mSquaresActor2->SetPosition(0,0,-1);
293 if (m3DActors.size())
295 for (unsigned int i =0; i < m3DActors.size(); i++)
297 if (m3DActors[i]->GetVisibility())
299 m3DActors[i]->VisibilityOff();
302 std::cout << "display " << tslice << " on " << m3DActors.size() << std::endl;
303 m3DActors[tslice]->VisibilityOn();
310 void vvSegmentationDialog::clippingvaluechanged(int value)
312 binaryButton->setEnabled(1);
313 int min = (clipping1Slider->value() < clipping2Slider->value() ) ?
314 clipping1Slider->value():clipping2Slider->value();
315 int max = (clipping1Slider->value() > clipping2Slider->value() ) ?
316 clipping1Slider->value():clipping2Slider->value();
317 mSquares1->SetValue(0,min);
318 mSquares2->SetValue(0,max);
320 QString textMin = "<b> Min : </b>";
321 textMin += QString::number(min);
322 QString textMax = "\n <b> Max : </b>";
323 textMax += QString::number(max);
324 minLabel->setText(textMin);
325 maxLabel->setText(textMax);
327 if (mSquares1->GetInput())
336 void vvSegmentationDialog::BinariseSurface()
338 infoLabel->setText("Click erode then space on desired organ !");
340 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
341 int clampMin = (clipping1Slider->value() < clipping2Slider->value() ) ?
342 clipping1Slider->value():clipping2Slider->value();
343 int clampMax = (clipping1Slider->value() > clipping2Slider->value() ) ?
344 clipping1Slider->value():clipping2Slider->value();
345 vtkImageData* outputImage = vtkImageData::New();
347 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
349 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
351 image->GetWholeExtent(ext);
353 in1Ptr = image->GetScalarPointerForExtent(ext);
355 switch (image->GetScalarType())
358 vvImageBinarize(image, static_cast<VTK_TT *>(in1Ptr),
359 ext,clampMin,clampMax));
361 std::cerr << "Error, unknown pixel format : " << image->GetScalarTypeAsString() << std::endl;
365 outputImage->Initialize();
366 outputImage->SetExtent(ext);
367 outputImage->SetOrigin(image->GetOrigin());
368 outputImage->SetSpacing(image->GetSpacing());
369 outputImage->SetScalarTypeToUnsignedChar();
370 outputImage->CopyAndCastFrom(image,ext);
371 outputImage->Update();
373 image->DeepCopy(outputImage);
374 image->UpdateInformation();
375 image->PropagateUpdateExtent();
377 vtkImageData* imageBin = vtkImageData::New();
378 imageBin->DeepCopy(image);
380 mBinaireImages.push_back(imageBin);
383 outputImage->Delete();
384 erodeButton->setEnabled(1);
385 QApplication::restoreOverrideCursor();
386 mManager->SetColorWindow(2);
387 mManager->SetColorLevel(0.5);
391 void vvSegmentationDialog::Erode()
393 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
394 vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
395 erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
396 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
398 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
399 erode->SetInput(image);
401 image->DeepCopy(erode->GetOutput());
405 dilateButton->setEnabled(1);
407 QApplication::restoreOverrideCursor();
410 void vvSegmentationDialog::Dilate()
412 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
413 vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
414 vtkImageLogic* And = vtkImageLogic::New();
415 And->SetOperationToAnd();
416 dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
417 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
419 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
420 dilate->SetInput(image);
421 vtkImageData* mask = mBinaireImages[numImage];
422 And->SetInput1(dilate->GetOutput());
423 And->SetInput2(mask);
425 image->DeepCopy(And->GetOutput());
431 QApplication::restoreOverrideCursor();
434 void vvSegmentationDialog::InsertSeed()
436 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
438 point4D[0] = mManager->GetLandmarks()->GetCoordinates(
439 mManager->GetLandmarks()->GetNumberOfPoints()-1)[0];
440 point4D[1] = mManager->GetLandmarks()->GetCoordinates(
441 mManager->GetLandmarks()->GetNumberOfPoints()-1)[1];
442 point4D[2] = mManager->GetLandmarks()->GetCoordinates(
443 mManager->GetLandmarks()->GetNumberOfPoints()-1)[2];
444 point4D[3] = mManager->GetLandmarks()->GetCoordinates(
445 mManager->GetLandmarks()->GetNumberOfPoints()-1)[3];
447 point4D[0] = point4D[0]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[0];
448 point4D[1] = point4D[1]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[1];
449 point4D[2] = point4D[2]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[2];
451 vtkImageSeedConnectivity* seed = vtkImageSeedConnectivity::New();
452 seed->SetInputConnectValue(1);
453 seed->SetOutputConnectedValue(1);
454 seed->SetOutputUnconnectedValue(0);
455 seed->AddSeed(point4D[0],point4D[1],point4D[2]);
457 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
459 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
460 seed->SetInput(image);
462 image->DeepCopy(seed->GetOutput());
467 QApplication::restoreOverrideCursor();
470 void vvSegmentationDialog::ChangeDimRendering()
472 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
474 if (dimButton->text() == "3D")
476 if (m3DActors.size() == 0)
478 m3DExtractor->SetValue(0,0.5);
479 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
481 vtkActor* actor = vtkActor::New();
482 m3DExtractor->SetInput(mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage]);
483 m3DExtractor->Update();
485 vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
486 mapper->SetInput(m3DExtractor->GetOutput());
487 m3DMappers.push_back(mapper);
489 actor->SetMapper(mapper);
490 actor->GetProperty()->SetColor(1.0,0.7,0.2);
491 actor->VisibilityOff();
493 mManager->GetSlicer(0)->GetRenderer()->AddActor(actor);
494 m3DActors.push_back(actor);
498 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.5,0.6,0.9);
499 m3DActors[0]->VisibilityOn();
501 vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
502 mManager->SetInteractorStyleNavigator(0,style);
505 mManager->GetSlicer(0)->GetImageActor()->VisibilityOff();
506 mSquaresActor1->VisibilityOff();
507 mSquaresActor2->VisibilityOff();
509 dimButton->setText("2D");
513 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.0,0.0,0.0);
514 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
515 mManager->SetInteractorStyleNavigator(0,style);
518 mManager->GetSlicer(0)->SetSliceOrientation(2);
519 m3DActors[mManager->GetSlicer(0)->GetTSlice()]->VisibilityOff();
521 mManager->GetSlicer(0)->GetImageActor()->VisibilityOn();
522 mSquaresActor1->VisibilityOn();
523 mSquaresActor2->VisibilityOn();
524 dimButton->setText("3D");
526 QApplication::restoreOverrideCursor();
529 void vvSegmentationDialog::KernelValueChanged(int kernel)
531 mKernelValue = kernel;
534 void vvSegmentationDialog::Save()
536 if (dimButton->text() == "2D") //If in *3D* mode, save the mesh
538 QString fileName = QFileDialog::getSaveFileName(this,
540 QDir::home().dirName(),
541 "Mesh Files (*.vtk *.vtp)");
542 if (!fileName.isEmpty())
544 vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
545 w->SetInput(m3DExtractor->GetOutput());
546 w->SetFileName(fileName.toStdString().c_str());
551 QStringList OutputListeFormat;
552 OutputListeFormat.clear();
553 int dimension = mManager->GetDimension();
556 OutputListeFormat.push_back(".mhd");
560 OutputListeFormat.push_back(".bmp");
561 OutputListeFormat.push_back(".png");
562 OutputListeFormat.push_back(".jpeg");
563 OutputListeFormat.push_back(".tif");
564 OutputListeFormat.push_back(".mhd");
565 OutputListeFormat.push_back(".hdr");
566 OutputListeFormat.push_back(".vox");
568 else if (dimension == 3)
570 OutputListeFormat.push_back(".mhd");
571 OutputListeFormat.push_back(".hdr");
572 OutputListeFormat.push_back(".vox");
574 else if (dimension == 4)
576 OutputListeFormat.push_back(".mhd");
578 QString Extensions = "AllFiles(*.*)";
579 for (int i = 0; i < OutputListeFormat.count(); i++)
581 Extensions += ";;Images ( *";
582 Extensions += OutputListeFormat[i];
585 QString fileName = QFileDialog::getSaveFileName(this,
587 QDir::home().dirName(),
589 if (!fileName.isEmpty())
591 std::string fileformat = vtksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
592 if (OutputListeFormat.contains(
595 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
596 vvProgressDialog progress("Saving "+fileName.toStdString());
597 qApp->processEvents();
598 vvImageWriter *writer = new vvImageWriter;
599 writer->SetOutputFileName(fileName.toStdString());
600 writer->SetInput(mManager->GetSlicer(0)->GetImage());
601 writer->Update(dimension,"unsigned_char");
602 QApplication::restoreOverrideCursor();
603 if (writer->GetLastError().size())
605 QString error = "Saving did not succeed\n";
606 error += writer->GetLastError().c_str();
607 QMessageBox::information(this,tr("Saving Problem"),error);
613 QString error = fileformat.c_str();
615 error += "no file format specified !";
617 error += " format unknown !!!\n";
618 QMessageBox::information(this,tr("Saving Problem"),error);
625 #endif /* end #define _vvSegmentationDialog_CXX */