From aa07cab826526f7317dd547532a5c3ac5f5aca5d Mon Sep 17 00:00:00 2001 From: Aurelien Bricier <aurelien.bricier@c-s.fr> Date: Mon, 18 Oct 2010 17:11:24 +0200 Subject: [PATCH] TEST: added scale and rotation invariance tests --- Testing/Code/FeatureExtraction/CMakeLists.txt | 40 ++++ .../otbComplexMomentImage.cxx | 122 ++++++++++ .../otbFeatureExtractionTests1.cxx | 5 + .../FeatureExtraction/otbFlusserImage.cxx | 208 ++++++++++++++++- Testing/Code/FeatureExtraction/otbHuImage.cxx | 209 +++++++++++++++++- 5 files changed, 581 insertions(+), 3 deletions(-) diff --git a/Testing/Code/FeatureExtraction/CMakeLists.txt b/Testing/Code/FeatureExtraction/CMakeLists.txt index 4b7c189935..18e402a782 100644 --- a/Testing/Code/FeatureExtraction/CMakeLists.txt +++ b/Testing/Code/FeatureExtraction/CMakeLists.txt @@ -73,6 +73,16 @@ ADD_TEST(feTvComplexMomentImage ${FEATUREEXTRACTION_TESTS1} 4 ${TEMP}/feComplexMomentImage.txt) +ADD_TEST(feTvComplexMomentImageScaleInvariant ${FEATUREEXTRACTION_TESTS1} + --compare-ascii ${NOTOL} ${BASELINE_FILES}/feComplexMomentImageScaleInvariant.txt + ${TEMP}/feComplexMomentImageScaleInvariant.txt + otbComplexMomentImageScaleInvariant + ${INPUTDATA}/poupees.png + 4 + 4 + ${TEMP}/feComplexMomentImageScaleInvariant.txt + ${TEMP}/feComplexImageScaleInvariant.tiff) + ADD_TEST(feTvRealMomentImage ${FEATUREEXTRACTION_TESTS1} --compare-ascii ${NOTOL} ${BASELINE_FILES}/feRealMomentImage.txt ${TEMP}/feRealMomentImage.txt @@ -96,6 +106,21 @@ ADD_TEST(feTvHuImage ${FEATUREEXTRACTION_TESTS1} ${INPUTDATA}/poupees.png ${TEMP}/feHuImage.txt) +ADD_TEST(feTuHuImageScaleInvariant ${FEATUREEXTRACTION_TESTS1} + otbHuImageScaleInvariant + ${INPUTDATA}/poupees.png + ${TEMP}/feHuImageScaleInvariant.txt + ${TEMP}/feHuImageScaleInvariant.tiff + ) + +ADD_TEST(feTuHuImageRotationInvariant ${FEATUREEXTRACTION_TESTS1} + otbHuImageRotationInvariant + ${INPUTDATA}/poupees.png + ${TEMP}/feHuImageRotationInvariant.txt + ${TEMP}/feHuImageRotationInvariant.tiff + 90 + ) + ADD_TEST(feTuFlusserImage ${FEATUREEXTRACTION_TESTS1} --compare-ascii ${EPSILON_8} ${BASELINE_FILES}/feFlusserImage.txt ${TEMP}/feFlusserImage.txt @@ -103,6 +128,21 @@ ADD_TEST(feTuFlusserImage ${FEATUREEXTRACTION_TESTS1} ${INPUTDATA}/poupees.png ${TEMP}/feFlusserImage.txt) +ADD_TEST(feTuFlusserImageScaleInvariant ${FEATUREEXTRACTION_TESTS1} + otbFlusserImageScaleInvariant + ${INPUTDATA}/poupees.png + ${TEMP}/feFlusserImageScaleInvariant.txt + ${TEMP}/feFlusserImageScaleInvariant.tiff + ) + +ADD_TEST(feTuFlusserImageRotationInvariant ${FEATUREEXTRACTION_TESTS1} + otbFlusserImageRotationInvariant + ${INPUTDATA}/poupees.png + ${TEMP}/feFlusserImageRotationInvariant.txt + ${TEMP}/feFlusserImageRotationInvariant.tiff + 90 + ) + ADD_TEST(feTuComplexMomentPathNew ${FEATUREEXTRACTION_TESTS1} otbComplexMomentPathNew) diff --git a/Testing/Code/FeatureExtraction/otbComplexMomentImage.cxx b/Testing/Code/FeatureExtraction/otbComplexMomentImage.cxx index 4b1c5cc5c6..02add720eb 100644 --- a/Testing/Code/FeatureExtraction/otbComplexMomentImage.cxx +++ b/Testing/Code/FeatureExtraction/otbComplexMomentImage.cxx @@ -28,6 +28,11 @@ #include "otbImageFileReader.h" #include "otbComplexMomentImageFunction.h" +#include "otbBCOInterpolateImageFunction.h" +#include "itkLinearInterpolateImageFunction.h" +#include "otbStreamingResampleImageFilter.h" +#include "otbStreamingImageFileWriter.h" +#include "itkResampleImageFilter.h" int otbComplexMomentImage(int argc, char * argv[]) { @@ -78,3 +83,120 @@ int otbComplexMomentImage(int argc, char * argv[]) return EXIT_SUCCESS; } + + +int otbComplexMomentImageScaleInvariant(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + unsigned int p((unsigned int) ::atoi(argv[2])); + unsigned int q((unsigned int) ::atoi(argv[3])); + const char * outputFilename = argv[4]; + const char * outputImageName = argv[5]; + + typedef double InputPixelType; + const unsigned int Dimension = 2; + typedef otb::Image<InputPixelType, Dimension> InputImageType; + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::StreamingResampleImageFilter<InputImageType, + InputImageType, + double> StreamingResampleImageFilterType; + typedef otb::BCOInterpolateImageFunction<InputImageType, + double> InterpolatorType; + //typedef itk::LinearInterpolateImageFunction<InputImageType, + // double> InterpolatorType; + typedef otb::ComplexMomentImageFunction<InputImageType> FunctionType; + typedef FunctionType::ComplexType ComplexType; + typedef otb::StreamingImageFileWriter<InputImageType> WriterType; + + ReaderType::Pointer reader = ReaderType::New(); + StreamingResampleImageFilterType::Pointer resampler = StreamingResampleImageFilterType::New(); + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + FunctionType::Pointer function1 = FunctionType::New(); + FunctionType::Pointer function2 = FunctionType::New(); + WriterType::Pointer writer = WriterType::New(); + + reader->SetFileName(inputFilename); + reader->Update(); + + interpolator->SetInputImage(reader->GetOutput()); + interpolator->SetRadius(2); + interpolator->SetAlpha(-0.5); + + resampler->SetInput(reader->GetOutput()); + resampler->SetInterpolator(interpolator); + StreamingResampleImageFilterType::SizeType size; + size[0] = 1024; + size[1] = 1024; + resampler->SetOutputSize(size); + resampler->SetOutputSpacing(0.5); + resampler->Update(); + writer->SetInput(resampler->GetOutput()); + writer->SetFileName(outputImageName); + writer->Update(); + + function1->SetInputImage(reader->GetOutput()); + function1->SetQmax(q); + function1->SetPmax(p); + InputImageType::IndexType index1; + index1[0] = 100; + index1[1] = 100; + function1->SetNeighborhoodRadius(4); + ComplexType Result1 = function1->EvaluateAtIndex(index1); + + function2->SetInputImage(resampler->GetOutput()); + function2->SetQmax(q); + function2->SetPmax(p); + InputImageType::IndexType index2; + index2[0] = 200; + index2[1] = 200; + function2->SetNeighborhoodRadius(8); + ComplexType Result2 = function2->EvaluateAtIndex(index2); + + std::ofstream outputStream(outputFilename); + outputStream << std::setprecision(10); + + for (unsigned int k=0; k<=p; k++) + { + for (unsigned int l=0; l<=q; l++) + { + double error; + if ( (k+l) >= 2) + { + if (k == l) + { + error = 2*vcl_abs( Result1.at(k).at(l).real() - Result2.at(k).at(l).real()) + / vcl_abs(Result1.at(k).at(l).real() + Result2.at(k).at(l).real()); + } + else + { + error = (vcl_abs( Result1.at(k).at(l).real() - Result2.at(k).at(l).real()) + / vcl_abs(Result1.at(k).at(l).real() + Result2.at(k).at(l).real()) + + vcl_abs( Result1.at(k).at(l).imag() - Result2.at(k).at(l).imag()) + / vcl_abs(Result1.at(k).at(l).imag() + Result2.at(k).at(l).imag())); + } + + outputStream << "Error = " << error << std::endl + << "Original Image - Complex Moment c" << k << l + << " : " << Result1.at(k).at(l) << std::endl + << "Scaled Image - Complex Moment c" << k << l + << " : " << Result2.at(k).at(l) << std::endl + << std::endl; + /* + if (error > 1) + { + itkGenericExceptionMacro( <<std::endl + << "Error = " << error + << " > 1 -> TEST FAILLED" << std::endl + << "Original Image - Complex Moment c" << k << l + << " : " << Result1.at(k).at(l) << std::endl + << " Scaled Image - Complex Moment c" << k << l + << " : " << Result2.at(k).at(l) << std::endl ); + } + */ + } + } + } + outputStream.close(); + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests1.cxx b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests1.cxx index 1e5bb534e5..9ad43cad06 100644 --- a/Testing/Code/FeatureExtraction/otbFeatureExtractionTests1.cxx +++ b/Testing/Code/FeatureExtraction/otbFeatureExtractionTests1.cxx @@ -30,10 +30,15 @@ void RegisterTests() REGISTER_TEST(otbDrawPathDessinCarre); REGISTER_TEST(otbDrawPathAlign); REGISTER_TEST(otbComplexMomentImage); + REGISTER_TEST(otbComplexMomentImageScaleInvariant); REGISTER_TEST(otbRealMomentImage); REGISTER_TEST(otbRadiometricMomentsImage); REGISTER_TEST(otbHuImage); + REGISTER_TEST(otbHuImageRotationInvariant); + REGISTER_TEST(otbHuImageScaleInvariant); REGISTER_TEST(otbFlusserImage); + REGISTER_TEST(otbFlusserImageRotationInvariant); + REGISTER_TEST(otbFlusserImageScaleInvariant); REGISTER_TEST(otbComplexMomentPathNew); REGISTER_TEST(otbComplexMomentPath); REGISTER_TEST(otbComplexMomentPathFloat); diff --git a/Testing/Code/FeatureExtraction/otbFlusserImage.cxx b/Testing/Code/FeatureExtraction/otbFlusserImage.cxx index 1b7e92c3de..4c8527a23b 100644 --- a/Testing/Code/FeatureExtraction/otbFlusserImage.cxx +++ b/Testing/Code/FeatureExtraction/otbFlusserImage.cxx @@ -24,16 +24,23 @@ #include <iomanip> #include <fstream> #include "itkExceptionObject.h" -#include "itkImage.h" +#include "otbImage.h" #include "otbImageFileReader.h" #include "otbFlusserImageFunction.h" +#include "otbBCOInterpolateImageFunction.h" +#include "itkLinearInterpolateImageFunction.h" +#include "otbStreamingResampleImageFilter.h" +#include "otbStreamingImageFileWriter.h" +#include "itkResampleImageFilter.h" + int otbFlusserImage(int argc, char * argv[]) { const char * inputFilename = argv[1]; const char * outputFilename = argv[2]; + typedef unsigned char InputPixelType; const unsigned int Dimension = 2; @@ -69,3 +76,202 @@ int otbFlusserImage(int argc, char * argv[]) return EXIT_SUCCESS; } + +int otbFlusserImageScaleInvariant(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const char * outputImageName = argv[3]; + + + typedef double InputPixelType; + const unsigned int Dimension = 2; + typedef otb::Image<InputPixelType, Dimension> InputImageType; + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::StreamingResampleImageFilter<InputImageType, + InputImageType, + double> StreamingResampleImageFilterType; + typedef otb::BCOInterpolateImageFunction<InputImageType, + double> InterpolatorType; + typedef otb::FlusserImageFunction<InputImageType> FunctionType; + typedef FunctionType::RealType RealType; + typedef otb::StreamingImageFileWriter<InputImageType> WriterType; + + ReaderType::Pointer reader = ReaderType::New(); + StreamingResampleImageFilterType::Pointer resampler = StreamingResampleImageFilterType::New(); + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + FunctionType::Pointer function1 = FunctionType::New(); + FunctionType::Pointer function2 = FunctionType::New(); + WriterType::Pointer writer = WriterType::New(); + + reader->SetFileName(inputFilename); + reader->Update(); + + interpolator->SetInputImage(reader->GetOutput()); + interpolator->SetRadius(2); + interpolator->SetAlpha(-0.5); + + resampler->SetInput(reader->GetOutput()); + resampler->SetInterpolator(interpolator); + StreamingResampleImageFilterType::SizeType size; + size[0] = 1024; + size[1] = 1024; + resampler->SetOutputSize(size); + resampler->SetOutputSpacing(0.5); + resampler->Update(); + writer->SetInput(resampler->GetOutput()); + writer->SetFileName(outputImageName); + writer->Update(); + + function1->SetInputImage(reader->GetOutput()); + InputImageType::IndexType index1; + index1[0] = 100; + index1[1] = 100; + function1->SetNeighborhoodRadius(2); + RealType Result1 = function1->EvaluateAtIndex(index1); + + function2->SetInputImage(resampler->GetOutput()); + InputImageType::IndexType index2; + index2[0] = 200; + index2[1] = 200; + function2->SetNeighborhoodRadius(4); + RealType Result2 = function2->EvaluateAtIndex(index2); + + std::ofstream outputStream(outputFilename); + outputStream << std::setprecision(10); + + for (unsigned int j = 1; j < 12; j++) + { + double error = 2*vcl_abs( Result1[j-1] - Result2[j-1]) / vcl_abs(Result1[j-1] + Result2[j-1]); + + outputStream << "Error = " << error << std::endl + << "Original Image - Flusser Moment #" << j << " : " << Result1[j-1] << std::endl + << "Scaled Image - Flusser Moment #" << j << " : " << Result2[j-1] << std::endl + << std::endl; + + if (error > 1) + { + itkGenericExceptionMacro( <<std::endl + << "Error = " << error + << " > 1 -> TEST FAILLED" << std::endl + << "Original Image - Flusser Moment #" << j << " : " << Result1[j-1] << std::endl + << "Scaled Image - Flusser Moment #" << j << " : " << Result2[j-1] << std::endl + << std::endl;) + } + } + outputStream.close(); + + return EXIT_SUCCESS; +} + +int otbFlusserImageRotationInvariant(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const char * outputImageName = argv[3]; + const double angleInDegrees = atoi(argv[4]); + + + typedef double InputPixelType; + const unsigned int Dimension = 2; + typedef otb::Image<InputPixelType, Dimension> InputImageType; + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef itk::ResampleImageFilter< + InputImageType, InputImageType > FilterType; + typedef itk::LinearInterpolateImageFunction<InputImageType, double> InterpolatorType; + typedef otb::FlusserImageFunction<InputImageType> FunctionType; + typedef FunctionType::RealType RealType; + typedef otb::StreamingImageFileWriter<InputImageType> WriterType; + typedef itk::AffineTransform< double, Dimension > TransformType; + + + ReaderType::Pointer reader = ReaderType::New(); + FilterType::Pointer filter = FilterType::New(); + TransformType::Pointer transform = TransformType::New(); + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + FunctionType::Pointer function1 = FunctionType::New(); + FunctionType::Pointer function2 = FunctionType::New(); + WriterType::Pointer writer = WriterType::New(); + + reader->SetFileName(inputFilename); + reader->Update(); + + filter->SetInterpolator(interpolator); + filter->SetDefaultPixelValue( 100 ); + + const InputImageType::SpacingType & spacing = reader->GetOutput()->GetSpacing(); + const InputImageType::PointType & origin = reader->GetOutput()->GetOrigin(); + InputImageType::SizeType size = + reader->GetOutput()->GetLargestPossibleRegion().GetSize(); + + filter->SetOutputOrigin( origin ); + filter->SetOutputSpacing( spacing ); + filter->SetOutputDirection( reader->GetOutput()->GetDirection() ); + filter->SetSize( size ); + + + filter->SetInput(reader->GetOutput()); + + TransformType::OutputVectorType translation1; + const double imageCenterX = origin[0] + spacing[0] * size[0] / 2.0; + const double imageCenterY = origin[1] + spacing[1] * size[1] / 2.0; + translation1[0] = -imageCenterX; + translation1[1] = -imageCenterY; + transform->Translate( translation1 ); + + const double degreesToRadians = vcl_atan(1.0) / 45.0; + const double angle = angleInDegrees * degreesToRadians; + transform->Rotate2D( -angle, false ); + + TransformType::OutputVectorType translation2; + translation2[0] = imageCenterX; + translation2[1] = imageCenterY; + transform->Translate( translation2, false ); + + filter->SetTransform( transform ); + filter->Update(); + + writer->SetInput(filter->GetOutput()); + writer->SetFileName(outputImageName); + writer->Update(); + + function1->SetInputImage(reader->GetOutput()); + InputImageType::IndexType index1; + index1[0] = 256; + index1[1] = 256; + function1->SetNeighborhoodRadius(4); + RealType Result1 = function1->EvaluateAtIndex(index1); + + function2->SetInputImage(filter->GetOutput()); + InputImageType::IndexType index2; + index2[0] = 256; + index2[1] = 256; + function2->SetNeighborhoodRadius(4); + RealType Result2 = function2->EvaluateAtIndex(index2); + + std::ofstream outputStream(outputFilename); + outputStream << std::setprecision(10); + + for (unsigned int j = 1; j < 12; j++) + { + double error = vcl_abs( Result1[j-1] - Result2[j-1]); + + outputStream << "Error = " << error << std::endl + << "Original Image - Flusser Moment #" << j << " : " << Result1[j-1] << std::endl + << "Rotated Image - Flusser Moment #" << j << " : " << Result2[j-1] << std::endl + << "Rotation angle : " << angleInDegrees << std::endl; + + if (error > 1E-9) + { + itkGenericExceptionMacro( <<std::endl + << "Error = " << error + << " > 1E-9 -> TEST FAILLED" << std::endl + << "Original Image - Flusser Moment #" << j << " : " << Result1[j-1] << std::endl + << " Rotated Image - Flusser Moment #" << j << " : " << Result2[j-1] << std::endl + << "Rotation angle : " << angleInDegrees << std::endl ); + } + } + outputStream.close(); + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/FeatureExtraction/otbHuImage.cxx b/Testing/Code/FeatureExtraction/otbHuImage.cxx index 2dbfaaad1f..acfd85ab5a 100644 --- a/Testing/Code/FeatureExtraction/otbHuImage.cxx +++ b/Testing/Code/FeatureExtraction/otbHuImage.cxx @@ -24,10 +24,17 @@ #include <iomanip> #include <fstream> #include "itkExceptionObject.h" -#include "itkImage.h" +#include "otbImage.h" #include "otbImageFileReader.h" #include "otbHuImageFunction.h" +#include "otbBCOInterpolateImageFunction.h" +#include "itkLinearInterpolateImageFunction.h" +#include "otbStreamingResampleImageFilter.h" +#include "otbStreamingImageFileWriter.h" +#include "itkResampleImageFilter.h" + + int otbHuImage(int argc, char * argv[]) { @@ -37,7 +44,7 @@ int otbHuImage(int argc, char * argv[]) typedef unsigned char InputPixelType; const unsigned int Dimension = 2; - typedef itk::Image<InputPixelType, Dimension> InputImageType; + typedef otb::Image<InputPixelType, Dimension> InputImageType; typedef otb::ImageFileReader<InputImageType> ReaderType; typedef otb::HuImageFunction<InputImageType> FunctionType; typedef FunctionType::RealType RealType; @@ -67,3 +74,201 @@ int otbHuImage(int argc, char * argv[]) return EXIT_SUCCESS; } + +int otbHuImageScaleInvariant(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const char * outputImageName = argv[3]; + + + typedef double InputPixelType; + const unsigned int Dimension = 2; + typedef otb::Image<InputPixelType, Dimension> InputImageType; + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef otb::StreamingResampleImageFilter<InputImageType, + InputImageType, + double> StreamingResampleImageFilterType; + typedef otb::BCOInterpolateImageFunction<InputImageType, + double> InterpolatorType; + typedef otb::HuImageFunction<InputImageType> FunctionType; + typedef FunctionType::RealType RealType; + typedef otb::StreamingImageFileWriter<InputImageType> WriterType; + + ReaderType::Pointer reader = ReaderType::New(); + StreamingResampleImageFilterType::Pointer resampler = StreamingResampleImageFilterType::New(); + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + FunctionType::Pointer function1 = FunctionType::New(); + FunctionType::Pointer function2 = FunctionType::New(); + WriterType::Pointer writer = WriterType::New(); + + reader->SetFileName(inputFilename); + reader->Update(); + + interpolator->SetInputImage(reader->GetOutput()); + interpolator->SetRadius(2); + interpolator->SetAlpha(-0.5); + + resampler->SetInput(reader->GetOutput()); + resampler->SetInterpolator(interpolator); + StreamingResampleImageFilterType::SizeType size; + size[0] = 1024; + size[1] = 1024; + resampler->SetOutputSize(size); + resampler->SetOutputSpacing(0.5); + resampler->Update(); + writer->SetInput(resampler->GetOutput()); + writer->SetFileName(outputImageName); + writer->Update(); + + function1->SetInputImage(reader->GetOutput()); + InputImageType::IndexType index1; + index1[0] = 100; + index1[1] = 100; + function1->SetNeighborhoodRadius(2); + RealType Result1 = function1->EvaluateAtIndex(index1); + + function2->SetInputImage(resampler->GetOutput()); + InputImageType::IndexType index2; + index2[0] = 200; + index2[1] = 200; + function2->SetNeighborhoodRadius(4); + RealType Result2 = function2->EvaluateAtIndex(index2); + + std::ofstream outputStream(outputFilename); + outputStream << std::setprecision(10); + + for (unsigned int j = 1; j < 8; j++) + { + double error = 2*vcl_abs( Result1[j-1] - Result2[j-1]) / vcl_abs(Result1[j-1] + Result2[j-1]); + + outputStream << "Error = " << error << std::endl + << "Original Image - Hu Moment #" << j << " : " << Result1[j-1] << std::endl + << "Scaled Image - Hu Moment #" << j << " : " << Result2[j-1] << std::endl + << std::endl; + + if (error > 1) + { + itkGenericExceptionMacro( <<std::endl + << "Error = " << error + << " > 1 -> TEST FAILLED" << std::endl + << "Original Image - Hu Moment #" << j << " : " << Result1[j-1] << std::endl + << "Scaled Image - Hu Moment #" << j << " : " << Result2[j-1] << std::endl + << std::endl); + } + } + outputStream.close(); + + return EXIT_SUCCESS; +} + +int otbHuImageRotationInvariant(int argc, char * argv[]) +{ + const char * inputFilename = argv[1]; + const char * outputFilename = argv[2]; + const char * outputImageName = argv[3]; + const double angleInDegrees = atoi(argv[4]); + + + typedef double InputPixelType; + const unsigned int Dimension = 2; + typedef otb::Image<InputPixelType, Dimension> InputImageType; + typedef otb::ImageFileReader<InputImageType> ReaderType; + typedef itk::ResampleImageFilter< + InputImageType, InputImageType > FilterType; + typedef itk::LinearInterpolateImageFunction<InputImageType, double> InterpolatorType; + typedef otb::HuImageFunction<InputImageType> FunctionType; + typedef FunctionType::RealType RealType; + typedef otb::StreamingImageFileWriter<InputImageType> WriterType; + typedef itk::AffineTransform< double, Dimension > TransformType; + + + ReaderType::Pointer reader = ReaderType::New(); + FilterType::Pointer filter = FilterType::New(); + TransformType::Pointer transform = TransformType::New(); + InterpolatorType::Pointer interpolator = InterpolatorType::New(); + FunctionType::Pointer function1 = FunctionType::New(); + FunctionType::Pointer function2 = FunctionType::New(); + WriterType::Pointer writer = WriterType::New(); + + reader->SetFileName(inputFilename); + reader->Update(); + + filter->SetInterpolator(interpolator); + filter->SetDefaultPixelValue( 100 ); + + const InputImageType::SpacingType & spacing = reader->GetOutput()->GetSpacing(); + const InputImageType::PointType & origin = reader->GetOutput()->GetOrigin(); + InputImageType::SizeType size = + reader->GetOutput()->GetLargestPossibleRegion().GetSize(); + + filter->SetOutputOrigin( origin ); + filter->SetOutputSpacing( spacing ); + filter->SetOutputDirection( reader->GetOutput()->GetDirection() ); + filter->SetSize( size ); + + filter->SetInput(reader->GetOutput()); + + TransformType::OutputVectorType translation1; + const double imageCenterX = origin[0] + spacing[0] * size[0] / 2.0; + const double imageCenterY = origin[1] + spacing[1] * size[1] / 2.0; + translation1[0] = -imageCenterX; + translation1[1] = -imageCenterY; + transform->Translate( translation1 ); + + const double degreesToRadians = vcl_atan(1.0) / 45.0; + const double angle = angleInDegrees * degreesToRadians; + transform->Rotate2D( -angle, false ); + + TransformType::OutputVectorType translation2; + translation2[0] = imageCenterX; + translation2[1] = imageCenterY; + transform->Translate( translation2, false ); + + filter->SetTransform( transform ); + filter->Update(); + + writer->SetInput(filter->GetOutput()); + writer->SetFileName(outputImageName); + writer->Update(); + + function1->SetInputImage(reader->GetOutput()); + InputImageType::IndexType index1; + index1[0] = 256; + index1[1] = 256; + function1->SetNeighborhoodRadius(4); + RealType Result1 = function1->EvaluateAtIndex(index1); + + function2->SetInputImage(filter->GetOutput()); + InputImageType::IndexType index2; + index2[0] = 256; + index2[1] = 256; + function2->SetNeighborhoodRadius(4); + RealType Result2 = function2->EvaluateAtIndex(index2); + + std::ofstream outputStream(outputFilename); + outputStream << std::setprecision(10); + + for (unsigned int j = 1; j < 8; j++) + { + double error = vcl_abs( Result1[j-1] - Result2[j-1]); + + outputStream << "Error = " << error << std::endl + << "Original Image - Hu Moment #" << j << " : " << Result1[j-1] << std::endl + << "Rotated Image - Hu Moment #" << j << " : " << Result2[j-1] << std::endl + << "Rotation angle : " << angleInDegrees << std::endl; + + if (error > 1E-9) + { + itkGenericExceptionMacro( <<std::endl + << "Error = " << error + << " > 1E-9 -> TEST FAILLED" << std::endl + << "Original Image - Hu Moment #" << j << " : " << Result1[j-1] << std::endl + << "Rotated Image - Hu Moment #" << j << " : " << Result2[j-1] << std::endl + << "Rotation angle : " << angleInDegrees << std::endl ); + } + } + outputStream.close(); + + return EXIT_SUCCESS; +} -- GitLab