#include "metaCommand.h"
#include <iostream>
#include <fstream>
#include <sstream>
#define ITK_TEST_DIMENSION_MAX 6
int
int
main(int argc, char ** argv)
{
MetaCommand command;
command.SetOption("toleranceIntensity", "i", false, "Acceptable differences in pixels intensity");
command.SetOptionLongTag("toleranceIntensity", "tolerance-intensity");
command.AddOptionField("toleranceIntensity", "value", MetaCommand::FLOAT, true);
command.SetOption("toleranceRadius", "r", false, "Neighbor pixels to look for similar values");
command.SetOptionLongTag("toleranceRadius", "tolerance-radius");
command.AddOptionField("toleranceRadius", "value", MetaCommand::INT, true);
command.SetOption(
"toleranceNumberOfPixels", "n", false, "Number of Pixels that are acceptable to have intensity differences");
command.SetOptionLongTag("toleranceNumberOfPixels", "tolerance-number-of-pixels");
command.AddOptionField("toleranceNumberOfPixels", "value", MetaCommand::INT, true);
command.SetOption("testImage", "t", true, "Filename of the image to be tested against the baseline images");
command.SetOptionLongTag("testImage", "test-image");
command.AddOptionField("testImage", "filename", MetaCommand::STRING, true);
command.SetOption("baselineImages", "s", false, "List of baseline images <N> <image1> <image2>...<imageN>");
command.SetOptionLongTag("baselineImages", "baseline-images");
command.AddOptionField("baselineImages", "filename", MetaCommand::LIST, true);
command.SetOption("baselineImage", "b", false, "Baseline images filename");
command.SetOptionLongTag("baselineImage", "baseline-image");
command.AddOptionField("baselineImage", "filename", MetaCommand::STRING, true);
command.SetParseFailureOnUnrecognizedOption(true);
if (!command.Parse(argc, argv))
{
std::cerr << "Error during " << argv[0] << " command argument parsing." << std::endl;
return EXIT_FAILURE;
}
double toleranceIntensity = 0.0;
unsigned int toleranceRadius = 0;
unsigned long toleranceNumberOfPixels = 0;
std::string testImageFilename;
std::string baselineImageFilename;
if (command.GetOptionWasSet("toleranceIntensity"))
{
toleranceIntensity = command.GetValueAsFloat("toleranceIntensity", "value");
}
if (command.GetOptionWasSet("toleranceRadius"))
{
toleranceRadius = command.GetValueAsInt("toleranceRadius", "value");
}
if (command.GetOptionWasSet("toleranceNumberOfPixels"))
{
toleranceNumberOfPixels = command.GetValueAsInt("toleranceNumberOfPixels", "value");
}
if (command.GetOptionWasSet("testImage"))
{
testImageFilename = command.GetValueAsString("testImage", "filename");
}
std::list<std::string> baselineImageFilenames;
baselineImageFilenames.clear();
bool singleBaselineImage = true;
if (!command.GetOptionWasSet("baselineImage") && !command.GetOptionWasSet("baselineImages"))
{
std::cerr << "You must provide a --baseline-image"
<< " or --baseline-images option." << std::endl;
return EXIT_FAILURE;
}
if (command.GetOptionWasSet("baselineImage"))
{
singleBaselineImage = true;
baselineImageFilename = command.GetValueAsString("baselineImage", "filename");
}
if (command.GetOptionWasSet("baselineImages"))
{
singleBaselineImage = false;
baselineImageFilenames = command.GetValueAsList("baselineImages");
}
std::string bestBaselineFilename;
int bestBaselineStatus = 2001;
try
{
if (singleBaselineImage)
{
baselineImageFilename.c_str(),
0,
false,
toleranceIntensity,
toleranceRadius,
toleranceNumberOfPixels);
bestBaselineFilename = baselineImageFilename;
}
else
{
using nameIterator = std::list<std::string>::const_iterator;
nameIterator baselineImageItr = baselineImageFilenames.begin();
while (baselineImageItr != baselineImageFilenames.end())
{
baselineImageItr->c_str(),
0,
false,
toleranceIntensity,
toleranceRadius,
toleranceNumberOfPixels);
if (currentStatus < bestBaselineStatus)
{
bestBaselineStatus = currentStatus;
bestBaselineFilename = *baselineImageItr;
}
if (bestBaselineStatus == 0)
{
break;
}
++baselineImageItr;
}
}
if (bestBaselineStatus == 0)
{
bestBaselineFilename.c_str(),
1,
false,
toleranceIntensity,
toleranceRadius,
toleranceNumberOfPixels);
}
else
{
bestBaselineFilename.c_str(),
1,
true,
toleranceIntensity,
toleranceRadius,
toleranceNumberOfPixels);
}
}
catch (
const itk::ExceptionObject &
e)
{
std::cerr << "ITK test driver caught an ITK exception:\n";
bestBaselineStatus = -1;
}
catch (
const std::exception &
e)
{
std::cerr << "ITK test driver caught an exception:\n";
std::cerr <<
e.what() <<
"\n";
bestBaselineStatus = -1;
}
catch (...)
{
std::cerr << "ITK test driver caught an unknown exception!!!\n";
bestBaselineStatus = -1;
}
std::cout << bestBaselineStatus << std::endl;
return bestBaselineStatus;
}
int
const char * baselineImageFilename,
int reportErrors,
bool createDifferenceImage,
double intensityTolerance,
int radiusTolerance,
int numberOfPixelsTolerance)
{
baselineReader->SetFileName(baselineImageFilename);
try
{
baselineReader->UpdateLargestPossibleRegion();
}
catch (
const itk::ExceptionObject &
e)
{
std::cerr <<
"Exception detected while reading " << baselineImageFilename <<
" : " <<
e;
return 1000;
}
testReader->SetFileName(testImageFilename);
try
{
testReader->UpdateLargestPossibleRegion();
}
catch (
const itk::ExceptionObject &
e)
{
std::cerr <<
"Exception detected while reading " << testImageFilename <<
" : " <<
e << std::endl;
return 1000;
}
baselineSize = baseline->GetLargestPossibleRegion().GetSize();
testSize =
test->GetLargestPossibleRegion().GetSize();
if (baselineSize != testSize)
{
std::cerr << "The size of the Baseline image and Test image do not match!" << std::endl
<< "Baseline image: " << baselineImageFilename << " has size " << baselineSize << std::endl
<< "Test image: " << testImageFilename << " has size " << testSize << std::endl;
return 1;
}
diff->SetValidInput(baselineReader->GetOutput());
diff->SetTestInput(testReader->GetOutput());
diff->SetDifferenceThreshold(intensityTolerance);
diff->SetToleranceRadius(radiusTolerance);
diff->UpdateLargestPossibleRegion();
bool differenceFailed = false;
const double averageIntensityDifference = diff->GetTotalDifference();
const unsigned long numberOfPixelsWithDifferences = diff->GetNumberOfPixelsWithDifferences();
if (averageIntensityDifference > 0.0)
{
if (static_cast<int>(numberOfPixelsWithDifferences) > numberOfPixelsTolerance)
{
differenceFailed = true;
}
else
{
differenceFailed = false;
}
}
else
{
differenceFailed = false;
}
if (reportErrors)
{
rescale->SetOutputMinimum(nonPositiveMin);
rescale->SetOutputMaximum(unsignedCharMax);
rescale->SetInput(diff->GetOutput());
rescale->UpdateLargestPossibleRegion();
size = rescale->GetOutput()->GetLargestPossibleRegion().GetSize();
{
size[i] = 0;
}
region.SetSize(size);
extract->SetDirectionCollapseToSubmatrix();
extract->SetInput(rescale->GetOutput());
extract->SetExtractionRegion(region);
writer->SetInput(extract->GetOutput());
if (createDifferenceImage)
{
std::cout << R"(<DartMeasurement name="ImageError" type="numeric/double">)" << averageIntensityDifference
<< "</DartMeasurement>" << std::endl
<< R"(<DartMeasurement name="NumberOfPixelsError" type="numeric/int">)" << numberOfPixelsWithDifferences
<< "</DartMeasurement>" << std::endl;
std::ostringstream diffName;
diffName << testImageFilename << ".diff.png";
try
{
rescale->SetInput(diff->GetOutput());
rescale->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during rescale of " << diffName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during rescale of " << diffName.str() << std::endl;
}
writer->SetFileName(diffName.str().c_str());
try
{
writer->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during write of " << diffName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during write of " << diffName.str() << std::endl;
}
std::cout << R"(<DartMeasurementFile name="DifferenceImage" type="image/png">)";
std::cout << diffName.str();
std::cout << "</DartMeasurementFile>" << std::endl;
}
std::ostringstream baseName;
baseName << testImageFilename << ".base.png";
try
{
rescale->SetInput(baselineReader->GetOutput());
rescale->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during rescale of " << baseName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during rescale of " << baseName.str() << std::endl;
}
try
{
writer->SetFileName(baseName.str().c_str());
writer->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during write of " << baseName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during write of " << baseName.str() << std::endl;
}
std::cout << R"(<DartMeasurementFile name="BaselineImage" type="image/png">)";
std::cout << baseName.str();
std::cout << "</DartMeasurementFile>" << std::endl;
std::ostringstream testName;
testName << testImageFilename << ".test.png";
try
{
rescale->SetInput(testReader->GetOutput());
rescale->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during rescale of " << testName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during rescale of " << testName.str() << std::endl;
}
try
{
writer->SetFileName(testName.str().c_str());
writer->Update();
}
catch (
const std::exception &
e)
{
std::cerr << "Error during write of " << testName.str() << std::endl;
std::cerr <<
e.what() <<
"\n";
}
catch (...)
{
std::cerr << "Error during write of " << testName.str() << std::endl;
}
std::cout << R"(<DartMeasurementFile name="TestImage" type="image/png">)";
std::cout << testName.str();
std::cout << "</DartMeasurementFile>" << std::endl;
}
return differenceFailed;
}