From 857f2c68803cfb804a01d3e17f423e6176eecee4 Mon Sep 17 00:00:00 2001 From: "nissim.hadar" Date: Thu, 23 Nov 2017 05:58:00 -0800 Subject: [PATCH] New image comparison method. --- tools/auto-tester/src/ITKImageComparer.cpp | 82 ++++------------------ tools/auto-tester/src/Test.cpp | 9 ++- tools/auto-tester/src/common.h | 2 +- 3 files changed, 20 insertions(+), 73 deletions(-) diff --git a/tools/auto-tester/src/ITKImageComparer.cpp b/tools/auto-tester/src/ITKImageComparer.cpp index e0ebcb8c16..ae00ecc098 100644 --- a/tools/auto-tester/src/ITKImageComparer.cpp +++ b/tools/auto-tester/src/ITKImageComparer.cpp @@ -10,13 +10,8 @@ #include "ITKImageComparer.h" -#include -#include #include -#include -#include -#include -#include +#include ITKImageComparer::ITKImageComparer() { // These are smart pointers that do not need to be deleted @@ -38,73 +33,20 @@ float ITKImageComparer::compareImages(QString resultImageFilename, QString expec resultImageToMonochrome->SetInput(resultImageReader->GetOutput()); expectedImageToMonochrome->SetInput(expectedImageReader->GetOutput()); + + using DiffType = itk::Testing::ComparisonImageFilter; + DiffType::Pointer diff = DiffType::New(); - // Setup registration components - // The transform that will map the fixed image space into the moving image space - using TransformType = itk::TranslationTransform; + diff->SetTestInput(resultImageToMonochrome->GetOutput()); + diff->SetValidInput(expectedImageToMonochrome->GetOutput()); - // The optimizer explores the parameter space of the transform in search of optimal values of the metric - using OptimizerType = itk::RegularStepGradientDescentOptimizerv4; + const double INTENSITY_TOLERANCE = 0.01; + diff->SetDifferenceThreshold(INTENSITY_TOLERANCE); - // The metric will compare how well the two images match each other - using MetricType = itk::MeanSquaresImageToImageMetricv4; + const double RADIUS_TOLERANCE = 2.0; + diff->SetToleranceRadius(RADIUS_TOLERANCE); - //The registration method type is instantiated using the types of the fixed and moving images as well - // as the output transform type.This class is responsible for interconnecting the components - using RegistrationType = itk::ImageRegistrationMethodv4; + diff->UpdateLargestPossibleRegion(); - // Create registration components (smart pointers, so no need to delete) - MetricType::Pointer metric = MetricType::New(); - OptimizerType::Pointer optimizer = OptimizerType::New(); - RegistrationType::Pointer registration = RegistrationType::New(); - - // The comparison metric needs an interpreter. - // The same interpolator is used for both images - using LinearInterpolatorType = itk::LinearInterpolateImageFunction; - LinearInterpolatorType::Pointer interpolator = LinearInterpolatorType::New(); - metric->SetFixedInterpolator(interpolator); - metric->SetMovingInterpolator(interpolator); - - // Connect components - registration->SetMetric(metric); - registration->SetOptimizer(optimizer); - registration->SetFixedImage(resultImageToMonochrome->GetOutput()); - registration->SetMovingImage(expectedImageToMonochrome->GetOutput()); - - // Initialization - TransformType::Pointer movingInitialTransform = TransformType::New(); - TransformType::ParametersType initialParameters(movingInitialTransform->GetNumberOfParameters()); - - initialParameters[0] = 0.0; // Initial offset in mm along X - initialParameters[1] = 0.0; // Initial offset in mm along Y - - movingInitialTransform->SetParameters(initialParameters); - registration->SetMovingInitialTransform(movingInitialTransform); - - // Set optimizer parameters - optimizer->SetLearningRate(4); - optimizer->SetMinimumStepLength(0.001); - optimizer->SetRelaxationFactor(0.5); - optimizer->SetNumberOfIterations(200); - - // Define registration criteria - const unsigned int numberOfLevels = 1; - RegistrationType::ShrinkFactorsArrayType shrinkFactorsPerLevel; - shrinkFactorsPerLevel.SetSize(1); - shrinkFactorsPerLevel[0] = 1; - RegistrationType::SmoothingSigmasArrayType smoothingSigmasPerLevel; - smoothingSigmasPerLevel.SetSize(1); - smoothingSigmasPerLevel[0] = 0; - registration->SetNumberOfLevels(numberOfLevels); - registration->SetSmoothingSigmasPerLevel(smoothingSigmasPerLevel); - registration->SetShrinkFactorsPerLevel(shrinkFactorsPerLevel); - - // Activate the registration project - try - { - registration->Update(); - return 0.0; - } catch (itk::ExceptionObject & err) { - return EXIT_FAILURE; - } + return (float)diff->GetNumberOfPixelsWithDifferences(); } diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 502cc29682..f4e31741de 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -62,7 +62,8 @@ void Test::evaluateTests() { messageBox.critical(0, "Test failed", "Found " + QString::number(resultImages.length()) + " images in directory" + - "\nExpected to find " + QString::number(expectedImages.length()) + " images"); + "\nExpected to find " + QString::number(expectedImages.length()) + " images" + ); exit(-1); } @@ -138,11 +139,13 @@ void Test::createRecursiveScript() { QFileInfo fileInfo(testPathname); if (fileInfo.exists()) { // Current folder contains a test - textStream << "Script.include(\"" << testPathname << "/" << " ? raw = true\")" << endl; + textStream << "Script.include(\"" << testPathname + "\")" << endl; } } allTestsFilename.close(); + + messageBox.information(0, "Success", "Script has been created"); } void Test::createTest() { @@ -166,6 +169,8 @@ void Test::createTest() { ++i; } } + + messageBox.information(0, "Success", "Test images have been created"); } void Test::createListOfAllJPEGimagesInDirectory() { diff --git a/tools/auto-tester/src/common.h b/tools/auto-tester/src/common.h index 079f1d3ebf..7e32c41052 100644 --- a/tools/auto-tester/src/common.h +++ b/tools/auto-tester/src/common.h @@ -21,7 +21,7 @@ public: _actualImageFilename = actualImageFilename; } - float _error; + double _error; QString _pathname; QString _expectedImageFilename; QString _actualImageFilename;