PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
CompareVolumes.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5 =========================================================Plus=header=end*/
6 
11 #include "PlusConfigure.h"
12 #include "vtksys/CommandLineArguments.hxx"
13 
14 #include <fstream>
15 #include <iostream>
16 #include <time.h>
17 
18 #include "vtkDataSetReader.h"
19 #include "vtkDataSetWriter.h"
20 #include "vtkImageClip.h"
21 #include "vtkImageData.h"
22 #include "vtkImageMathematics.h"
23 #include "vtkImageHistogramStatistics.h"
24 #include "vtkMetaImageReader.h"
25 
26 #include "vtkPlusCompareVolumes.h"
27 
28 //-----------------------------------------------------------------------------
29 int SimpleCompareVolumes( vtkImageData* testVol, vtkImageData* refVol, double simpleCompareMaxError )
30 {
31  if ( testVol == NULL )
32  {
33  LOG_ERROR( "Test volume is invalid" );
34  return EXIT_FAILURE;
35  }
36  if ( refVol == NULL )
37  {
38  LOG_ERROR( "Reference volume is invalid" );
39  return EXIT_FAILURE;
40  }
41 
42  int* testExt = testVol->GetExtent();
43  int* refExt = refVol->GetExtent();
44  if ( testExt[0] != refExt[0] || testExt[1] != refExt[1]
45  || testExt[2] != refExt[2] || testExt[3] != refExt[3]
46  || testExt[4] != refExt[4] || testExt[5] != refExt[5] )
47  {
48  LOG_ERROR( "Test volume extents (" << testExt[0] << ", " << testExt[1] << ", " << testExt[2] << ", " << testExt[3] << ", " << testExt[4] << ", " << testExt[5] << ")" \
49  << " do not match reference volume extents (" << refExt[0] << ", " << refExt[1] << ", " << refExt[2] << ", " << refExt[3] << ", " << refExt[4] << ", " << refExt[5] << ")" )
50  return EXIT_FAILURE;
51  }
52 
53  double* testSpacing = testVol->GetSpacing();
54  double* refSpacing = refVol->GetSpacing();
55  if ( testSpacing[0] != refSpacing[0] || testSpacing[1] != refSpacing[1] || testSpacing[2] != refSpacing[2] )
56  {
57  LOG_ERROR( "Test volume spacing (" << testSpacing[0] << ", " << testSpacing[1] << ", " << testSpacing[2] << ")" \
58  << " does not match reference volume spacing (" << refSpacing[0] << ", " << refSpacing[1] << ", " << refSpacing[2] << ")" )
59  return EXIT_FAILURE;
60  }
61 
62  double* testOrigin = testVol->GetOrigin();
63  double* refOrigin = refVol->GetOrigin();
64  if ( testOrigin[0] != refOrigin[0] || testOrigin[1] != refOrigin[1] || testOrigin[2] != refOrigin[2] )
65  {
66  LOG_ERROR( "Test volume origin (" << testOrigin[0] << ", " << testOrigin[1] << ", " << testOrigin[2] << ")" \
67  << " does not match reference volume origin (" << refOrigin[0] << ", " << refOrigin[1] << ", " << refOrigin[2] << ")" )
68  return EXIT_FAILURE;
69  }
70 
71  vtkSmartPointer<vtkImageMathematics> imageDiff = vtkSmartPointer<vtkImageMathematics>::New();
72  imageDiff->SetOperationToSubtract();
73  imageDiff->SetInputData( 0, testVol );
74  imageDiff->SetInputData( 1, refVol );
75 
76  vtkSmartPointer<vtkImageMathematics> imageAbsDiff = vtkSmartPointer<vtkImageMathematics>::New();
77  imageAbsDiff->SetOperationToAbsoluteValue();
78  imageAbsDiff->SetInputConnection( imageDiff->GetOutputPort() );
79 
80  vtkSmartPointer<vtkImageHistogramStatistics> statistics = vtkSmartPointer<vtkImageHistogramStatistics>::New();
81  statistics->SetInputConnection( imageAbsDiff->GetOutputPort() );
82  statistics->GenerateHistogramImageOff();
83  statistics->Update();
84 
85  double maxVal = statistics->GetMaximum();
86  double meanVal = statistics->GetMean();
87  double stdev = statistics->GetStandardDeviation();
88 
89  LOG_INFO( "Absolute difference between pixels: max=" << maxVal << ", mean=" << meanVal << ", stdev=" << stdev );
90  if ( stdev > simpleCompareMaxError )
91  {
92  LOG_ERROR( "Standard deviation of the absolute difference between the images (" << stdev << ") is larger than the maximum allowed image difference (" << simpleCompareMaxError << ")" );
93  return EXIT_FAILURE;
94  }
95 
96  LOG_INFO( "Standard deviation of the absolute difference between the images (" << stdev << ") is smaller than the maximum allowed image difference (" << simpleCompareMaxError << ")" );
97 
98  return EXIT_SUCCESS;
99 }
100 
101 
102 
103 int main( int argc, char** argv )
104 {
105  bool printHelp( false );
106  std::string inputGTFileName;
107  std::string inputGTAlphaFileName;
108  std::string inputTestingFileName;
109  std::string inputTestingAlphaFileName;
110  std::string inputSliceAlphaFileName;
111  std::string outputStatsFileName;
112  std::string outputTrueDiffFileName;
113  std::string outputAbsoluteDiffFileName;
114  std::vector<int> roiOriginV;
115  std::vector<int> roiSizeV;
116  double simpleCompareMaxError = -1;
117 
118  int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
119 
120  vtksys::CommandLineArguments args;
121  args.Initialize( argc, argv );
122 
123  args.AddArgument( "--ground-truth-image", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputGTFileName, "The ground truth volume being compared against" );
124  args.AddArgument( "--ground-truth-alpha", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputGTAlphaFileName, "The ground truth volume's alpha component" );
125  args.AddArgument( "--testing-image", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTestingFileName, "The testing image to compare to the ground truth" );
126  args.AddArgument( "--testing-alpha", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputTestingAlphaFileName, "The testing volume's alpha component" );
127  args.AddArgument( "--slices-alpha", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputSliceAlphaFileName, "The alpha component for when the slices are pasted into the volume, without hole filling" );
128  args.AddArgument( "--roi-origin", vtksys::CommandLineArguments::MULTI_ARGUMENT, &roiOriginV, "The three x y z values describing the origin for the region of interest's extent, in volume IJK coordinates" );
129  args.AddArgument( "--roi-size", vtksys::CommandLineArguments::MULTI_ARGUMENT, &roiSizeV, "The three x y z values describing the size for the region of interest's extent, in volume IJK coordinates" );
130  args.AddArgument( "--output-stats-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputStatsFileName, "The file to dump the statistics for the comparison" );
131  args.AddArgument( "--output-diff-volume-true", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputTrueDiffFileName, "Save the true difference volume to this file" );
132  args.AddArgument( "--output-diff-volume-absolute", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputAbsoluteDiffFileName, "Save the absolute difference volume to this file" );
133  args.AddArgument( "--simple-compare-max-error", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &simpleCompareMaxError, "If specified, a simple comparison of the volumes is performed (no detailed statistics are computed, only the ground truth and test volumes are used) and if the stdev of pixel values of the absolute difference image is larger than the specified value then the test returns with failure" );
134  args.AddArgument( "--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)" );
135  args.AddArgument( "--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp, "Print this help." );
136 
137  if ( !args.Parse() )
138  {
139  std::cerr << "Problem parsing arguments" << std::endl;
140  std::cout << "Help: " << args.GetHelp() << std::endl;
141  exit( EXIT_FAILURE );
142  }
143 
144  if ( printHelp )
145  {
146  std::cout << args.GetHelp() << std::endl;
147  exit( EXIT_SUCCESS );
148  }
149 
150  vtkPlusLogger::Instance()->SetLogLevel( verboseLevel );
151 
152  /************************************************************/
153 
154  // Check file names
155  if ( inputGTFileName.empty() || inputTestingFileName.empty() )
156  {
157  LOG_ERROR( "ground-truth-image and testing-image are required arguments" );
158  LOG_ERROR( "Help: " << args.GetHelp() );
159  exit( EXIT_FAILURE );
160  }
161 
162  // read in the volumes
163 
164  LOG_INFO( "Reading input ground truth image: " << inputGTFileName );
165  vtkSmartPointer<vtkMetaImageReader> reader = vtkSmartPointer<vtkMetaImageReader>::New();
166  reader->SetFileName( inputGTFileName.c_str() );
167  reader->Update();
168  vtkImageData* groundTruth = vtkImageData::SafeDownCast( reader->GetOutput() );
169 
170  LOG_INFO( "Reading input testing image: " << inputTestingFileName );
171  vtkSmartPointer<vtkMetaImageReader> reader3 = vtkSmartPointer<vtkMetaImageReader>::New();
172  reader3->SetFileName( inputTestingFileName.c_str() );
173  reader3->Update();
174  vtkImageData* testingImage = vtkImageData::SafeDownCast( reader3->GetOutput() );
175 
176  /************************************************************/
177  // Simple volume comparison
178 
179  if ( simpleCompareMaxError >= 0 )
180  {
181  LOG_INFO( "Perform simple volume comparison" );
182  return SimpleCompareVolumes( testingImage, groundTruth, simpleCompareMaxError );
183  }
184 
185  /************************************************************/
186  // Full volume comparison, with detailed statistic
187 
188 
189  // record the start time for data recording, see http://www.cplusplus.com/reference/clibrary/ctime/localtime/
190  time_t rawtime;
191  struct tm* timeInfo;
192  time( &rawtime );
193  timeInfo = localtime( &rawtime );
194  char timeAndDate[60];
195  strftime( timeAndDate, 60, "%Y %m %d %H:%M", timeInfo );
196 
197  // Check file names
198  if ( inputGTAlphaFileName.empty() || inputTestingAlphaFileName.empty() || inputSliceAlphaFileName.empty() || outputStatsFileName.empty() )
199  {
200  LOG_ERROR( "ground-truth-image, ground-truth-alpha, testing-image, testing-alpha, slices-alpha, and output-stats-file are required arguments!" );
201  LOG_ERROR( "Help: " << args.GetHelp() );
202  exit( EXIT_FAILURE );
203  }
204 
205  // read in the additional volumes
206 
207  LOG_INFO( "Reading input ground truth alpha: " << inputGTAlphaFileName );
208  vtkSmartPointer<vtkMetaImageReader> reader2 = vtkSmartPointer<vtkMetaImageReader>::New();
209  reader2->SetFileName( inputGTAlphaFileName.c_str() );
210  reader2->Update();
211  vtkImageData* groundTruthAlpha = vtkImageData::SafeDownCast( reader2->GetOutput() );
212 
213  LOG_INFO( "Reading input testing alpha: " << inputTestingAlphaFileName );
214  vtkSmartPointer<vtkMetaImageReader> reader4 = vtkSmartPointer<vtkMetaImageReader>::New();
215  reader4->SetFileName( inputTestingAlphaFileName.c_str() );
216  reader4->Update();
217  vtkImageData* testingAlpha = vtkImageData::SafeDownCast( reader4->GetOutput() );
218 
219  LOG_INFO( "Reading input slices alpha: " << inputSliceAlphaFileName );
220  vtkSmartPointer<vtkMetaImageReader> reader5 = vtkSmartPointer<vtkMetaImageReader>::New();
221  reader5->SetFileName( inputSliceAlphaFileName.c_str() );
222  reader5->Update();
223  vtkImageData* slicesAlpha = vtkImageData::SafeDownCast( reader5->GetOutput() );
224 
225  // check to make sure extents match
226  int* extentGT = groundTruth->GetExtent();
227  int* extentGTAlpha = groundTruthAlpha->GetExtent();
228  int* extentTestAlpha = testingAlpha->GetExtent();
229  int* extentSlicesAlpha = slicesAlpha->GetExtent();
230  bool match( true );
231  for ( int i = 0; i < 6; i++ )
232  if ( extentGT[i] != extentGTAlpha[i] || extentGT[i] != extentSlicesAlpha[i] || extentGT[i] != extentTestAlpha[i] || extentGT[i] != extentSlicesAlpha[i] )
233  { match = false; }
234  if ( !match )
235  {
236  LOG_ERROR( "Image sizes do not match!" );
237  exit( EXIT_FAILURE );
238  }
239 
240  // crop the image to the ROI
241 
242  vtkImageData* groundTruthRoi = groundTruth;
243  vtkImageData* groundTruthAlphaRoi = groundTruthAlpha;
244  vtkImageData* testingImageRoi = testingImage;
245  vtkImageData* testingAlphaRoi = testingAlpha;
246  vtkImageData* slicesAlphaRoi = slicesAlpha;
247  int roiExtent[6] = {0}; // array format of roi extent
248  for ( int extentIndex = 0; extentIndex < 6; extentIndex++ )
249  {
250  roiExtent[extentIndex] = extentGT[extentIndex];
251  }
252 
253  // Create the clippers here to be able use their outputs throughout this method
254  vtkSmartPointer<vtkImageClip> clipGT = vtkSmartPointer<vtkImageClip>::New();
255  vtkSmartPointer<vtkImageClip> clipGTAlpha = vtkSmartPointer<vtkImageClip>::New();
256  vtkSmartPointer<vtkImageClip> clipTest = vtkSmartPointer<vtkImageClip>::New();
257  vtkSmartPointer<vtkImageClip> clipTestAlpha = vtkSmartPointer<vtkImageClip>::New();
258  vtkSmartPointer<vtkImageClip> clipSlicesAlpha = vtkSmartPointer<vtkImageClip>::New();
259 
260  if ( roiOriginV.size() == 3 && roiSizeV.size() == 3 )
261  {
262  // Clip volumes to a ROI
263 
264  roiExtent[0] = roiOriginV[0];
265  roiExtent[1] = roiOriginV[0] + roiSizeV[0] - 1;
266  roiExtent[2] = roiOriginV[1];
267  roiExtent[3] = roiOriginV[1] + roiSizeV[1] - 1;
268  roiExtent[4] = roiOriginV[2];
269  roiExtent[5] = roiOriginV[2] + roiSizeV[2] - 1;
270 
271  // check new extents
272  if ( roiExtent[0] < extentGT[0] || roiExtent[1] >= extentGT[1] ||
273  roiExtent[2] < extentGT[2] || roiExtent[3] >= extentGT[3] ||
274  roiExtent[4] < extentGT[4] || roiExtent[5] >= extentGT[5] )
275  {
276  LOG_ERROR( "Region of interest contains data outside the original volume's IJK coordinates! Extents are: " << roiExtent[0] << " " << roiExtent[1] << " " << roiExtent[2] << " " << roiExtent[3] << " " << roiExtent[4] << " " << roiExtent[5] << "\n" << "Original extent is: " << extentGT[0] << " " << extentGT[1] << " " << extentGT[2] << " " << extentGT[3] << " " << extentGT[4] << " " << extentGT[5] );
277  exit( EXIT_FAILURE );
278  }
279 
280  clipGT->SetInputData( groundTruth );
281  clipGT->SetClipData( 1 );
282  clipGT->SetOutputWholeExtent( roiExtent );
283  clipGT->Update();
284  groundTruthRoi = clipGT->GetOutput();
285 
286  clipGTAlpha->SetInputData( groundTruthAlpha );
287  clipGTAlpha->SetClipData( 1 );
288  clipGTAlpha->SetOutputWholeExtent( roiExtent );
289  clipGTAlpha->Update();
290  groundTruthAlphaRoi = clipGTAlpha->GetOutput();
291 
292  clipTest->SetInputData( testingImage );
293  clipTest->SetClipData( 1 );
294  clipTest->SetOutputWholeExtent( roiExtent );
295  clipTest->Update();
296  testingImageRoi = clipTest->GetOutput();
297 
298  clipTestAlpha->SetInputData( testingAlpha );
299  clipTestAlpha->SetClipData( 1 );
300  clipTestAlpha->SetOutputWholeExtent( roiExtent );
301  clipTestAlpha->Update();
302  testingAlphaRoi = clipTestAlpha->GetOutput();
303 
304  clipSlicesAlpha->SetInputData( slicesAlpha );
305  clipSlicesAlpha->SetClipData( 1 );
306  clipSlicesAlpha->SetOutputWholeExtent( roiExtent );
307  clipSlicesAlpha->Update();
308  slicesAlphaRoi = clipSlicesAlpha->GetOutput();
309  }
310  else if ( roiOriginV.size() != 0 || roiSizeV.size() != 0 )
311  {
312  LOG_ERROR( "ROI size and origin each need to be 3 values in volume IJK coordinates: X Y Z" );
313  exit( EXIT_FAILURE );
314  }
315 
316  // calculate the histogram for the difference image
317  LOG_INFO( "Calculating difference images and statistics..." );
318  vtkSmartPointer<vtkPlusCompareVolumes> histogramGenerator = vtkSmartPointer<vtkPlusCompareVolumes>::New();
319  histogramGenerator->SetInputGT( groundTruthRoi );
320  histogramGenerator->SetInputGTAlpha( groundTruthAlphaRoi );
321  histogramGenerator->SetInputTest( testingImageRoi );
322  histogramGenerator->SetInputTestAlpha( testingAlphaRoi );
323  histogramGenerator->SetInputSliceAlpha( slicesAlphaRoi );
324  histogramGenerator->Update();
325 
326  // write data to a CSV
327  if ( !outputStatsFileName.empty() )
328  {
329  LOG_INFO( "Writing output statistics: " << outputStatsFileName );
330  int* TruHistogram = histogramGenerator->GetTrueHistogramPtr();
331  int* AbsHistogram = histogramGenerator->GetAbsoluteHistogramPtr();
332  int* AbsHistogramWithHoles = histogramGenerator->GetAbsoluteHistogramWithHolesPtr();
333  std::ifstream testingFile( outputStatsFileName.c_str() );
334  std::ofstream outputStatsFile; // for use once we establish whether or not the file exists
335  if ( testingFile.is_open() )
336  {
337  // if the file exists already, just output what we want
338  testingFile.close(); // no reading, must open for writing now
339  outputStatsFile.open( outputStatsFileName.c_str(), std::ios::out | std::ios::app );
340  outputStatsFile << timeAndDate << ","
341  << inputGTFileName << ","
342  << inputGTAlphaFileName << ","
343  << inputSliceAlphaFileName << ","
344  << inputTestingFileName << ","
345  << inputTestingAlphaFileName << ","
346  << roiExtent[0] << "_" << roiExtent[1] << "_" << roiExtent[2] << "_" << roiExtent[3] << "_" << roiExtent[4] << "_" << roiExtent[5] << ","
347  << histogramGenerator->GetNumberOfHoles() << ","
348  << histogramGenerator->GetNumberOfFilledHoles() << ","
349  << histogramGenerator->GetNumberVoxelsVisible() << ","
350  << histogramGenerator->GetTrueMaximum() << ","
351  << histogramGenerator->GetTrueMinimum() << ","
352  << histogramGenerator->GetTrueMedian() << ","
353  << histogramGenerator->GetTrueMean() << ","
354  << histogramGenerator->GetTrueStdev() << ","
355  << histogramGenerator->GetTrue5thPercentile() << ","
356  << histogramGenerator->GetTrue95thPercentile() << ","
357  << histogramGenerator->GetAbsoluteMaximum() << ","
358  << histogramGenerator->GetAbsoluteMinimum() << ","
359  << histogramGenerator->GetAbsoluteMedian() << ","
360  << histogramGenerator->GetAbsoluteMean() << ","
361  << histogramGenerator->GetAbsoluteStdev() << ","
362  << histogramGenerator->GetAbsolute5thPercentile() << ","
363  << histogramGenerator->GetAbsolute95thPercentile() << ","
364  << histogramGenerator->GetRMS() << ","
365  << histogramGenerator->GetAbsoluteMeanWithHoles();
366  for ( int i = 0; i < 511; i++ )
367  { outputStatsFile << "," << TruHistogram[i]; }
368  for ( int i = 0; i < 256; i++ )
369  { outputStatsFile << "," << AbsHistogram[i]; }
370  for ( int i = 0; i < 256; i++ )
371  { outputStatsFile << "," << AbsHistogramWithHoles[i]; }
372  outputStatsFile << std::endl;
373  }
374  else
375  {
376  // need to create the file and write to it. First give it a header row.
377  testingFile.close(); // no reading, must open for writing now
378  outputStatsFile.open( outputStatsFileName.c_str() );
379  outputStatsFile << "Time,Dataset - Ground Truth,Dataset - Ground Truth Alpha,Dataset - Slices Alpha,Dataset - Testing Image,Dataset - Testing Alpha,Region of Interest Extent,Number of Holes,Number of Filled Holes,Number of Visible Voxels,True Maximum Error,True Minimum Error,True Median Error,True Mean Error,True Standard Deviation,True 5th Percentile,True 95th Percentile,Absolute Maximum Error,Absolute Minimum Error,Absolute Median Error,Absolute Mean Error,Absolute Standard Deviation,Absolute 5th Percentile,Absolute 95th Percentile,RMS,Absolute Mean Error Including Holes";
380  for ( int i = 0; i < 511; i++ )
381  {
382  outputStatsFile << "," << ( i - 255 );
383  }
384  for ( int i = 0; i < 256; i++ )
385  {
386  outputStatsFile << "," << i;
387  }
388  for ( int i = 0; i < 256; i++ )
389  {
390  outputStatsFile << "," << i;
391  }
392  outputStatsFile << std::endl;
393  outputStatsFile << timeAndDate << ","
394  << inputGTFileName << ","
395  << inputGTAlphaFileName << ","
396  << inputSliceAlphaFileName << ","
397  << inputTestingFileName << ","
398  << inputTestingAlphaFileName << ","
399  << roiExtent[0] << "_" << roiExtent[1] << "_" << roiExtent[2] << "_" << roiExtent[3] << "_" << roiExtent[4] << "_" << roiExtent[5] << ","
400  << histogramGenerator->GetNumberOfHoles() << ","
401  << histogramGenerator->GetNumberOfFilledHoles() << ","
402  << histogramGenerator->GetNumberVoxelsVisible() << ","
403  << histogramGenerator->GetTrueMaximum() << ","
404  << histogramGenerator->GetTrueMinimum() << ","
405  << histogramGenerator->GetTrueMedian() << ","
406  << histogramGenerator->GetTrueMean() << ","
407  << histogramGenerator->GetTrueStdev() << ","
408  << histogramGenerator->GetTrue5thPercentile() << ","
409  << histogramGenerator->GetTrue95thPercentile() << ","
410  << histogramGenerator->GetAbsoluteMaximum() << ","
411  << histogramGenerator->GetAbsoluteMinimum() << ","
412  << histogramGenerator->GetAbsoluteMedian() << ","
413  << histogramGenerator->GetAbsoluteMean() << ","
414  << histogramGenerator->GetAbsoluteStdev() << ","
415  << histogramGenerator->GetAbsolute5thPercentile() << ","
416  << histogramGenerator->GetAbsolute95thPercentile() << ","
417  << histogramGenerator->GetRMS() << ","
418  << histogramGenerator->GetAbsoluteMeanWithHoles();
419  for ( int i = 0; i < 511; i++ )
420  { outputStatsFile << "," << TruHistogram[i]; }
421  for ( int i = 0; i < 256; i++ )
422  { outputStatsFile << "," << AbsHistogram[i]; }
423  for ( int i = 0; i < 256; i++ )
424  { outputStatsFile << "," << AbsHistogramWithHoles[i]; }
425  outputStatsFile << std::endl;
426  }
427  }
428 
429  if ( !outputAbsoluteDiffFileName.empty() )
430  {
431  LOG_INFO( "Writing absolute difference image: " << outputAbsoluteDiffFileName );
432  vtkSmartPointer<vtkDataSetWriter> writerAbs = vtkSmartPointer<vtkDataSetWriter>::New();
433  writerAbs->SetFileTypeToBinary();
434  writerAbs->SetInputData( histogramGenerator->GetOutputAbsoluteDifferenceImage() );
435  writerAbs->SetFileName( outputAbsoluteDiffFileName.c_str() );
436  writerAbs->Update();
437  }
438 
439  if ( !outputTrueDiffFileName.empty() )
440  {
441  LOG_INFO( "Writing true difference image: " << outputTrueDiffFileName );
442  vtkSmartPointer<vtkDataSetWriter> writerTru = vtkSmartPointer<vtkDataSetWriter>::New();
443  writerTru->SetFileTypeToBinary();
444  writerTru->SetInputData( histogramGenerator->GetOutputTrueDifferenceImage() );
445  writerTru->SetFileName( outputTrueDiffFileName.c_str() );
446  writerTru->Update();
447  }
448 
449  return EXIT_SUCCESS;
450 }
for i
int main(int argc, char **argv)
PhidgetGPS_Time * time
Definition: phidget22.h:3623
static vtkIGSIOLogger * Instance()
int SimpleCompareVolumes(vtkImageData *testVol, vtkImageData *refVol, double simpleCompareMaxError)