26 #include <QApplication> 28 #include "milxQtAnimateModel.h" 29 #include "milxQtImage.h" 30 #include "milxQtFile.h" 32 #include <tclap/CmdLine.h> 34 using namespace TCLAP;
36 int main(
int argc,
char* argv[])
38 QApplication app(argc,argv);
39 QMainWindow mainWindow;
43 milx::PrintInfo(
"--------------------------------------------------------");
47 milx::PrintInfo(
"Australian e-Health Research Centre, CSIRO, Australia.");
51 milx::PrintInfo(
"--------------------------------------------------------\n");
58 ValueArg<std::string> outputArg(
"o",
"output",
"Output movie name",
false,
"movie.avi",
"Output");
59 ValueArg<std::string> imageArg(
"i",
"image",
"Load and generate image slices as planes (axial, coronal & saggital) in view",
false,
"image.nii.gz",
"Image");
60 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");
62 ValueArg<std::string> setScalarsArg(
"",
"setscalars",
"Set active scalars of model as array name given",
false,
"Stats",
"Set Scalars");
63 ValueArg<std::string> labelArg(
"l",
"label",
"Overlay binary image/label on the image",
false,
"labelling.nii.gz",
"Label");
64 ValueArg<std::string> transformArg(
"t",
"transform",
"Transform (ITK Format) to apply to objects being rendered",
false,
"rigid.txt",
"Transform");
65 ValueArg<std::string> isoArg(
"",
"isosurface",
"Generate Iso-surface (surface from label image) from the image",
false,
"data.nii.gz",
"Isosurface");
66 ValueArg<std::string> loadScalarsArg(
"",
"loadscalars",
"Load scalars for the mesh from another mesh",
false,
"scalars.vtk",
"Scalars");
67 ValueArg<std::string> loadViewFileArg(
"",
"loadviewfile",
"Load saved view from file (use onscreen mode to save view files)",
false,
"camera.cam",
"Load View File");
68 ValueArg<std::string> scalarBarArg(
"",
"scalarbar",
"Enable the scalar bar for display with given name.",
false,
"Scalars",
"Scalar Bar");
69 ValueArg<float> opacityArg(
"",
"opacity",
"Set the opacity of the models",
false, 0.5,
"Opacity");
70 ValueArg<float> isoValueArg(
"",
"isovalue",
"Set the label or iso-surface value for option --isosurface.",
false, 0.5,
"Isovalue");
71 ValueArg<float> minArg(
"",
"min",
"Set the minimum value for scalars on model.",
false, 0.0,
"Minimum Scalar");
72 ValueArg<float> maxArg(
"",
"max",
"Set the maximum value for scalars on model.",
false, 1.0,
"Maximum Scalar");
73 ValueArg<float> redArg(
"",
"redbackground",
"Set the redness value (0-1) for the background.",
false, 1.0,
"Red Component");
74 ValueArg<float> greenArg(
"",
"greenbackground",
"Set the greenness value (0-1) for the background.",
false, 1.0,
"Green Component");
75 ValueArg<float> blueArg(
"",
"bluebackground",
"Set the blueness value (0-1) for the background.",
false, 1.0,
"Blue Component");
76 ValueArg<float> zoomArg(
"",
"zoom",
"Zoom in on the current view by given factor.",
false, 2.0,
"Zoom");
77 ValueArg<int> heightArg(
"y",
"height",
"Set the height of the window.",
false, 600,
"Height");
78 ValueArg<int> widthArg(
"x",
"width",
"Set the width of the window.",
false, 800,
"Width");
79 ValueArg<int> axialSliceArg(
"",
"axialslice",
"Set the axial slice of the image.",
false, 0,
"Axial Slice");
80 ValueArg<int> coronalSliceArg(
"",
"coronalslice",
"Set the coronal slice of the image.",
false, 0,
"Coronal Slice");
81 ValueArg<int> saggitalSliceArg(
"",
"saggitalslice",
"Set the saggital slice of the image.",
false, 0,
"Saggital Slice");
82 ValueArg<int> indexArg(
"",
"frameindex",
"Extract the frame numbers from the filenames provided at the nth integer substring in names.",
false, 0,
"Frame Index");
83 ValueArg<int> framesArg(
"f",
"frames",
"Number of frames to write in the movie file.",
false, 128,
"Frames");
85 SwitchArg jetArg(
"",
"jet",
"Change colourmap of the scalars to the Jet map",
false);
86 SwitchArg vtkArg(
"",
"vtk",
"Change colourmap of the scalars to blue-red (rainbow VTK) map",
false);
87 SwitchArg hsvArg(
"",
"hsv",
"Change colourmap of the scalars to blue-red (rainbow HSV) map",
false);
88 SwitchArg rainbowArg(
"",
"rainbow",
"Change colourmap of the scalars to the rainbow map",
false);
89 SwitchArg spectralArg(
"",
"spectral",
"Change colourmap of the scalars to the spectral map",
false);
90 SwitchArg nihArg(
"",
"NIH",
"Change colourmap of the scalars to NIH",
false);
91 SwitchArg fireArg(
"",
"NIH_FIRE",
"Change colourmap of the scalars to NIH Fire",
false);
92 SwitchArg aalArg(
"",
"AAL",
"Change colourmap of the scalars to AAL",
false);
93 SwitchArg fsArg(
"",
"FS",
"Change colourmap of the scalars to FreeSurfer",
false);
94 SwitchArg hotArg(
"",
"HOT",
"Change colourmap of the scalars to HOT",
false);
95 SwitchArg coolArg(
"",
"COOL",
"Change colourmap of the scalars to COOL",
false);
96 SwitchArg loadViewArg(
"",
"loadview",
"Load saved view (use smilx or onscreen render mode to view and save with Right Click->View->Save View",
false);
97 SwitchArg onscreenArg(
"",
"onscreen",
"Enable on screen rendering, i.e. display the rendering as an interactive window.",
false);
98 SwitchArg whiteArg(
"",
"white",
"Make background white rather than default gradient colour.",
false);
99 SwitchArg inverseArg(
"",
"inverse",
"Use the inverse transform when transform file is provided.",
false);
100 SwitchArg noaxialArg(
"",
"noaxial",
"Do not show axial slice when image is given.",
false);
101 SwitchArg nocoronalArg(
"",
"nocoronal",
"Do not show coronal slice when image is given.",
false);
102 SwitchArg nosaggitalArg(
"",
"nosaggital",
"Do not show saggital slice when image is given.",
false);
103 SwitchArg axialArg(
"",
"axial",
"Show axial view based on position of first surface.",
false);
104 SwitchArg coronalArg(
"",
"coronal",
"Show coronal view based on position of first surface.",
false);
105 SwitchArg saggitalArg(
"",
"saggital",
"Show saggital view based on position of first surface.",
false);
106 SwitchArg removeScalarsArg(
"",
"removescalars",
"Remove the scalars of the models.",
false);
107 SwitchArg outlineArg(
"",
"outline",
"Display outline box for the model. Model outline overided by image if present.",
false);
108 SwitchArg slicesArg(
"",
"noslices",
"Prevent any slices from being shown. Other elements from image option etc. will still be displayed.",
false);
109 SwitchArg autoColourArg(
"",
"autocolour",
"Colour each additional model automatically based on order.",
false);
110 SwitchArg wireframesArg(
"",
"wireframes",
"Display all surfaces as a wireframe models.",
false);
111 SwitchArg humanArg(
"",
"nohuman",
"Disable human orientation glyph.",
false);
114 UnlabeledMultiArg<std::string> multinames(
"surfaces",
"Surfaces to Animate",
true,
"Surfaces");
117 std::vector<Arg*> xorlist;
118 xorlist.push_back(&axialArg);
119 xorlist.push_back(&coronalArg);
120 xorlist.push_back(&saggitalArg);
124 cmd.add( multinames );
125 cmd.add( outputArg );
127 cmd.add( vectorsArg );
129 #ifdef ITK_REVIEW //Review only members 132 cmd.add( transformArg );
140 cmd.add( opacityArg );
141 cmd.add( isoValueArg );
142 cmd.add( loadScalarsArg );
143 cmd.add( setScalarsArg );
144 cmd.add( heightArg );
146 cmd.add( axialSliceArg );
147 cmd.add( coronalSliceArg );
148 cmd.add( saggitalSliceArg );
150 cmd.add( framesArg );
155 cmd.add( rainbowArg );
156 cmd.add( spectralArg );
163 cmd.add( loadViewArg );
164 cmd.add( loadViewFileArg );
165 cmd.add( scalarBarArg );
166 cmd.add( onscreenArg );
168 cmd.add( inverseArg );
169 cmd.add( noaxialArg );
170 cmd.add( nocoronalArg );
171 cmd.add( nosaggitalArg );
172 cmd.add( removeScalarsArg );
173 cmd.add( outlineArg );
174 cmd.add( slicesArg );
175 cmd.add( autoColourArg );
176 cmd.add( wireframesArg );
180 cmd.parse( argc, argv );
184 std::vector<std::string> filenames = multinames.getValue();
185 const std::string movieName = outputArg.getValue();
186 const std::string imageName = imageArg.getValue();
187 const std::string vectorsName = vectorsArg.getValue();
189 const std::string labelName = labelArg.getValue();
190 const std::string transformName = transformArg.getValue();
191 const std::string isoName = isoArg.getValue();
192 const std::string loadScalarsName = loadScalarsArg.getValue();
193 const std::string loadViewName = loadViewFileArg.getValue();
194 const std::string arrayName = setScalarsArg.getValue();
195 const std::string barName = scalarBarArg.getValue();
196 const float opacity = opacityArg.getValue();
197 const float isoValue = isoValueArg.getValue();
198 const float minValue = minArg.getValue();
199 const float maxValue = maxArg.getValue();
200 const float redValue = redArg.getValue();
201 const float greenValue = greenArg.getValue();
202 const float blueValue = blueArg.getValue();
203 const float zoomFactor = zoomArg.getValue();
204 const int windowHeight = heightArg.getValue();
205 const int windowWidth = widthArg.getValue();
206 const int axialSliceNumber = axialSliceArg.getValue();
207 const int coronalSliceNumber = coronalSliceArg.getValue();
208 const int saggitalSliceNumber = saggitalSliceArg.getValue();
209 const int index = indexArg.getValue();
210 int frames = framesArg.getValue();
215 if(inverseArg.isSet())
217 if(!transformArg.isSet())
219 cerr <<
"Error in arguments! Inverse argument needs to be used with the transform argument." << endl;
223 if(noaxialArg.isSet() || nosaggitalArg.isSet() || nocoronalArg.isSet() || axialSliceArg.isSet() || coronalSliceArg.isSet() || saggitalSliceArg.isSet())
225 if(!imageArg.isSet())
227 cerr <<
"Error in arguments! View/Slice arguments need to be used with the image argument." << endl;
231 if(isoValueArg.isSet())
235 cerr <<
"Error in arguments! Isovalue argument needs to be used with the isosurface argument." << endl;
242 QScopedPointer<milxQtFile> reader(
new milxQtFile);
243 bool errorReading =
false;
244 bool success =
false;
247 cout <<
">> Animate: Reading Models" << endl;
248 vtkSmartPointer<vtkPolyDataCollection> collection;
252 cerr <<
"Error reading models!" << endl;
257 vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
258 transform->Identity();
259 transform->PostMultiply();
260 if(transformArg.isSet())
263 transform->Concatenate(matrix);
264 if(inverseArg.isSet())
265 transform->Inverse();
269 vtkSmartPointer<vtkPolyDataCollection> updatedCollection = vtkSmartPointer<vtkPolyDataCollection>::New();
270 const size_t n = collection->GetNumberOfItems();
271 if(!framesArg.isSet())
276 cerr <<
"At least one model must be provided!" << endl;
280 vtkSmartPointer<vtkLookupTable> lookupTable = vtkSmartPointer<vtkLookupTable>::New();
281 if(autoColourArg.isSet())
283 lookupTable->SetTableRange(0.0, n+1);
284 lookupTable->Build();
289 collection->InitTraversal();
290 for(
size_t j = 0; j < n; j ++)
295 mdl->setName(filenames[j].c_str());
296 mdl->SetInput(collection->GetNextItem());
298 if(removeScalarsArg.isSet() && mdl->GetScalars())
299 mdl->RemoveScalars();
300 if(loadScalarsArg.isSet())
301 mdl->loadScalars(loadScalarsName.c_str());
303 mdl->generateModel();
306 if(autoColourArg.isSet() && j > 0)
309 lookupTable->GetColor(j, colour);
310 mdl->changeColour(colour[0], colour[1], colour[2]);
312 if(setScalarsArg.isSet())
313 mdl->showArray(arrayName.c_str());
316 if(mdl->GetScalars())
318 mdl->GetScalarRange(range);
323 mdl->SetScalarRange(range);
326 if( opacityArg.isSet() && (!autoColourArg.isSet() || j == 0) )
327 mdl->SetOpacity(opacity);
328 if(vectorsArg.isSet())
329 mdl->generateVectorField();
331 updatedCollection->AddItem(mdl->GetOutput());
332 files.append(filenames[j].c_str());
334 std::cerr <<
"Done" << std::endl;
338 model->SetInputCollection(updatedCollection, files, index);
339 if(!model->isLoaded())
341 cerr <<
"Error reading models into animation! Check frameindex or filenames provided." << endl;
344 mainWindow.setCentralWidget(model.data());
347 QScopedPointer<milxQtModel> modelIso(
new milxQtModel);
348 QScopedPointer<milxQtImage> imgIso(
new milxQtImage);
351 cout <<
">> Animate: Applying Isosurface" << endl;
352 success = reader->openImage(isoName.c_str(), imgIso.data());
353 imgIso->setName(isoName.c_str());
354 imgIso->generateImage();
355 imgIso->threshold(0, isoValue-1.0, isoValue);
361 modelIso->generateIsoSurface(imgIso->GetOutput(), 0, isoValue-1.0);
362 modelIso->generateModel();
363 modelIso->changeColour(0,1,0);
370 cerr <<
"Error Reading one or more of the input files. Exiting." << endl;
376 QScopedPointer<milxQtImage> imgCoronal(
new milxQtImage);
377 QScopedPointer<milxQtImage> imgSagittal(
new milxQtImage);
378 vtkSmartPointer<vtkMatrix4x4> orientTransform = vtkSmartPointer<vtkMatrix4x4>::New();
381 vtkSmartPointer<vtkTransform> transform2 = vtkSmartPointer<vtkTransform>::New();
382 transform2->Identity();
383 transform2->PostMultiply();
386 cout <<
">> Animate: Reading Image" << endl;
387 errorReading =
false;
388 success = reader->openImage(imageName.c_str(), img.data());
395 img->setName(imageName.c_str());
396 img->generateImage();
397 if(axialSliceArg.isSet())
398 img->setSlice(axialSliceNumber);
406 #ifdef ITK_REVIEW //Review only members 409 img->overlayContour(labelName.c_str());
418 imgCoronal->SetInput(img->GetRGBImage());
419 imgSagittal->SetInput(img->GetRGBImage());
423 imgCoronal->SetInput(img->GetFloatImage());
424 imgSagittal->SetInput(img->GetFloatImage());
430 if(!nocoronalArg.isSet())
432 imgCoronal->setName(imageName.c_str());
433 imgCoronal->generateImage();
434 imgCoronal->viewToCoronal();
435 if(coronalSliceArg.isSet())
436 imgCoronal->setSlice(coronalSliceNumber);
440 if(!nosaggitalArg.isSet())
442 imgSagittal->setName(imageName.c_str());
443 imgSagittal->generateImage();
444 imgSagittal->viewToSagittal();
445 if(saggitalSliceArg.isSet())
446 imgSagittal->setSlice(saggitalSliceNumber);
454 cerr <<
"Error Reading the image file. Exiting." << endl;
460 orientTransform->DeepCopy(img->getTransformMatrix());
461 orientTransform->Invert();
462 transform2->Concatenate(orientTransform);
464 cout <<
">> Animate: Transforming Actors" << endl;
468 model->setWindowTitle(
"MILX-Animate");
469 model->SetSize(windowHeight, windowWidth);
470 mainWindow.resize(windowWidth, windowHeight);
473 if(imageArg.isSet() && !slicesArg.isSet())
475 if(!noaxialArg.isSet())
476 model->addImageActor(img->GetImageActor(), transform2->GetMatrix());
477 if(!nocoronalArg.isSet())
478 model->addImageActor(imgCoronal->GetImageActor(), transform2->GetMatrix());
479 if(!nosaggitalArg.isSet())
480 model->addImageActor(imgSagittal->GetImageActor(), transform2->GetMatrix());
484 QObject::connect(img.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
485 QObject::connect(imgCoronal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
486 QObject::connect(imgSagittal.data(), SIGNAL(modified(vtkSmartPointer<vtkImageActor> )), model.data(), SLOT(updateImageActor(vtkSmartPointer<vtkImageActor>)));
490 cout <<
">>> Overlay: Setting Colourmap" << endl;
492 model->colourMapToJet();
494 model->colourMapToVTK();
496 model->colourMapToHSV();
497 if(rainbowArg.isSet())
498 model->colourMapToRainbow();
499 if(spectralArg.isSet())
500 model->colourMapToSpectral();
502 model->colourMapToNIH();
504 model->colourMapToNIH_Fire();
506 model->colourMapToAAL();
508 model->colourMapToFS();
510 model->colourMapToHOT();
512 model->colourMapToCOOL();
513 if(minArg.isSet() || maxArg.isSet())
514 model->SetScalarRange(range);
515 if(scalarBarArg.isSet())
517 if(minArg.isSet() || maxArg.isSet())
518 model->enableScale(barName.c_str(),
true, range[0], range[1]);
520 model->enableScale(barName.c_str(),
true);
524 model->AddActor(modelIso->GetActor());
526 model->background(
true);
527 if(outlineArg.isSet())
530 model->enableOutline(img->GetOutput());
532 model->enableOutline();
536 double backgroundColours[3];
537 model->GetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
539 model->disableOrient();
541 backgroundColours[0] = redValue;
543 backgroundColours[1] = greenValue;
545 backgroundColours[2] = blueValue;
546 if(redArg.isSet() || blueArg.isSet() || greenArg.isSet())
547 model->SetBackground(backgroundColours[0], backgroundColours[1], backgroundColours[2]);
550 if(transformArg.isSet())
551 model->SetTransform(transform);
553 model->viewToAxial();
554 if(coronalArg.isSet())
555 model->viewToCoronal();
556 if(saggitalArg.isSet())
557 model->viewToSagittal();
558 if(loadViewArg.isSet())
560 if(loadViewFileArg.isSet())
561 model->loadView(loadViewName.c_str());
562 if(wireframesArg.isSet())
563 model->generateWireframe();
567 vtkCamera *camera = model->GetRenderer()->GetActiveCamera();
568 camera->Zoom(zoomFactor);
571 cout <<
">> Animate: Rendering" << endl;
572 if(!onscreenArg.isSet())
573 model->OffScreenRenderingOn();
578 model->movie(movieName.c_str(), frames);
579 cout <<
">> Complete" << endl;
581 model->OffScreenRenderingOff();
583 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.