#include "metaCommand.h"
#include <iostream>
#include <fstream>
#include <sstream>
#define ITK_TEST_DIMENSION_MAX 6
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 )
{
bestBaselineStatus =
testImageFilename.c_str(), 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() )
{
const int currentStatus =
testImageFilename.c_str(), baselineImageItr->c_str(),
0, false, toleranceIntensity, toleranceRadius,
toleranceNumberOfPixels);
if(currentStatus < bestBaselineStatus)
{
bestBaselineStatus = currentStatus;
bestBaselineFilename = *baselineImageItr;
}
if(bestBaselineStatus == 0)
{
break;
}
++baselineImageItr;
}
}
if(bestBaselineStatus == 0)
{
testImageFilename.c_str(),
bestBaselineFilename.c_str(), 1, false,
toleranceIntensity,toleranceRadius,toleranceNumberOfPixels);
}
else
{
testImageFilename.c_str(),
bestBaselineFilename.c_str(), 1, true,
toleranceIntensity,toleranceRadius,toleranceNumberOfPixels);
}
}
{
std::cerr << "ITK test driver caught an ITK exception:\n";
std::cerr << e << "\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;
}
const char *baselineImageFilename,
int reportErrors,
bool createDifferenceImage,
double intensityTolerance,
int radiusTolerance,
int numberOfPixelsTolerance)
{
ReaderType::Pointer baselineReader = ReaderType::New();
baselineReader->SetFileName(baselineImageFilename);
try
{
baselineReader->UpdateLargestPossibleRegion();
}
{
std::cerr << "Exception detected while reading "
<< baselineImageFilename <<
" : " <<
e;
return 1000;
}
ReaderType::Pointer testReader = ReaderType::New();
testReader->SetFileName(testImageFilename);
try
{
testReader->UpdateLargestPossibleRegion();
}
{
std::cerr << "Exception detected while reading "
<< testImageFilename << " : " << e << std::endl;
return 1000;
}
ImageType::Pointer baseline = baselineReader->GetOutput();
baselineSize = baseline->GetLargestPossibleRegion().
GetSize();
ImageType::Pointer
test = testReader->GetOutput();
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;
}
DiffType::Pointer diff = DiffType::New();
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)
{
RescaleType::Pointer rescale = RescaleType::New();
const unsigned char nonPositiveMin =
itk::NumericTraits<unsigned char>::NonpositiveMin();
rescale->SetOutputMinimum(nonPositiveMin);
const unsigned char unsignedCharMax =
itk::NumericTraits<unsigned char>::max();
rescale->SetOutputMaximum(unsignedCharMax);
rescale->SetInput(diff->GetOutput());
rescale->UpdateLargestPossibleRegion();
size = rescale->GetOutput()->GetLargestPossibleRegion().GetSize();
{
size[i] = 0;
}
region.SetSize(size);
ExtractType::Pointer extract = ExtractType::New();
extract->SetDirectionCollapseToSubmatrix();
extract->SetInput(rescale->GetOutput());
extract->SetExtractionRegion(region);
WriterType::Pointer writer = WriterType::New();
writer->SetInput(extract->GetOutput());
if(createDifferenceImage)
{
std::cout
<< "<DartMeasurement name=\"ImageError\" type=\"numeric/double\">"
<< averageIntensityDifference
<< "</DartMeasurement>" << std::endl
<< "<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
<< "<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
<< "<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 << "<DartMeasurementFile name=\"TestImage\" type=\"image/png\">";
std::cout << testName.str();
std::cout << "</DartMeasurementFile>" << std::endl;
}
return differenceFailed;
}