From 14b24ed4bfdfc505f149b2cfb6d7c1bb15a80b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=20Haitz=20Legarreta=20Gorro=C3=B1o?= Date: Wed, 23 Jan 2019 23:25:30 -0500 Subject: [PATCH] ENH: Add a parameter to test to improve `itk::ResampleImageFilter` testing. Add a parameter to the `itkResampleImageFilterTest2.cxx` to improve the `itk::ResampleImageFilter` class testing. Specifically, exercise the workflow when the `UseReferenceImage` boolean is set to `false`. Add to the test arguments: - A boolean to as a hint to use or discard the reference image. - The spacing to be used when resampling when no reference image is used. Add the corresponding baselines. Rename the tests and old baselines to account for this new test. Take advantage of the commit to improve the style of the test: - Use the `TRY_EXPECT_NO_EXCEPTION` in lieu of `try/catch` for the sake of readability/compactness/save typing boilerplate code. - Explicitly call `Update()` on filters with the help of the `TRY_EXPECT_EXCEPTION` macro. - Use the `TEST_SET_GET_BOOLEAN` macro to test the boolean members. - Remove unused/unnecessary `reader` declared variables. - Move the `std::cout` messages before the filter calls to `Update()`. --- ...earestExtrapolateUseRefImageOff.png.sha512 | 1 + ...t2NearestExtrapolateUseRefImageOn.png.md5} | 0 ...earestExtrapolateUseRefImageOn.png.sha512} | 0 .../Filtering/ImageGrid/test/CMakeLists.txt | 44 ++-- .../ImageGrid/test/itkResampleImageTest2.cxx | 216 +++++++++--------- ...esampleImageTest2UseRefImageOff.png.sha512 | 1 + ...> ResampleImageTest2UseRefImageOn.png.md5} | 0 ...esampleImageTest2UseRefImageOn.png.sha512} | 0 8 files changed, 145 insertions(+), 117 deletions(-) create mode 100644 Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png.sha512 rename Modules/Filtering/ImageGrid/test/Baseline/{ResampleImageTest2NearestExtrapolate.png.md5 => ResampleImageTest2NearestExtrapolateUseRefImageOn.png.md5} (100%) rename Modules/Filtering/ImageGrid/test/Baseline/{ResampleImageTest2NearestExtrapolate.png.sha512 => ResampleImageTest2NearestExtrapolateUseRefImageOn.png.sha512} (100%) create mode 100644 Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png.sha512 rename Testing/Data/Baseline/BasicFilters/{ResampleImageTest2.png.md5 => ResampleImageTest2UseRefImageOn.png.md5} (100%) rename Testing/Data/Baseline/BasicFilters/{ResampleImageTest2.png.sha512 => ResampleImageTest2UseRefImageOn.png.sha512} (100%) diff --git a/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png.sha512 b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png.sha512 new file mode 100644 index 00000000000..ad50d02141d --- /dev/null +++ b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png.sha512 @@ -0,0 +1 @@ +f084c848c1c3f2f59431b145baf592c056ae19d98946fac3d281c7b82fef4d89914f2c71ef9e4f6264b87e22dbeda918301baac06338c767184a7b289980baa4 diff --git a/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.png.md5 b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png.md5 similarity index 100% rename from Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.png.md5 rename to Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png.md5 diff --git a/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.png.sha512 b/Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png.sha512 similarity index 100% rename from Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolate.png.sha512 rename to Modules/Filtering/ImageGrid/test/Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png.sha512 diff --git a/Modules/Filtering/ImageGrid/test/CMakeLists.txt b/Modules/Filtering/ImageGrid/test/CMakeLists.txt index 01db9fcccd2..52b0327745b 100644 --- a/Modules/Filtering/ImageGrid/test/CMakeLists.txt +++ b/Modules/Filtering/ImageGrid/test/CMakeLists.txt @@ -232,22 +232,40 @@ itk_add_test(NAME itkMirrorPadWithExponentialDecayTestUChar 0.75 11 7) itk_add_test(NAME itkResampleImageTest COMMAND ITKImageGridTestDriver itkResampleImageTest) -itk_add_test(NAME itkResampleImageTest2 +itk_add_test(NAME itkResampleImageTest2UseRefImageOff COMMAND ITKImageGridTestDriver - --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2.png} - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2a.png - --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2.png} - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2b.png - --compare DATA{Baseline/ResampleImageTest2NearestExtrapolate.png} - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2c.png - --compare DATA{Baseline/ResampleImageTest2NearestExtrapolate.png} - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2d.png + --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2aUseRefImageOff.png + --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2bUseRefImageOff.png + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cUseRefImageOff.png + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOff.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dUseRefImageOff.png itkResampleImageTest2 DATA{${ITK_DATA_ROOT}/Input/cthead1.png} DATA{${ITK_DATA_ROOT}/Input/circle.png} - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2a.png - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2b.png - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2c.png - ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2d.png) + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2aUseRefImageOff.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2bUseRefImageOff.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cUseRefImageOff.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dUseRefImageOff.png + 0 0.8) +itk_add_test(NAME itkResampleImageTest2UseRefImageOn + COMMAND ITKImageGridTestDriver + --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2aUseRefImageOn.png + --compare DATA{${ITK_DATA_ROOT}/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2bUseRefImageOn.png + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cUseRefImageOn.png + --compare DATA{Baseline/ResampleImageTest2NearestExtrapolateUseRefImageOn.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dUseRefImageOn.png + itkResampleImageTest2 DATA{${ITK_DATA_ROOT}/Input/cthead1.png} + DATA{${ITK_DATA_ROOT}/Input/circle.png} + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2aUseRefImageOn.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2bUseRefImageOn.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cUseRefImageOn.png + ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dUseRefImageOn.png + 1) itk_add_test(NAME itkResampleImageTest3 COMMAND ITKImageGridTestDriver --compare DATA{Baseline/ResampleImageTest3.png} diff --git a/Modules/Filtering/ImageGrid/test/itkResampleImageTest2.cxx b/Modules/Filtering/ImageGrid/test/itkResampleImageTest2.cxx index a2f70e0529b..92cc493da6f 100644 --- a/Modules/Filtering/ImageGrid/test/itkResampleImageTest2.cxx +++ b/Modules/Filtering/ImageGrid/test/itkResampleImageTest2.cxx @@ -54,20 +54,24 @@ class NonlinearAffineTransform: }; } -int itkResampleImageTest2(int argc, char * argv [] ) +int itkResampleImageTest2(int argc, char * argv[]) { - if( argc < 5 ) - { - std::cerr << "Missing arguments ! " << std::endl; - std::cerr << "Usage : " << std::endl; - std::cerr << argv[0] << "inputImage referenceImage " - << "resampledImageLinear resampledImageNonLinear " - << "resampledImageLinearNearestExtrapolate" - << "resampledImageNonLinearNearestExtrapolate"; - std::cerr << std::endl; + if (argc < 8) + { + std::cerr << "Missing parameters." << std::endl; + std::cerr << "Usage: " << std::endl; + std::cerr << argv[0]; + std::cerr << "inputImage " + << " referenceImage" + << " resampledImageLinear" + << " resampledImageNonLinear" + << " resampledImageLinearNearestExtrapolate" + << " resampledImageNonLinearNearestExtrapolate" + << " useReferenceImage" + << " [outputSpacing]" << std::endl; return EXIT_FAILURE; - } + } constexpr unsigned int NDimensions = 2; @@ -76,36 +80,31 @@ int itkResampleImageTest2(int argc, char * argv [] ) using CoordRepType = double; using AffineTransformType = - itk::AffineTransform; + itk::AffineTransform; using NonlinearAffineTransformType = - NonlinearAffineTransform; + NonlinearAffineTransform; using InterpolatorType = - itk::LinearInterpolateImageFunction; + itk::LinearInterpolateImageFunction; using ExtrapolatorType = - itk::NearestNeighborExtrapolateImageFunction; + itk::NearestNeighborExtrapolateImageFunction; using ReaderType = itk::ImageFileReader< ImageType >; using WriterType = itk::ImageFileWriter< ImageType >; ReaderType::Pointer reader1 = ReaderType::New(); ReaderType::Pointer reader2 = ReaderType::New(); - ReaderType::Pointer reader3 = ReaderType::New(); - ReaderType::Pointer reader4 = ReaderType::New(); WriterType::Pointer writer1 = WriterType::New(); WriterType::Pointer writer2 = WriterType::New(); WriterType::Pointer writer3 = WriterType::New(); WriterType::Pointer writer4 = WriterType::New(); - reader1->SetFileName( argv[1] ); - reader2->SetFileName( argv[2] ); - reader3->SetFileName( argv[3] ); - reader4->SetFileName( argv[4] ); + reader1->SetFileName(argv[1]); - writer1->SetFileName( argv[3] ); - writer2->SetFileName( argv[4] ); - writer3->SetFileName( argv[5] ); - writer4->SetFileName( argv[6] ); + writer1->SetFileName(argv[3]); + writer2->SetFileName(argv[4]); + writer3->SetFileName(argv[5]); + writer4->SetFileName(argv[6]); // Create an affine transformation AffineTransformType::Pointer affineTransform = AffineTransformType::New(); @@ -122,45 +121,92 @@ int itkResampleImageTest2(int argc, char * argv [] ) ResampleFilterType::Pointer resample = ResampleFilterType::New(); - EXERCISE_BASIC_OBJECT_METHODS( resample, ResampleImageFilter, ImageToImageFilter ); + EXERCISE_BASIC_OBJECT_METHODS(resample, ResampleImageFilter, ImageToImageFilter); - resample->SetInput( reader1->GetOutput() ); - TEST_SET_GET_VALUE( reader1->GetOutput(), resample->GetInput() ); - resample->SetReferenceImage( reader2->GetOutput() ); - TEST_SET_GET_VALUE( reader2->GetOutput(), resample->GetReferenceImage() ); + TRY_EXPECT_NO_EXCEPTION( reader1->Update() ); - resample->UseReferenceImageOn(); - TEST_EXPECT_TRUE( resample->GetUseReferenceImage() ); + resample->SetInput(reader1->GetOutput()); + TEST_SET_GET_VALUE(reader1->GetOutput(), resample->GetInput()); - resample->SetTransform( affineTransform ); - TEST_SET_GET_VALUE( affineTransform, resample->GetTransform() ); + resample->SetTransform(affineTransform); + TEST_SET_GET_VALUE(affineTransform, resample->GetTransform()); - resample->SetInterpolator( interpolator ); - TEST_SET_GET_VALUE( interpolator, resample->GetInterpolator() ); + resample->SetInterpolator(interpolator); + TEST_SET_GET_VALUE(interpolator, resample->GetInterpolator()); - writer1->SetInput( resample->GetOutput() ); + bool useReferenceImage = std::stoi( argv[7] ); + TEST_SET_GET_BOOLEAN( resample, UseReferenceImage, useReferenceImage ); - // Check GetReferenceImage - if( resample->GetReferenceImage() != reader2->GetOutput() ) + + // If the reference image is to be used, read it and set it to the filter; + // else, create an image region for the output image. + if( useReferenceImage ) { - std::cerr << "GetReferenceImage() failed ! " << std::endl; - return EXIT_FAILURE; + reader2->SetFileName( argv[2] ); + + TRY_EXPECT_NO_EXCEPTION( reader2->Update() ); + + resample->SetReferenceImage( reader2->GetOutput() ); + TEST_SET_GET_VALUE( reader2->GetOutput(), resample->GetReferenceImage() ); + } + else + { + // Set a fixed, isotropic output spacing + typename ImageType::SpacingType::ValueType outputSpacingValue = 1.5; + if( argc > 7 ) + { + outputSpacingValue = std::stod( argv[8] ); + } + + typename ImageType::SpacingType outputSpacing; + for( unsigned int i = 0; i < NDimensions; ++i ) + { + outputSpacing[i] = outputSpacingValue; + } + + const typename ImageType::SizeType& inputSize = + resample->GetInput()->GetLargestPossibleRegion().GetSize(); + const typename ImageType::SpacingType& inputSpacing = + resample->GetInput()->GetSpacing(); + + typename ImageType::SizeType outputSize; + + typedef typename ImageType::SizeType::SizeValueType SizeValueType; + for( unsigned int i = 0; i < NDimensions; ++i ) + { + outputSize[i] = static_cast< SizeValueType >( + (double)inputSize[i] * inputSpacing[i] / outputSpacing[i]); + } + + resample->SetOutputSpacing( outputSpacing ); + resample->SetSize( outputSize ); + resample->SetOutputOrigin( resample->GetInput()->GetOrigin() ); + resample->SetOutputDirection( resample->GetInput()->GetDirection() ); } // Run the resampling filter with the normal, linear, affine transform. // This will use ResampleImageFilter::LinearThreadedGenerateData(). std::cout << "Test with normal AffineTransform." << std::endl; - try - { - writer1->Update(); - } - catch( itk::ExceptionObject & excp ) + + TRY_EXPECT_NO_EXCEPTION(resample->Update()); + + writer1->SetInput(resample->GetOutput()); + + // Check GetReferenceImage + if( useReferenceImage ) { - std::cerr << excp << std::endl; - return EXIT_FAILURE; + if (resample->GetReferenceImage() != reader2->GetOutput()) + { + std::cerr << "Test failed!" << std::endl; + std::cerr << "GetReferenceImage() failed ! " << std::endl; + return EXIT_FAILURE; + } } + TRY_EXPECT_NO_EXCEPTION( writer1->Update() ); + + // Assign an affine transform that returns // false for IsLinear() instead of true, to force // the filter to use the NonlinearThreadedGenerateData method @@ -172,77 +218,39 @@ int itkResampleImageTest2(int argc, char * argv [] ) nonlinearAffineTransform->Scale(2.0); resample->SetTransform( nonlinearAffineTransform ); + + TRY_EXPECT_NO_EXCEPTION( resample->Update() ); + writer2->SetInput( resample->GetOutput() ); - try - { - writer2->Update(); - } - catch( itk::ExceptionObject & excp ) - { - std::cerr << excp << std::endl; - return EXIT_FAILURE; - } + + TRY_EXPECT_NO_EXCEPTION( writer2->Update() ); + // Instead of using the default pixel when sampling outside the input image, // we use a nearest neighbor extrapolator. + std::cout << "Test with nearest neighbor extrapolator, affine transform." << std::endl; resample->SetTransform( affineTransform ); resample->SetExtrapolator( extrapolator ); + + TRY_EXPECT_NO_EXCEPTION( resample->Update() ); + writer3->SetInput( resample->GetOutput() ); - std::cout << "Test with nearest neighbor extrapolator, affine transform." << std::endl; - try - { - writer3->Update(); - } - catch( itk::ExceptionObject & excp ) - { - std::cerr << excp << std::endl; - return EXIT_FAILURE; - } + + TRY_EXPECT_NO_EXCEPTION( writer3->Update() ); + // Instead of using the default pixel when sampling outside the input image, // we use a nearest neighbor extrapolator. - resample->SetTransform( nonlinearAffineTransform ); - writer4->SetInput( resample->GetOutput() ); std::cout << "Test with nearest neighbor extrapolator, nonlinear transform." << std::endl; - try - { - writer4->Update(); - } - catch( itk::ExceptionObject & excp ) - { - std::cerr << excp << std::endl; - return EXIT_FAILURE; - } + resample->SetTransform( nonlinearAffineTransform ); - // Check UseReferenceImage methods - resample->UseReferenceImageOff(); - if( resample->GetUseReferenceImage() ) - { - std::cerr << "GetUseReferenceImage() or UseReferenceImageOff() failed ! "; - std::cerr << std::endl; - return EXIT_FAILURE; - } + TRY_EXPECT_NO_EXCEPTION( resample->Update() ); - // Check UseReferenceImage methods - resample->UseReferenceImageOn(); - if( !resample->GetUseReferenceImage() ) - { - std::cerr << "GetUseReferenceImage() or UseReferenceImageOn() failed ! "; - std::cerr << std::endl; - return EXIT_FAILURE; - } + writer4->SetInput( resample->GetOutput() ); - // Check UseReferenceImage methods - resample->SetUseReferenceImage( false ); - if( resample->GetUseReferenceImage() ) - { - std::cerr << "GetUseReferenceImage() or SetUseReferenceImage() failed ! "; - std::cerr << std::endl; - return EXIT_FAILURE; - } + TRY_EXPECT_NO_EXCEPTION( writer4->Update() ); - std::cout << "Test passed." << std::endl; + std::cout << "Test finished." << std::endl; return EXIT_SUCCESS; - } diff --git a/Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png.sha512 b/Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png.sha512 new file mode 100644 index 00000000000..c7960c4f95c --- /dev/null +++ b/Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOff.png.sha512 @@ -0,0 +1 @@ +7eb79455a61686919e646504147ce973be74f5669bca42daa1d45a95f45dc559eee8982dfbf3e97147f2acb76296764b4e08d1a16abc45a6787818b1967d44dd diff --git a/Testing/Data/Baseline/BasicFilters/ResampleImageTest2.png.md5 b/Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png.md5 similarity index 100% rename from Testing/Data/Baseline/BasicFilters/ResampleImageTest2.png.md5 rename to Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png.md5 diff --git a/Testing/Data/Baseline/BasicFilters/ResampleImageTest2.png.sha512 b/Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png.sha512 similarity index 100% rename from Testing/Data/Baseline/BasicFilters/ResampleImageTest2.png.sha512 rename to Testing/Data/Baseline/BasicFilters/ResampleImageTest2UseRefImageOn.png.sha512