1 #ifndef _vvSegmentationDialog_CXX
2 #define _vvSegmentationDialog_CXX
4 /*=========================================================================
8 Author : David Sarrut (david.sarrut@gmail.com)
11 Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
12 CREATIS-LRMN http://www.creatis.insa-lyon.fr
14 This program is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, version 3 of the License.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 =========================================================================*/
30 #include "vvSegmentationDialog.h"
31 #include "vvProgressDialog.h"
32 #include "vvImageWriter.h"
33 #include "vvLandmarks.h"
34 #include "vvInteractorStyleNavigator.h"
37 #include "vtkMarchingCubes.h"
38 #include "vtkMarchingSquares.h"
39 #include "vtkImageClip.h"
40 #include "vtkCamera.h"
41 #include "vtkRenderer.h"
42 #include "vtkProperty.h"
43 #include "vtkLookupTable.h"
44 #include "vtkClipPolyData.h"
45 #include "vtkImageToPolyDataFilter.h"
46 #include "vtkLookupTable.h"
47 #include "vtkDoubleArray.h"
48 #include "vtkPointData.h"
49 #include "vtkCellData.h"
50 #include "vtkImageMapToWindowLevelColors.h"
51 #include "vtkImageContinuousErode3D.h"
52 #include "vtkImageContinuousDilate3D.h"
53 #include "vtkImageLogic.h"
54 #include "vtkInteractorStyleTrackballCamera.h"
55 #include "vtkImageSeedConnectivity.h"
56 #include "vtkConnectivityFilter.h"
57 #include "vtkPolyData.h"
58 #include <vtkPolyDataMapper.h>
59 #include <vtkImageData.h>
60 #include "vtkInformation.h"
61 #include "vtkInformationVector.h"
62 #include "vtkStreamingDemandDrivenPipeline.h"
63 #include <vtkPolyDataWriter.h>
65 #include <QMessageBox>
67 //====================================================================
68 vvSegmentationDialog::vvSegmentationDialog(QWidget * parent, Qt::WindowFlags f)
69 :QDialog(parent,f), Ui::vvSegmentationDialog() {
73 mManager = new vvSlicerManager(1);
75 mClipper = vtkImageClip::New();
76 mSquares1 = vtkMarchingSquares::New();
77 mSquaresMapper1 = vtkPolyDataMapper::New();
78 mSquaresActor1 = vtkActor::New();
80 mSquares2 = vtkMarchingSquares::New();
81 mSquaresMapper2 = vtkPolyDataMapper::New();
82 mSquaresActor2 = vtkActor::New();
84 //m3DMapper = vtkPolyDataMapper::New();
85 //m3DActor = vtkActor::New();
86 m3DExtractor = vtkMarchingCubes::New();
90 mBinaireImages.clear();
93 connect(clipping1Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
94 connect(clipping2Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
95 connect(binaryButton,SIGNAL(clicked()),this,SLOT(BinariseSurface()));
96 connect(saveButton,SIGNAL(clicked()),this,SLOT(Save()));
97 connect(erodeButton,SIGNAL(clicked()),this,SLOT(Erode()));
98 connect(dilateButton,SIGNAL(clicked()),this,SLOT(Dilate()));
99 connect(dimButton,SIGNAL(clicked()),this,SLOT(ChangeDimRendering()));
100 connect(kernelSpinBox,SIGNAL(valueChanged(int)),this,SLOT(KernelValueChanged(int)));
102 binaryButton->setEnabled(0);
103 erodeButton->setEnabled(0);
104 dilateButton->setEnabled(0);
105 infoLabel->setText("Select Up and Down threshold before clicking binarise !");
108 vvSegmentationDialog::~vvSegmentationDialog()
112 mSquaresActor1->Delete();
113 mSquaresMapper1->Delete();
116 mSquaresActor2->Delete();
117 mSquaresMapper2->Delete();
120 //m3DMapper->Delete();
121 //m3DActor->Delete();
122 m3DExtractor->Delete();
124 for (unsigned int i = 0; i < mBinaireImages.size(); i++)
125 mBinaireImages[i]->Delete();
127 for (unsigned int i = 0; i < m3DActors.size(); i++)
128 m3DActors[i]->Delete();
130 for (unsigned int i = 0; i < m3DMappers.size(); i++)
131 m3DMappers[i]->Delete();
136 //----------------------------------------------------------------------------
137 // This templated function executes the filter for any type of data.
138 // Handles the one input operations
140 void vvImageBinarize(vtkImageData *in1Data, T *in1Ptr,
141 int outExt[6],int clampMin, int clampMax)
143 int idxR, idxY, idxZ;
145 vtkIdType inIncX, inIncY, inIncZ;
148 // find the region to loop over
150 (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents();
151 // What a pain. Maybe I should just make another filter.
153 maxY = outExt[3] - outExt[2];
154 maxZ = outExt[5] - outExt[4];
156 // Get increments to march through data
157 in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
159 for (idxZ = 0; idxZ <= maxZ; idxZ++)
161 for (idxY = 0; idxY <= maxY; idxY++)
163 for (idxR = 0; idxR < rowLength; idxR++)
165 if (static_cast<double>(*in1Ptr) > clampMin && static_cast<double>(*in1Ptr) <= clampMax)
166 *in1Ptr = static_cast<T>(1);
168 *in1Ptr = static_cast<T>(0);
177 void vvSegmentationDialog::SetImage(vvImage::Pointer image)
180 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
181 mManager->SetImage(image);
182 mManager->SetSlicerWindow(0,viewWidget->GetRenderWindow());
183 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
184 mManager->SetInteractorStyleNavigator(0,style);
188 mManager->GetImage()->GetScalarRange(range);
189 mManager->GetSlicer(0)->SetColorWindow(range[1]-range[0]);
190 mManager->GetSlicer(0)->SetColorLevel((range[1]+range[0])/2);
192 clipping1Slider->setMinimum(range[0]);
193 clipping1Slider->setMaximum(range[1]);
194 clipping2Slider->setMinimum(range[0]);
195 clipping2Slider->setMaximum(range[1]);
196 clipping1Slider->setValue(range[0]);
197 clipping2Slider->setValue(range[1]);
199 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
200 mSquares1->SetValue(0,clipping1Slider->value());
201 mSquares2->SetValue(0,clipping2Slider->value());
202 mSquares1->SetInput(mClipper->GetOutput());
203 mSquares2->SetInput(mClipper->GetOutput());
205 mSquaresMapper1->SetInput(mSquares1->GetOutput());
206 mSquaresMapper2->SetInput(mSquares2->GetOutput());
207 mSquaresMapper1->ScalarVisibilityOff();
208 mSquaresMapper2->ScalarVisibilityOff();
210 mSquaresActor1->SetMapper(mSquaresMapper1);
211 mSquaresActor2->SetMapper(mSquaresMapper2);
212 mSquaresActor1->GetProperty()->SetColor(1.0,0,0);
213 mSquaresActor2->GetProperty()->SetColor(0,0,1.0);
214 mSquaresActor1->SetPickable(0);
215 mSquaresActor2->SetPickable(0);
217 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor1);
218 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor2);
223 UpdateSlice(0,mManager->GetSlicer(0)->GetSlice());
225 connect(mManager,SIGNAL(UpdateTSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
226 connect(mManager,SIGNAL(UpdateSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
227 connect(mManager,SIGNAL(UpdateSliceRange(int,int,int,int,int)),this,SLOT(UpdateSlice(int, int)));
228 connect(mManager,SIGNAL(LandmarkAdded()),this,SLOT(InsertSeed()));
229 QApplication::restoreOverrideCursor();
232 void vvSegmentationDialog::UpdateSlice(int slicer,int slices)
234 int slice = mManager->GetSlicer(0)->GetSlice();
235 int tslice = mManager->GetSlicer(0)->GetTSlice();
236 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
237 int* extent = mManager->GetSlicer(0)->GetImageActor()->GetDisplayExtent();
238 mClipper->SetOutputWholeExtent(extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
240 for (i = 0; i < 6;i = i+2)
242 if (extent[i] == extent[i+1])
251 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice)
253 mSquaresActor1->SetPosition(1,0,0);
254 mSquaresActor2->SetPosition(1,0,0);
258 mSquaresActor1->SetPosition(-1,0,0);
259 mSquaresActor2->SetPosition(-1,0,0);
263 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice)
265 mSquaresActor1->SetPosition(0,1,0);
266 mSquaresActor2->SetPosition(0,1,0);
270 mSquaresActor1->SetPosition(0,-1,0);
271 mSquaresActor2->SetPosition(0,-1,0);
275 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice)
277 mSquaresActor1->SetPosition(0,0,1);
278 mSquaresActor2->SetPosition(0,0,1);
282 mSquaresActor1->SetPosition(0,0,-1);
283 mSquaresActor2->SetPosition(0,0,-1);
290 if (m3DActors.size())
292 for (unsigned int i =0; i < m3DActors.size(); i++)
294 if (m3DActors[i]->GetVisibility())
296 m3DActors[i]->VisibilityOff();
299 std::cout << "display " << tslice << " on " << m3DActors.size() << std::endl;
300 m3DActors[tslice]->VisibilityOn();
307 void vvSegmentationDialog::clippingvaluechanged(int value)
309 binaryButton->setEnabled(1);
310 int min = (clipping1Slider->value() < clipping2Slider->value() ) ?
311 clipping1Slider->value():clipping2Slider->value();
312 int max = (clipping1Slider->value() > clipping2Slider->value() ) ?
313 clipping1Slider->value():clipping2Slider->value();
314 mSquares1->SetValue(0,min);
315 mSquares2->SetValue(0,max);
317 QString textMin = "<b> Min : </b>";
318 textMin += QString::number(min);
319 QString textMax = "\n <b> Max : </b>";
320 textMax += QString::number(max);
321 minLabel->setText(textMin);
322 maxLabel->setText(textMax);
324 if (mSquares1->GetInput())
333 void vvSegmentationDialog::BinariseSurface()
335 infoLabel->setText("Click erode then space on desired organ !");
337 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
338 int clampMin = (clipping1Slider->value() < clipping2Slider->value() ) ?
339 clipping1Slider->value():clipping2Slider->value();
340 int clampMax = (clipping1Slider->value() > clipping2Slider->value() ) ?
341 clipping1Slider->value():clipping2Slider->value();
342 vtkImageData* outputImage = vtkImageData::New();
344 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
346 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
348 image->GetWholeExtent(ext);
350 in1Ptr = image->GetScalarPointerForExtent(ext);
352 switch (image->GetScalarType())
355 vvImageBinarize(image, static_cast<VTK_TT *>(in1Ptr),
356 ext,clampMin,clampMax));
358 std::cerr << "Error, unknown pixel format : " << image->GetScalarTypeAsString() << std::endl;
362 outputImage->Initialize();
363 outputImage->SetExtent(ext);
364 outputImage->SetOrigin(image->GetOrigin());
365 outputImage->SetSpacing(image->GetSpacing());
366 outputImage->SetScalarTypeToUnsignedChar();
367 outputImage->CopyAndCastFrom(image,ext);
368 outputImage->Update();
370 image->DeepCopy(outputImage);
371 image->UpdateInformation();
372 image->PropagateUpdateExtent();
374 vtkImageData* imageBin = vtkImageData::New();
375 imageBin->DeepCopy(image);
377 mBinaireImages.push_back(imageBin);
380 outputImage->Delete();
381 erodeButton->setEnabled(1);
382 QApplication::restoreOverrideCursor();
383 mManager->SetColorWindow(2);
384 mManager->SetColorLevel(0.5);
388 void vvSegmentationDialog::Erode()
390 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
391 vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
392 erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
393 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
395 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
396 erode->SetInput(image);
398 image->DeepCopy(erode->GetOutput());
402 dilateButton->setEnabled(1);
404 QApplication::restoreOverrideCursor();
407 void vvSegmentationDialog::Dilate()
409 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
410 vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
411 vtkImageLogic* And = vtkImageLogic::New();
412 And->SetOperationToAnd();
413 dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
414 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
416 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
417 dilate->SetInput(image);
418 vtkImageData* mask = mBinaireImages[numImage];
419 And->SetInput1(dilate->GetOutput());
420 And->SetInput2(mask);
422 image->DeepCopy(And->GetOutput());
428 QApplication::restoreOverrideCursor();
431 void vvSegmentationDialog::InsertSeed()
433 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
435 point4D[0] = mManager->GetLandmarks()->GetCoordinates(
436 mManager->GetLandmarks()->GetNumberOfPoints()-1)[0];
437 point4D[1] = mManager->GetLandmarks()->GetCoordinates(
438 mManager->GetLandmarks()->GetNumberOfPoints()-1)[1];
439 point4D[2] = mManager->GetLandmarks()->GetCoordinates(
440 mManager->GetLandmarks()->GetNumberOfPoints()-1)[2];
441 point4D[3] = mManager->GetLandmarks()->GetCoordinates(
442 mManager->GetLandmarks()->GetNumberOfPoints()-1)[3];
444 point4D[0] = point4D[0]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[0];
445 point4D[1] = point4D[1]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[1];
446 point4D[2] = point4D[2]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[2];
448 vtkImageSeedConnectivity* seed = vtkImageSeedConnectivity::New();
449 seed->SetInputConnectValue(1);
450 seed->SetOutputConnectedValue(1);
451 seed->SetOutputUnconnectedValue(0);
452 seed->AddSeed(point4D[0],point4D[1],point4D[2]);
454 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
456 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
457 seed->SetInput(image);
459 image->DeepCopy(seed->GetOutput());
464 QApplication::restoreOverrideCursor();
467 void vvSegmentationDialog::ChangeDimRendering()
469 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
471 if (dimButton->text() == "3D")
473 if (m3DActors.size() == 0)
475 m3DExtractor->SetValue(0,0.5);
476 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++)
478 vtkActor* actor = vtkActor::New();
479 m3DExtractor->SetInput(mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage]);
480 m3DExtractor->Update();
482 vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
483 mapper->SetInput(m3DExtractor->GetOutput());
484 m3DMappers.push_back(mapper);
486 actor->SetMapper(mapper);
487 actor->GetProperty()->SetColor(1.0,0.7,0.2);
488 actor->VisibilityOff();
490 mManager->GetSlicer(0)->GetRenderer()->AddActor(actor);
491 m3DActors.push_back(actor);
495 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.5,0.6,0.9);
496 m3DActors[0]->VisibilityOn();
498 vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
499 mManager->SetInteractorStyleNavigator(0,style);
502 mManager->GetSlicer(0)->GetImageActor()->VisibilityOff();
503 mSquaresActor1->VisibilityOff();
504 mSquaresActor2->VisibilityOff();
506 dimButton->setText("2D");
510 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.0,0.0,0.0);
511 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
512 mManager->SetInteractorStyleNavigator(0,style);
515 mManager->GetSlicer(0)->SetSliceOrientation(2);
516 m3DActors[mManager->GetSlicer(0)->GetTSlice()]->VisibilityOff();
518 mManager->GetSlicer(0)->GetImageActor()->VisibilityOn();
519 mSquaresActor1->VisibilityOn();
520 mSquaresActor2->VisibilityOn();
521 dimButton->setText("3D");
523 QApplication::restoreOverrideCursor();
526 void vvSegmentationDialog::KernelValueChanged(int kernel)
528 mKernelValue = kernel;
531 void vvSegmentationDialog::Save()
533 if (dimButton->text() == "2D") //If in *3D* mode, save the mesh
535 QString fileName = QFileDialog::getSaveFileName(this,
537 QDir::home().dirName(),
538 "Mesh Files (*.vtk *.vtp)");
539 if (!fileName.isEmpty())
541 vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
542 w->SetInput(m3DExtractor->GetOutput());
543 w->SetFileName(fileName.toStdString().c_str());
548 QStringList OutputListeFormat;
549 OutputListeFormat.clear();
550 int dimension = mManager->GetDimension();
553 OutputListeFormat.push_back(".mhd");
557 OutputListeFormat.push_back(".bmp");
558 OutputListeFormat.push_back(".png");
559 OutputListeFormat.push_back(".jpeg");
560 OutputListeFormat.push_back(".tif");
561 OutputListeFormat.push_back(".mhd");
562 OutputListeFormat.push_back(".hdr");
563 OutputListeFormat.push_back(".vox");
565 else if (dimension == 3)
567 OutputListeFormat.push_back(".mhd");
568 OutputListeFormat.push_back(".hdr");
569 OutputListeFormat.push_back(".vox");
571 else if (dimension == 4)
573 OutputListeFormat.push_back(".mhd");
575 QString Extensions = "AllFiles(*.*)";
576 for (int i = 0; i < OutputListeFormat.count(); i++)
578 Extensions += ";;Images ( *";
579 Extensions += OutputListeFormat[i];
582 QString fileName = QFileDialog::getSaveFileName(this,
584 QDir::home().dirName(),
586 if (!fileName.isEmpty())
588 std::string fileformat = vtksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
589 if (OutputListeFormat.contains(
592 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
593 vvProgressDialog progress("Saving "+fileName.toStdString());
594 qApp->processEvents();
595 vvImageWriter *writer = new vvImageWriter;
596 writer->SetOutputFileName(fileName.toStdString());
597 writer->SetInput(mManager->GetSlicer(0)->GetImage());
598 writer->Update(dimension,"unsigned_char");
599 QApplication::restoreOverrideCursor();
600 if (writer->GetLastError().size())
602 QString error = "Saving did not succeed\n";
603 error += writer->GetLastError().c_str();
604 QMessageBox::information(this,tr("Saving Problem"),error);
610 QString error = fileformat.c_str();
612 error += "no file format specified !";
614 error += " format unknown !!!\n";
615 QMessageBox::information(this,tr("Saving Problem"),error);
622 #endif /* end #define _vvSegmentationDialog_CXX */