1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
5 - University of LYON http://www.universite-lyon.fr/
6 - Léon Bérard cancer center http://oncora1.lyon.fnclcc.fr
7 - CREATIS CNRS laboratory http://www.creatis.insa-lyon.fr
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.
13 It is distributed under dual licence
15 - BSD See included LICENSE.txt file
16 - CeCILL-B http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
18 #ifndef _vvSegmentationDialog_CXX
19 #define _vvSegmentationDialog_CXX
23 #include "vvSegmentationDialog.h"
24 #include "vvProgressDialog.h"
25 #include "vvImageWriter.h"
26 #include "vvLandmarks.h"
27 #include "vvInteractorStyleNavigator.h"
30 #include "vtkMarchingCubes.h"
31 #include "vtkMarchingSquares.h"
32 #include "vtkImageClip.h"
33 #include "vtkCamera.h"
34 #include "vtkRenderer.h"
35 #include "vtkProperty.h"
36 #include "vtkLookupTable.h"
37 #include "vtkClipPolyData.h"
38 #include "vtkImageToPolyDataFilter.h"
39 #include "vtkLookupTable.h"
40 #include "vtkDoubleArray.h"
41 #include "vtkPointData.h"
42 #include "vtkCellData.h"
43 #include "vtkImageMapToWindowLevelColors.h"
44 #include "vtkImageContinuousErode3D.h"
45 #include "vtkImageContinuousDilate3D.h"
46 #include "vtkImageLogic.h"
47 #include "vtkInteractorStyleTrackballCamera.h"
48 #include "vtkImageSeedConnectivity.h"
49 #include "vtkConnectivityFilter.h"
50 #include "vtkPolyData.h"
51 #include <vtkPolyDataMapper.h>
52 #include <vtkImageData.h>
53 #include "vtkInformation.h"
54 #include "vtkInformationVector.h"
55 #include "vtkStreamingDemandDrivenPipeline.h"
56 #include <vtkPolyDataWriter.h>
58 #include <QMessageBox>
60 //====================================================================
61 vvSegmentationDialog::vvSegmentationDialog(QWidget * parent, Qt::WindowFlags f)
62 :QDialog(parent,f), Ui::vvSegmentationDialog()
67 mManager = new vvSlicerManager(1);
69 mClipper = vtkImageClip::New();
70 mSquares1 = vtkMarchingSquares::New();
71 mSquaresMapper1 = vtkPolyDataMapper::New();
72 mSquaresActor1 = vtkActor::New();
74 mSquares2 = vtkMarchingSquares::New();
75 mSquaresMapper2 = vtkPolyDataMapper::New();
76 mSquaresActor2 = vtkActor::New();
78 //m3DMapper = vtkPolyDataMapper::New();
79 //m3DActor = vtkActor::New();
80 m3DExtractor = vtkMarchingCubes::New();
84 mBinaireImages.clear();
87 connect(clipping1Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
88 connect(clipping2Slider,SIGNAL(valueChanged(int)),this,SLOT(clippingvaluechanged(int)));
89 connect(binaryButton,SIGNAL(clicked()),this,SLOT(BinariseSurface()));
90 connect(saveButton,SIGNAL(clicked()),this,SLOT(Save()));
91 connect(erodeButton,SIGNAL(clicked()),this,SLOT(Erode()));
92 connect(dilateButton,SIGNAL(clicked()),this,SLOT(Dilate()));
93 connect(dimButton,SIGNAL(clicked()),this,SLOT(ChangeDimRendering()));
94 connect(kernelSpinBox,SIGNAL(valueChanged(int)),this,SLOT(KernelValueChanged(int)));
96 binaryButton->setEnabled(0);
97 erodeButton->setEnabled(0);
98 dilateButton->setEnabled(0);
99 infoLabel->setText("Select Up and Down threshold before clicking binarise !");
102 vvSegmentationDialog::~vvSegmentationDialog()
106 mSquaresActor1->Delete();
107 mSquaresMapper1->Delete();
110 mSquaresActor2->Delete();
111 mSquaresMapper2->Delete();
114 //m3DMapper->Delete();
115 //m3DActor->Delete();
116 m3DExtractor->Delete();
118 for (unsigned int i = 0; i < mBinaireImages.size(); i++)
119 mBinaireImages[i]->Delete();
121 for (unsigned int i = 0; i < m3DActors.size(); i++)
122 m3DActors[i]->Delete();
124 for (unsigned int i = 0; i < m3DMappers.size(); i++)
125 m3DMappers[i]->Delete();
130 //----------------------------------------------------------------------------
131 // This templated function executes the filter for any type of data.
132 // Handles the one input operations
134 void vvImageBinarize(vtkImageData *in1Data, T *in1Ptr,
135 int outExt[6],int clampMin, int clampMax)
137 int idxR, idxY, idxZ;
139 vtkIdType inIncX, inIncY, inIncZ;
142 // find the region to loop over
144 (outExt[1] - outExt[0]+1)*in1Data->GetNumberOfScalarComponents();
145 // What a pain. Maybe I should just make another filter.
147 maxY = outExt[3] - outExt[2];
148 maxZ = outExt[5] - outExt[4];
150 // Get increments to march through data
151 in1Data->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
153 for (idxZ = 0; idxZ <= maxZ; idxZ++) {
154 for (idxY = 0; idxY <= maxY; idxY++) {
155 for (idxR = 0; idxR < rowLength; idxR++) {
156 if (static_cast<double>(*in1Ptr) > clampMin && static_cast<double>(*in1Ptr) <= clampMax)
157 *in1Ptr = static_cast<T>(1);
159 *in1Ptr = static_cast<T>(0);
168 void vvSegmentationDialog::SetImage(vvImage::Pointer image)
171 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
172 mManager->SetImage(image);
173 mManager->SetSlicerWindow(0,viewWidget->GetRenderWindow());
174 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
175 mManager->SetInteractorStyleNavigator(0,style);
179 mManager->GetImage()->GetScalarRange(range);
180 mManager->GetSlicer(0)->SetColorWindow(range[1]-range[0]);
181 mManager->GetSlicer(0)->SetColorLevel((range[1]+range[0])/2);
183 clipping1Slider->setMinimum(range[0]);
184 clipping1Slider->setMaximum(range[1]);
185 clipping2Slider->setMinimum(range[0]);
186 clipping2Slider->setMaximum(range[1]);
187 clipping1Slider->setValue(range[0]);
188 clipping2Slider->setValue(range[1]);
190 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
191 mSquares1->SetValue(0,clipping1Slider->value());
192 mSquares2->SetValue(0,clipping2Slider->value());
193 mSquares1->SetInput(mClipper->GetOutput());
194 mSquares2->SetInput(mClipper->GetOutput());
196 mSquaresMapper1->SetInput(mSquares1->GetOutput());
197 mSquaresMapper2->SetInput(mSquares2->GetOutput());
198 mSquaresMapper1->ScalarVisibilityOff();
199 mSquaresMapper2->ScalarVisibilityOff();
201 mSquaresActor1->SetMapper(mSquaresMapper1);
202 mSquaresActor2->SetMapper(mSquaresMapper2);
203 mSquaresActor1->GetProperty()->SetColor(1.0,0,0);
204 mSquaresActor2->GetProperty()->SetColor(0,0,1.0);
205 mSquaresActor1->SetPickable(0);
206 mSquaresActor2->SetPickable(0);
208 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor1);
209 mManager->GetSlicer(0)->GetRenderer()->AddActor(mSquaresActor2);
214 UpdateSlice(0,mManager->GetSlicer(0)->GetSlice());
216 connect(mManager,SIGNAL(UpdateTSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
217 connect(mManager,SIGNAL(UpdateSlice(int,int)),this,SLOT(UpdateSlice(int, int)));
218 connect(mManager,SIGNAL(UpdateSliceRange(int,int,int,int,int)),this,SLOT(UpdateSlice(int, int)));
219 connect(mManager,SIGNAL(LandmarkAdded()),this,SLOT(InsertSeed()));
220 QApplication::restoreOverrideCursor();
223 void vvSegmentationDialog::UpdateSlice(int slicer,int slices)
225 int slice = mManager->GetSlicer(0)->GetSlice();
226 int tslice = mManager->GetSlicer(0)->GetTSlice();
227 mClipper->SetInput(mManager->GetSlicer(0)->GetInput());
228 int* extent = mManager->GetSlicer(0)->GetImageActor()->GetDisplayExtent();
229 mClipper->SetOutputWholeExtent(extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
231 for (i = 0; i < 6; i = i+2) {
232 if (extent[i] == extent[i+1]) {
239 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[0] > slice) {
240 mSquaresActor1->SetPosition(1,0,0);
241 mSquaresActor2->SetPosition(1,0,0);
243 mSquaresActor1->SetPosition(-1,0,0);
244 mSquaresActor2->SetPosition(-1,0,0);
248 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[1] > slice) {
249 mSquaresActor1->SetPosition(0,1,0);
250 mSquaresActor2->SetPosition(0,1,0);
252 mSquaresActor1->SetPosition(0,-1,0);
253 mSquaresActor2->SetPosition(0,-1,0);
257 if (mManager->GetSlicer(0)->GetRenderer()->GetActiveCamera()->GetPosition()[2] > slice) {
258 mSquaresActor1->SetPosition(0,0,1);
259 mSquaresActor2->SetPosition(0,0,1);
261 mSquaresActor1->SetPosition(0,0,-1);
262 mSquaresActor2->SetPosition(0,0,-1);
269 if (m3DActors.size()) {
270 for (unsigned int i =0; i < m3DActors.size(); i++) {
271 if (m3DActors[i]->GetVisibility()) {
272 m3DActors[i]->VisibilityOff();
275 std::cout << "display " << tslice << " on " << m3DActors.size() << std::endl;
276 m3DActors[tslice]->VisibilityOn();
283 void vvSegmentationDialog::clippingvaluechanged(int value)
285 binaryButton->setEnabled(1);
286 int min = (clipping1Slider->value() < clipping2Slider->value() ) ?
287 clipping1Slider->value():clipping2Slider->value();
288 int max = (clipping1Slider->value() > clipping2Slider->value() ) ?
289 clipping1Slider->value():clipping2Slider->value();
290 mSquares1->SetValue(0,min);
291 mSquares2->SetValue(0,max);
293 QString textMin = "<b> Min : </b>";
294 textMin += QString::number(min);
295 QString textMax = "\n <b> Max : </b>";
296 textMax += QString::number(max);
297 minLabel->setText(textMin);
298 maxLabel->setText(textMax);
300 if (mSquares1->GetInput()) {
308 void vvSegmentationDialog::BinariseSurface()
310 infoLabel->setText("Click erode then space on desired organ !");
312 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
313 int clampMin = (clipping1Slider->value() < clipping2Slider->value() ) ?
314 clipping1Slider->value():clipping2Slider->value();
315 int clampMax = (clipping1Slider->value() > clipping2Slider->value() ) ?
316 clipping1Slider->value():clipping2Slider->value();
317 vtkImageData* outputImage = vtkImageData::New();
319 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
320 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
322 image->GetWholeExtent(ext);
324 in1Ptr = image->GetScalarPointerForExtent(ext);
326 switch (image->GetScalarType()) {
328 vvImageBinarize(image, static_cast<VTK_TT *>(in1Ptr),
329 ext,clampMin,clampMax));
331 std::cerr << "Error, unknown pixel format : " << image->GetScalarTypeAsString() << std::endl;
335 outputImage->Initialize();
336 outputImage->SetExtent(ext);
337 outputImage->SetOrigin(image->GetOrigin());
338 outputImage->SetSpacing(image->GetSpacing());
339 outputImage->SetScalarTypeToUnsignedChar();
340 outputImage->CopyAndCastFrom(image,ext);
341 outputImage->Update();
343 image->DeepCopy(outputImage);
344 image->UpdateInformation();
345 image->PropagateUpdateExtent();
347 vtkImageData* imageBin = vtkImageData::New();
348 imageBin->DeepCopy(image);
350 mBinaireImages.push_back(imageBin);
353 outputImage->Delete();
354 erodeButton->setEnabled(1);
355 QApplication::restoreOverrideCursor();
356 mManager->SetColorWindow(2);
357 mManager->SetColorLevel(0.5);
361 void vvSegmentationDialog::Erode()
363 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
364 vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
365 erode->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
366 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
367 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
368 erode->SetInput(image);
370 image->DeepCopy(erode->GetOutput());
374 dilateButton->setEnabled(1);
376 QApplication::restoreOverrideCursor();
379 void vvSegmentationDialog::Dilate()
381 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
382 vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
383 vtkImageLogic* And = vtkImageLogic::New();
384 And->SetOperationToAnd();
385 dilate->SetKernelSize(mKernelValue,mKernelValue,mKernelValue);
386 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
387 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
388 dilate->SetInput(image);
389 vtkImageData* mask = mBinaireImages[numImage];
390 And->SetInput1(dilate->GetOutput());
391 And->SetInput2(mask);
393 image->DeepCopy(And->GetOutput());
399 QApplication::restoreOverrideCursor();
402 void vvSegmentationDialog::InsertSeed()
404 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
406 point4D[0] = mManager->GetLandmarks()->GetCoordinates(
407 mManager->GetLandmarks()->GetNumberOfPoints()-1)[0];
408 point4D[1] = mManager->GetLandmarks()->GetCoordinates(
409 mManager->GetLandmarks()->GetNumberOfPoints()-1)[1];
410 point4D[2] = mManager->GetLandmarks()->GetCoordinates(
411 mManager->GetLandmarks()->GetNumberOfPoints()-1)[2];
412 point4D[3] = mManager->GetLandmarks()->GetCoordinates(
413 mManager->GetLandmarks()->GetNumberOfPoints()-1)[3];
415 point4D[0] = point4D[0]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[0];
416 point4D[1] = point4D[1]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[1];
417 point4D[2] = point4D[2]/mManager->GetSlicer(0)->GetImage()->GetVTKImages()[0]->GetSpacing()[2];
419 vtkImageSeedConnectivity* seed = vtkImageSeedConnectivity::New();
420 seed->SetInputConnectValue(1);
421 seed->SetOutputConnectedValue(1);
422 seed->SetOutputUnconnectedValue(0);
423 seed->AddSeed(point4D[0],point4D[1],point4D[2]);
425 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
426 vtkImageData* image = mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage];
427 seed->SetInput(image);
429 image->DeepCopy(seed->GetOutput());
434 QApplication::restoreOverrideCursor();
437 void vvSegmentationDialog::ChangeDimRendering()
439 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
441 if (dimButton->text() == "3D") {
442 if (m3DActors.size() == 0) {
443 m3DExtractor->SetValue(0,0.5);
444 for (unsigned int numImage = 0; numImage < mManager->GetSlicer(0)->GetImage()->GetVTKImages().size(); numImage++) {
445 vtkActor* actor = vtkActor::New();
446 m3DExtractor->SetInput(mManager->GetSlicer(0)->GetImage()->GetVTKImages()[numImage]);
447 m3DExtractor->Update();
449 vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
450 mapper->SetInput(m3DExtractor->GetOutput());
451 m3DMappers.push_back(mapper);
453 actor->SetMapper(mapper);
454 actor->GetProperty()->SetColor(1.0,0.7,0.2);
455 actor->VisibilityOff();
457 mManager->GetSlicer(0)->GetRenderer()->AddActor(actor);
458 m3DActors.push_back(actor);
462 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.5,0.6,0.9);
463 m3DActors[0]->VisibilityOn();
465 vtkInteractorStyleTrackballCamera* style = vtkInteractorStyleTrackballCamera::New();
466 mManager->SetInteractorStyleNavigator(0,style);
469 mManager->GetSlicer(0)->GetImageActor()->VisibilityOff();
470 mSquaresActor1->VisibilityOff();
471 mSquaresActor2->VisibilityOff();
473 dimButton->setText("2D");
475 mManager->GetSlicer(0)->GetRenderer()->SetBackground(0.0,0.0,0.0);
476 vvInteractorStyleNavigator* style = vvInteractorStyleNavigator::New();
477 mManager->SetInteractorStyleNavigator(0,style);
480 mManager->GetSlicer(0)->SetSliceOrientation(2);
481 m3DActors[mManager->GetSlicer(0)->GetTSlice()]->VisibilityOff();
483 mManager->GetSlicer(0)->GetImageActor()->VisibilityOn();
484 mSquaresActor1->VisibilityOn();
485 mSquaresActor2->VisibilityOn();
486 dimButton->setText("3D");
488 QApplication::restoreOverrideCursor();
491 void vvSegmentationDialog::KernelValueChanged(int kernel)
493 mKernelValue = kernel;
496 void vvSegmentationDialog::Save()
498 if (dimButton->text() == "2D") { //If in *3D* mode, save the mesh
499 QString fileName = QFileDialog::getSaveFileName(this,
501 QDir::home().dirName(),
502 "Mesh Files (*.vtk *.vtp)");
503 if (!fileName.isEmpty()) {
504 vtkSmartPointer<vtkPolyDataWriter> w = vtkSmartPointer<vtkPolyDataWriter>::New();
505 w->SetInput(m3DExtractor->GetOutput());
506 w->SetFileName(fileName.toStdString().c_str());
510 QStringList OutputListeFormat;
511 OutputListeFormat.clear();
512 int dimension = mManager->GetDimension();
513 if (dimension == 1) {
514 OutputListeFormat.push_back(".mhd");
516 if (dimension == 2) {
517 OutputListeFormat.push_back(".bmp");
518 OutputListeFormat.push_back(".png");
519 OutputListeFormat.push_back(".jpeg");
520 OutputListeFormat.push_back(".tif");
521 OutputListeFormat.push_back(".mhd");
522 OutputListeFormat.push_back(".hdr");
523 OutputListeFormat.push_back(".vox");
524 } else if (dimension == 3) {
525 OutputListeFormat.push_back(".mhd");
526 OutputListeFormat.push_back(".hdr");
527 OutputListeFormat.push_back(".vox");
528 } else if (dimension == 4) {
529 OutputListeFormat.push_back(".mhd");
531 QString Extensions = "AllFiles(*.*)";
532 for (int i = 0; i < OutputListeFormat.count(); i++) {
533 Extensions += ";;Images ( *";
534 Extensions += OutputListeFormat[i];
537 QString fileName = QFileDialog::getSaveFileName(this,
539 QDir::home().dirName(),
541 if (!fileName.isEmpty()) {
542 std::string fileformat = vtksys::SystemTools::GetFilenameLastExtension(fileName.toStdString());
543 if (OutputListeFormat.contains(
544 fileformat.c_str())) {
545 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
546 vvProgressDialog progress("Saving "+fileName.toStdString());
547 qApp->processEvents();
548 vvImageWriter *writer = new vvImageWriter;
549 writer->SetOutputFileName(fileName.toStdString());
550 writer->SetInput(mManager->GetSlicer(0)->GetImage());
551 writer->Update(dimension,"unsigned_char");
552 QApplication::restoreOverrideCursor();
553 if (writer->GetLastError().size()) {
554 QString error = "Saving did not succeed\n";
555 error += writer->GetLastError().c_str();
556 QMessageBox::information(this,tr("Saving Problem"),error);
560 QString error = fileformat.c_str();
562 error += "no file format specified !";
564 error += " format unknown !!!\n";
565 QMessageBox::information(this,tr("Saving Problem"),error);
572 #endif /* end #define _vvSegmentationDialog_CXX */