30 #include <QApplication> 32 #include "milxQtModel.h" 33 #include "milxQtImage.h" 34 #include "milxQtFile.h" 37 #include <vtkWindowToImageFilter.h> 39 #include <tclap/CmdLine.h> 41 using namespace TCLAP;
43 int main(
int argc,
char* argv[])
45 QApplication app(argc,argv);
46 QMainWindow mainWindow;
50 milx::PrintInfo(
"--------------------------------------------------------");
54 milx::PrintInfo(
"Australian e-Health Research Centre, CSIRO, Australia.");
58 milx::PrintInfo(
"--------------------------------------------------------\n");
65 ValueArg<std::string> outputArg(
"o",
"output",
"Output Screenshot name",
false,
"screenshot.png",
"Output");
66 ValueArg<std::string> imageArg(
"i",
"image",
"Load and generate image slices as planes (axial, coronal & saggital)",
false,
"image.nii.gz",
"Image");
67 ValueArg<std::string> vectorsArg(
"v",
"vectors",
"Generate and display vector field from model. If no vectors are present then scalars and normals will be used",
false,
"vectors.vtk",
"Vectors");
68 ValueArg<std::string> maskArg(
"s",
"scalarmask",
"Clip the main mesh based on binary scalar values in model",
false,
"mask.vtk",
"Scalar Mask");
69 ValueArg<std::string> setScalarsArg(
"",
"setscalars",
"Set active scalars of model as array name given",
false,
"Stats",
"Set Scalars");
70 ValueArg<std::string> labelArg(
"l",
"label",
"Overlay binary image/label on the image",
false,
"labelling.nii.gz",
"Label");
71 ValueArg<std::string> transformArg(
"t",
"transform",
"Transform (ITK Format) to apply to objects being rendered",
false,
"rigid.txt",
"Transform");
72 ValueArg<std::string> isoArg(
"",
"isosurface",
"Generate Iso-surface (surface from label image) from the image",
false,
"data.nii.gz",
"Isosurface");
73 ValueArg<std::string> loadScalarsArg(
"",
"loadscalars",
"Load scalars for the mesh from another mesh",
false,
"scalars.vtk",
"Scalars");
74 ValueArg<std::string> loadViewFileArg(
"",
"loadviewfile",
"Load saved view from file (use onscreen mode to save view files)",
false,
"camera.cam",
"Load View File");
75 ValueArg<std::string> scalarBarArg(
"",
"scalarbar",
"Enable the scalar bar for display with given name.",
false,
"Scalars",
"Scalar Bar");
76 ValueArg<float> opacityArg(
"",
"opacity",
"Set the opacity of the models",
false, 0.5,
"Opacity");
77 ValueArg<float> isoValueArg(
"",
"isovalue",
"Set the label or iso-surface value for option --isosurface.",
false, 0.5,
"Isovalue");
78 ValueArg<float> minArg(
"",
"min",
"Set the minimum value for scalars on model.",
false, 0.0,
"Minimum Scalar");
79 ValueArg<float> maxArg(
"",
"max",
"Set the maximum value for scalars on model.",
false, 1.0,
"Maximum Scalar");
80 ValueArg<float> redArg(
"",
"redbackground",
"Set the redness value (0-1) for the background.",
false, 1.0,
"Red Component");
81 ValueArg<float> greenArg(
"",
"greenbackground",
"Set the greenness value (0-1) for the background.",
false, 1.0,
"Green Component");
82 ValueArg<float> blueArg(
"",
"bluebackground",
"Set the blueness value (0-1) for the background.",
false, 1.0,
"Blue Component");
83 ValueArg<float> zoomArg(
"",
"zoom",
"Zoom in on the current view by given factor.",
false, 2.0,
"Zoom");
84 ValueArg<int> heightArg(
"y",
"height",
"Set the height of the window.",
false, 600,
"Height");
85 ValueArg<int> widthArg(
"x",
"width",
"Set the width of the window.",
false, 800,
"Width");
86 ValueArg<int> axialSliceArg(
"",
"axialslice",
"Set the axial slice of the image.",
false, 0,
"Axial Slice");
87 ValueArg<int> coronalSliceArg(
"",
"coronalslice",
"Set the coronal slice of the image.",
false, 0,
"Coronal Slice");
88 ValueArg<int> saggitalSliceArg(
"",
"saggitalslice",
"Set the saggital slice of the image.",
false, 0,
"Saggital Slice");
90 SwitchArg jetArg(
"",
"jet",
"Change colourmap of the scalars to the Jet map",
false);
91 SwitchArg vtkArg(
"",
"vtk",
"Change colourmap of the scalars to blue-red (rainbow VTK) map",
false);
92 SwitchArg hsvArg(
"",
"hsv",
"Change colourmap of the scalars to blue-red (rainbow HSV) map",
false);
93 SwitchArg rainbowArg(
"",
"rainbow",
"Change colourmap of the scalars to the rainbow map",
false);
94 SwitchArg spectralArg(
"",
"spectral",
"Change colourmap of the scalars to the spectral map",
false);
95 SwitchArg nihArg(
"",
"NIH",
"Change colourmap of the scalars to NIH",
false);
96 SwitchArg fireArg(
"",
"NIH_FIRE",
"Change colourmap of the scalars to NIH Fire",
false);
97 SwitchArg aalArg(
"",
"AAL",
"Change colourmap of the scalars to AAL",
false);
98 SwitchArg fsArg(
"",
"FS",
"Change colourmap of the scalars to FreeSurfer",
false);
99 SwitchArg hotArg(
"",
"HOT",
"Change colourmap of the scalars to HOT",
false);
100 SwitchArg coolArg(
"",
"COOL",
"Change colourmap of the scalars to COOL",
false);
101 SwitchArg loadViewArg(
"",
"loadview",
"Load saved view (use smilx or onscreen render mode to view and save with Right Click->View->Save View",
false);
102 SwitchArg onscreenArg(
"",
"onscreen",
"Enable on screen rendering, i.e. display the rendering as an interactive window.",
false);
103 SwitchArg whiteArg(
"",
"white",
"Make background white rather than default gradient colour.",
false);
104 SwitchArg inverseArg(
"",
"inverse",
"Use the inverse transform when transform file is provided.",
false);
105 SwitchArg noaxialArg(
"",
"noaxial",
"Do not show axial slice when image is given.",
false);
106 SwitchArg nocoronalArg(
"",
"nocoronal",
"Do not show coronal slice when image is given.",
false);
107 SwitchArg nosaggitalArg(
"",
"nosaggital",
"Do not show saggital slice when image is given.",
false);
108 SwitchArg axialArg(
"",
"axial",
"Show axial view based on position of first surface.",
false);
109 SwitchArg coronalArg(
"",
"coronal",
"Show coronal view based on position of first surface.",
false);
110 SwitchArg saggitalArg(
"",
"saggital",
"Show saggital view based on position of first surface.",
false);
111 SwitchArg removeScalarsArg(
"",
"removescalars",
"Remove the scalars of the models.",
false);
112 SwitchArg clampScalarsArg(
"",
"clampscalars",
"Clamp the scalars of the models to background colour (outside colourmap) from min/max values provided.",
false);
113 SwitchArg clampScalarsBelowArg(
"",
"clampbelow",
"Clamp the scalars of the models to background colour (outside colourmap) below min values provided.",
false);
114 SwitchArg outlineArg(
"",
"outline",
"Display outline box for the model. Model outline overided by image if present.",
false);
115 SwitchArg slicesArg(
"",
"noslices",
"Prevent any slices from being shown. Other elements from image option etc. will still be displayed.",
false);
116 SwitchArg autoColourArg(
"",
"autocolour",
"Colour each additional model automatically based on order.",
false);
117 SwitchArg wireframeArg(
"",
"wireframe",
"Display initial surface as a wireframe model.",
false);
118 SwitchArg wireframesArg(
"",
"wireframes",
"Display all surfaces as a wireframe models.",
false);
119 SwitchArg humanArg(
"",
"nohuman",
"Disable human orientation glyph.",
false);
120 SwitchArg specularArg(
"",
"nospecular",
"Disable specular lighting for the rendered view.",
false);
123 UnlabeledMultiArg<std::string> multinames(
"surfaces",
"Surfaces to overlay",
true,
"Surfaces");
126 std::vector<Arg*> xorlist;
127 xorlist.push_back(&axialArg);
128 xorlist.push_back(&coronalArg);
129 xorlist.push_back(&saggitalArg);
133 cmd.add( multinames );
134 cmd.add( outputArg );
136 cmd.add( vectorsArg );
138 #ifdef ITK_REVIEW //Review only members 141 cmd.add( transformArg );
149 cmd.add( opacityArg );
150 cmd.add( isoValueArg );
151 cmd.add( loadScalarsArg );
152 cmd.add( setScalarsArg );
153 cmd.add( heightArg );
155 cmd.add( axialSliceArg );
156 cmd.add( coronalSliceArg );
157 cmd.add( saggitalSliceArg );
162 cmd.add( rainbowArg );
163 cmd.add( spectralArg );
170 cmd.add( loadViewArg );
171 cmd.add( loadViewFileArg );
172 cmd.add( scalarBarArg );
173 cmd.add( onscreenArg );
175 cmd.add( inverseArg );
176 cmd.add( noaxialArg );
177 cmd.add( nocoronalArg );
178 cmd.add( nosaggitalArg );
179 cmd.add( removeScalarsArg );
180 cmd.add( clampScalarsArg );
181 cmd.add( clampScalarsBelowArg );
182 cmd.add( outlineArg );
183 cmd.add( slicesArg );
184 cmd.add( autoColourArg );
185 cmd.add( wireframeArg );
186 cmd.add( wireframesArg );
188 cmd.add( specularArg );
191 cmd.parse( argc, argv );
195 std::vector<std::string> filenames = multinames.getValue();
196 const std::string screenName = outputArg.getValue();
197 const std::string imageName = imageArg.getValue();
198 const std::string vectorsName = vectorsArg.getValue();
199 const std::string scalarMaskName = maskArg.getValue();
200 const std::string labelName = labelArg.getValue();
201 const std::string transformName = transformArg.getValue();
202 const std::string isoName = isoArg.getValue();
203 const std::string loadScalarsName = loadScalarsArg.getValue();
204 const std::string loadViewName = loadViewFileArg.getValue();
205 const std::string arrayName = setScalarsArg.getValue();
206 const std::string barName = scalarBarArg.getValue();
207 const float opacity = opacityArg.getValue();
208 const float isoValue = isoValueArg.getValue();
209 const float minValue = minArg.getValue();
210 const float maxValue = maxArg.getValue();
211 const float redValue = redArg.getValue();
212 const float greenValue = greenArg.getValue();
213 const float blueValue = blueArg.getValue();
214 const float zoomFactor = zoomArg.getValue();
215 const int windowHeight = heightArg.getValue();
216 const int windowWidth = widthArg.getValue();
217 const int axialSliceNumber = axialSliceArg.getValue();
218 const int coronalSliceNumber = coronalSliceArg.getValue();
219 const int saggitalSliceNumber = saggitalSliceArg.getValue();
224 if(inverseArg.isSet())
226 if(!transformArg.isSet())
228 cerr <<
"Error in arguments! Inverse argument needs to be used with the transform argument." << endl;
232 if(noaxialArg.isSet() || nosaggitalArg.isSet() || nocoronalArg.isSet() || axialSliceArg.isSet() || coronalSliceArg.isSet() || saggitalSliceArg.isSet())
234 if(!imageArg.isSet())
236 cerr <<
"Error in arguments! View/Slice arguments need to be used with the image argument." << endl;
240 if(isoValueArg.isSet())
244 cerr <<
"Error in arguments! Isovalue argument needs to be used with the isosurface argument." << endl;
251 QScopedPointer<milxQtFile> reader(
new milxQtFile);
252 bool errorReading =
false;
253 bool success =
false;
256 cout <<
">> Overlay: Reading Models" << endl;
257 vtkSmartPointer<vtkPolyDataCollection> collection;
261 cerr <<
"Error reading models!" << endl;
266 vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
267 transform->Identity();
268 transform->PostMultiply();
269 if(transformArg.isSet())
272 transform->Concatenate(matrix);
273 if(inverseArg.isSet())
274 transform->Inverse();
278 QList< QSharedPointer<milxQtModel> > models;
279 QSharedPointer<milxQtModel> model;
280 const size_t n = collection->GetNumberOfItems();
284 cerr <<
"At least one model must be provided!" << endl;
288 vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
289 if(autoColourArg.isSet())
291 lookupTable->SetTableRange(0.0, n+1);
292 lookupTable->Build();
296 collection->InitTraversal();
297 for(
size_t j = 0; j < n; j ++)
302 mdl->setName(filenames[j].c_str());
303 mdl->SetInput(collection->GetNextItem());
305 if(removeScalarsArg.isSet() && mdl->GetScalars())
306 mdl->RemoveScalars();
307 if(loadScalarsArg.isSet())
308 mdl->loadScalars(loadScalarsName.c_str());
310 mdl->generateModel();
313 if(autoColourArg.isSet() && j > 0)
316 lookupTable->GetColor(j, colour);
317 mdl->changeColour(colour[0], colour[1], colour[2]);
319 if(setScalarsArg.isSet())
320 mdl->showArray(arrayName.c_str());
323 if(mdl->GetScalars())
325 mdl->GetScalarRange(range);
326 if(clampScalarsBelowArg.isSet())
327 mdl->thresholdScalars(minValue, range[1], vtkMath::Nan());
328 if(clampScalarsArg.isSet())
329 mdl->thresholdScalars(minValue, maxValue, vtkMath::Nan());
336 if( opacityArg.isSet() && (!autoColourArg.isSet() || j == 0) )
337 mdl->SetOpacity(opacity);
338 if(wireframesArg.isSet())
339 mdl->generateWireframe();
344 mainWindow.setCentralWidget(model.data());
345 std::cerr <<
"Done" << std::endl;
348 QScopedPointer<milxQtModel> modelVectors(
new milxQtModel);
349 if(vectorsArg.isSet())
351 success = reader->openModel(vectorsName.c_str(), modelVectors.data());
354 cout <<
">> Applying Vectors" << endl;
355 modelVectors->setName(vectorsName.c_str());
356 modelVectors->generateModel();
357 modelVectors->generateVectorField();
365 QScopedPointer<milxQtModel> modelMask(
new milxQtModel);
368 success = reader->openModel(scalarMaskName.c_str(), modelMask.data());
371 cout <<
">> Overlay: Applying Mask" << endl;
372 modelMask->setName(scalarMaskName.c_str());
373 modelMask->generateModel();
376 modelMask->GetScalars()->SetName(
"Mask");
377 model->GetScalars()->SetName(
"Scalars");
378 model->GetOutput()->GetPointData()->AddArray(modelMask->GetScalars());
379 model->showArray(
"Mask");
380 model->threshold(1.0, 1.0);
381 model->showArray(
"Scalars");
384 model->resetScalarRange();
386 if(model->GetNumberOfPoints() == 0)
388 cerr <<
"Error using scalar mask. Model no longer has any points!" << endl;
396 QScopedPointer<milxQtModel> modelIso(
new milxQtModel);
397 QScopedPointer<milxQtImage> imgIso(
new milxQtImage);
400 cout <<
">> Overlay: Applying Isosurface" << endl;
401 success = reader->openImage(isoName.c_str(), imgIso.data());
402 imgIso->setName(isoName.c_str());
403 imgIso->generateImage();
404 imgIso->threshold(0, isoValue-1.0, isoValue);
410 modelIso->generateIsoSurface(imgIso->GetOutput(), 0, isoValue-1.0);
411 modelIso->generateModel();
412 modelIso->changeColour(0,1,0);
419 cerr <<
"Error Reading one or more of the input files. Exiting." << endl;
425 QScopedPointer<milxQtImage> imgCoronal(
new milxQtImage);
426 QScopedPointer<milxQtImage> imgSagittal(
new milxQtImage);
427 vtkSmartPointer<vtkMatrix4x4> orientTransform = vtkSmartPointer<vtkMatrix4x4>::New();
430 vtkSmartPointer<vtkTransform> transform2 = vtkSmartPointer<vtkTransform>::New();
431 transform2->Identity();
432 transform2->PostMultiply();
435 cout <<
">> Overlay: Reading Image" << endl;
436 errorReading =
false;
437 success = reader->openImage(imageName.c_str(), img.data());
444 img->setName(imageName.c_str());
445 img->generateImage();
446 if(axialSliceArg.isSet())
447 img->setSlice(axialSliceNumber);
455 #ifdef ITK_REVIEW //Review only members 458 img->overlayContour(labelName.c_str());
465 imgCoronal->setDisplayData(img.data());
466 imgSagittal->setDisplayData(img.data());
471 if(!nocoronalArg.isSet())
473 imgCoronal->setName(imageName.c_str());
474 imgCoronal->generateImage();
475 imgCoronal->viewToCoronal();
476 if(coronalSliceArg.isSet())
477 imgCoronal->setSlice(coronalSliceNumber);
481 if(!nosaggitalArg.isSet())
483 imgSagittal->setName(imageName.c_str());
484 imgSagittal->generateImage();
485 imgSagittal->viewToSagittal();
486 if(saggitalSliceArg.isSet())
487 imgSagittal->setSlice(saggitalSliceNumber);
495 cerr <<
"Error Reading the image file. Exiting." << endl;
501 orientTransform->DeepCopy(img->getTransformMatrix());
502 orientTransform->Invert();
503 transform2->Concatenate(orientTransform);
505 cout <<
">> Overlay: Transforming Actors" << endl;
509 model->setWindowTitle(
"MILX-Overlay");
510 model->SetSize(windowHeight, windowWidth);
511 mainWindow.resize(windowWidth, windowHeight);
513 foreach(QSharedPointer<milxQtModel> mdl, models)
515 model->addModelActor(mdl->GetActor());
518 if(imageArg.isSet() && !slicesArg.isSet())
520 if(!noaxialArg.isSet())
521 model->addImageActor(img->GetImageActor(), transform2->GetMatrix());
522 if(!nocoronalArg.isSet())
523 model->addImageActor(imgCoronal->GetImageActor(), transform2->GetMatrix());
524 if(!nosaggitalArg.isSet())
525 model->addImageActor(imgSagittal->GetImageActor(), transform2->GetMatrix());
529 QObject::connect(img.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
530 QObject::connect(imgCoronal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
531 QObject::connect(imgSagittal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
535 cout <<
">>> Overlay: Setting Colourmap" << endl;
537 model->colourMapToJet();
539 model->colourMapToVTK();
541 model->colourMapToHSV();
542 if(rainbowArg.isSet())
543 model->colourMapToRainbow();
544 if(spectralArg.isSet())
545 model->colourMapToSpectral();
547 model->colourMapToNIH();
549 model->colourMapToNIH_Fire();
551 model->colourMapToAAL();
553 model->colourMapToFS();
555 model->colourMapToHOT();
557 model->colourMapToCOOL();
558 if(minArg.isSet() || maxArg.isSet())
559 model->SetScalarRange(range);
560 if(scalarBarArg.isSet())
562 if(minArg.isSet() || maxArg.isSet())
563 model->enableScale(barName.c_str(),
true, range[0], range[1]);
565 model->enableScale(barName.c_str(),
true);
568 if(vectorsArg.isSet())
569 model->AddActor(modelVectors->GetActor());
574 model->AddActor(modelIso->GetActor());
577 model->background(
true);
578 if(outlineArg.isSet())
581 model->enableOutline(img->GetOutput());
583 model->enableOutline();
587 double backgroundColours[3];
588 model->GetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
590 model->disableOrient();
592 backgroundColours[0] = redValue;
594 backgroundColours[1] = greenValue;
596 backgroundColours[2] = blueValue;
597 if(redArg.isSet() || blueArg.isSet() || greenArg.isSet())
598 model->SetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
601 if(wireframeArg.isSet())
602 model->generateWireframe();
603 if(transformArg.isSet())
604 model->SetTransform(transform);
606 model->viewToAxial();
607 if(coronalArg.isSet())
608 model->viewToCoronal();
609 if(saggitalArg.isSet())
610 model->viewToSagittal();
611 if(loadViewArg.isSet())
613 if(loadViewFileArg.isSet())
614 model->loadView(loadViewName.c_str());
615 if(specularArg.isSet())
616 model->disableSpecularDisplay();
620 vtkCamera *camera = model->GetRenderer()->GetActiveCamera();
621 camera->Zoom(zoomFactor);
624 cout <<
">> Overlay: Rendering" << endl;
625 if(!onscreenArg.isSet())
626 model->OffScreenRenderingOn();
631 model->GetRenderWindow()->Render();
632 qApp->processEvents();
635 vtkSmartPointer<vtkWindowToImageFilter> windowToImage = vtkSmartPointer<vtkWindowToImageFilter>::New();
636 windowToImage->SetInput(model->GetRenderWindow());
637 windowToImage->Update();
639 QScopedPointer<milxQtFile> writer(
new milxQtFile);
640 model->GetRenderWindow()->Render();
641 writer->saveImage(screenName.c_str(), windowToImage->GetOutput());
642 cout <<
">> Complete" << endl;
644 model->OffScreenRenderingOff();
645 if(!onscreenArg.isSet())
This class represents the MILX Qt Image Display object using VTK.
This class represents the MILX Qt File I/O object using VTK/ITK/Qt.
This program Animates image slices and animates surfaces in the model view for creating movies...
static bool OpenModelCollection(std::vector< std::string > filenames, vtkSmartPointer< vtkPolyDataCollection > &collection)
Opens model files, which can be a VTK XML, Legacy VTK PolyData File (i.e. either a *...
static vtkMatrix4x4 * OpenITKTransform(std::string filename)
Opens an ITK transform file and converts it to a VTK transform matrix.
This class represents the MILX Qt Model/Mesh Display object using VTK.
void PrintInfo(const std::string msg)
Displays a generic msg to standard output with carriage return.
std::string NumberToString(double num, unsigned zeroPad=0)
Number to string converter.