Skip to content

Commit

Permalink
ENH: new tests to verify streaming capabilities of itkResampleImageFi…
Browse files Browse the repository at this point in the history
…lter

New tests are expected to fail as long as itkResampleFilter does not
support streaming for linear transforms GH PR InsightSoftwareConsortium#82.

Also, tests for comparing output with stream driven imaging (SDI) and
without based on itkWarpImageFilterTest2.cxx and
itkResampleImageTest.cxx.
  • Loading branch information
romangrothausmann authored and thewtex committed Feb 4, 2019
1 parent a1bd683 commit f973208
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6dcda44ce36e39fb6a792e26c8cd93830bab8edbe9f33385dc59b24bd6b40c99bbadf9b6ada967b1d1b6624e986f1161960d86db63b2d6b71da58eec0a2b911c
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bbc1a32a82e88334df11c79f54ba4260ea291f8316c882d6360e7546739eb92109a169cc07abe32250a4e12e49a4bb8bad22c45580ccb78c4ee482fa68675e4f
14 changes: 14 additions & 0 deletions Modules/Filtering/ImageGrid/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ itkMirrorPadImageTest.cxx
itkMirrorPadImageFilterTest.cxx
itkResampleImageTest.cxx
itkResampleImageTest2.cxx
itkResampleImageTest2Streaming.cxx
itkResampleImageTest3.cxx
itkResampleImageTest4.cxx
itkResampleImageTest5.cxx
itkResampleImageTest6.cxx
itkResampleImageTest7.cxx
itkResamplePhasedArray3DSpecialCoordinatesImageTest.cxx
itkPushPopTileImageFilterTest.cxx
itkShrinkImageStreamingTest.cxx
Expand Down Expand Up @@ -266,6 +268,15 @@ itk_add_test(NAME itkResampleImageTest2UseRefImageOn
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cUseRefImageOn.png
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dUseRefImageOn.png
1)
itk_add_test(NAME itkResampleImageTest2Streaming
COMMAND ITKImageGridTestDriver
itkResampleImageTest2Streaming DATA{Input/cthead1.mha}
DATA{Input/cthead1.mha}
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2aStreaming.mha
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2bStreaming.mha
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2cStreaming.mha
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest2dStreaming.mha)
set_tests_properties(itkResampleImageTest2Streaming PROPERTIES WILL_FAIL TRUE) # should fail as long as itkResampleFilter does not support streaming for linear transforms GH PR #82
itk_add_test(NAME itkResampleImageTest3
COMMAND ITKImageGridTestDriver
--compare DATA{Baseline/ResampleImageTest3.png}
Expand All @@ -284,6 +295,9 @@ itk_add_test(NAME itkResampleImageTest6
--compare DATA{Baseline/ResampleImageTest6.png}
${ITK_TEST_OUTPUT_DIR}/ResampleImageTest6.png
itkResampleImageTest6 10 ${ITK_TEST_OUTPUT_DIR}/ResampleImageTest6.png)
itk_add_test(NAME itkResampleImageTest7
COMMAND ITKImageGridTestDriver itkResampleImageTest7)
set_tests_properties(itkResampleImageTest7 PROPERTIES WILL_FAIL TRUE) # should fail as long as itkResampleFilter does not support streaming for linear transforms GH PR #82
itk_add_test(NAME itkResamplePhasedArray3DSpecialCoordinatesImageTest
COMMAND ITKImageGridTestDriver itkResamplePhasedArray3DSpecialCoordinatesImageTest)
itk_add_test(NAME itkPushPopTileImageFilterTest
Expand Down
1 change: 1 addition & 0 deletions Modules/Filtering/ImageGrid/test/Input/cthead1.mha.sha512
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bca480e13f66b2b85a3513c8c8ca6b38b3d9df7a24ab9a35654858173001f29323471f27632dc42a5714dc5c7d4dbcb1fbf5ba0b9699fe7bd73080cdcd262270
209 changes: 209 additions & 0 deletions Modules/Filtering/ImageGrid/test/itkResampleImageTest2Streaming.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
/*=========================================================================
*
* Copyright Insight Software Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/

#include <iostream>

#include "itkAffineTransform.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkResampleImageFilter.h"
#include "itkNearestNeighborExtrapolateImageFunction.h"
#include "itkPipelineMonitorImageFilter.h"
#include "itkTestingMacros.h"

/* Further testing of itkResampleImageFilter
* Output is compared with baseline image using the cmake itk_add_test
* '--compare' option.
*/

namespace {

template<typename TCoordRepType, unsigned int NDimensions>
class NonlinearAffineTransform:
public itk::AffineTransform<TCoordRepType,NDimensions>
{
public:
/** Standard class type aliases. */
using Self = NonlinearAffineTransform;
using Superclass = itk::AffineTransform< TCoordRepType, NDimensions >;
using Pointer = itk::SmartPointer< Self >;
using ConstPointer = itk::SmartPointer< const Self >;

/** New macro for creation of through a smart pointer. */
itkSimpleNewMacro(Self);

/** Run-time type information (and related methods). */
itkTypeMacro(NonlinearAffineTransform, AffineTransform);

/** Override this. See test below. */
bool IsLinear() const override { return false; }
};
}

int itkResampleImageTest2Streaming( int argc, char * argv [] )
{
if( argc < 7 )
{
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;
return EXIT_FAILURE;
}

constexpr unsigned int NDimensions = 2;

using PixelType = unsigned char;
using ImageType = itk::Image<PixelType, NDimensions>;
using CoordRepType = double;

using AffineTransformType = itk::AffineTransform<CoordRepType,NDimensions>;
using NonlinearAffineTransformType = NonlinearAffineTransform<CoordRepType,NDimensions>;
using InterpolatorType = itk::LinearInterpolateImageFunction<ImageType,CoordRepType>;
using ExtrapolatorType = itk::NearestNeighborExtrapolateImageFunction<ImageType,CoordRepType>;

using ReaderType = itk::ImageFileReader< ImageType >;
using WriterType = itk::ImageFileWriter< ImageType >;

ReaderType::Pointer reader1 = ReaderType::New();
ReaderType::Pointer reader2 = 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] );

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();
affineTransform->Scale(2.0);

// Create a linear interpolation image function
InterpolatorType::Pointer interpolator = InterpolatorType::New();

// Create a nearest neighbor extrapolate image function
ExtrapolatorType::Pointer extrapolator = ExtrapolatorType::New();

// Create and configure a resampling filter
using ResampleFilterType = itk::ResampleImageFilter< ImageType, ImageType >;
ResampleFilterType::Pointer resample = ResampleFilterType::New();

using MonitorFilterType = itk::PipelineMonitorImageFilter< ImageType >;
MonitorFilterType::Pointer monitor = MonitorFilterType::New();

EXERCISE_BASIC_OBJECT_METHODS( resample, ResampleImageFilter, ImageToImageFilter );

monitor->SetInput( reader1->GetOutput() );
resample->SetInput( monitor->GetOutput() );
TEST_SET_GET_VALUE( reader1->GetOutput(), monitor->GetInput() );

resample->SetReferenceImage( reader2->GetOutput() );
TEST_SET_GET_VALUE( reader2->GetOutput(), resample->GetReferenceImage() );

resample->UseReferenceImageOn();
TEST_EXPECT_TRUE( resample->GetUseReferenceImage() );

resample->SetTransform( affineTransform );
TEST_SET_GET_VALUE( affineTransform, resample->GetTransform() );

resample->SetInterpolator( interpolator );
TEST_SET_GET_VALUE( interpolator, resample->GetInterpolator() );

resample->SetInput( monitor->GetOutput() );
writer1->SetInput( resample->GetOutput() );

// Check GetReferenceImage
if( resample->GetReferenceImage() != reader2->GetOutput() )
{
std::cerr << "GetReferenceImage() failed ! " << std::endl;
std::cerr << "Test failed." << std::endl;
return EXIT_FAILURE;
}

// Run the resampling filter with the normal, linear, affine transform.
// This will use ResampleImageFilter::LinearThreadedGenerateData().
std::cout << "Test with normal AffineTransform." << std::endl;
writer1->SetNumberOfStreamDivisions(8); //split into 8 pieces for streaming.
TRY_EXPECT_NO_EXCEPTION( writer1->Update() );

// this verifies that the pipeline was executed as expected along
// with correct region propagation and output information
if (!monitor->VerifyAllInputCanStream(8))
{
std::cerr << "Streaming failed to execute as expected!" << std::endl;
std::cerr << monitor;
std::cerr << "Test failed." << std::endl;
return EXIT_FAILURE;
}

// Assign an affine transform that returns
// false for IsLinear() instead of true, to force
// the filter to use the NonlinearThreadedGenerateData method
// instead of LinearThreadedGenerateData. This will test that
// we get the same results for both methods.
std::cout << "Test with NonlinearAffineTransform." << std::endl;
NonlinearAffineTransformType::Pointer nonlinearAffineTransform =
NonlinearAffineTransformType::New();

nonlinearAffineTransform->Scale(2.0);
resample->SetTransform( nonlinearAffineTransform );
writer2->SetInput( resample->GetOutput() );
monitor->ClearPipelineSavedInformation();
writer2->SetNumberOfStreamDivisions(8); //demand splitting into 8 pieces for streaming, but faked non-linearity will disable streaming
TRY_EXPECT_NO_EXCEPTION( writer2->Update() );

// check that streaming is not possible for non-linear case
if (!monitor->VerifyAllInputCanStream(8))
{
std::cerr << "Streaming succedded for non-linear transform which should not be the case!" << std::endl;
std::cerr << monitor;
std::cerr << "Test failed." << std::endl;
return EXIT_FAILURE;
}

// Instead of using the default pixel when sampling outside the input image,
// we use a nearest neighbor extrapolator.
resample->SetTransform( affineTransform );
resample->SetExtrapolator( extrapolator );
writer3->SetInput( resample->GetOutput() );
std::cout << "Test with nearest neighbor extrapolator, affine transform." << std::endl;
writer3->SetNumberOfStreamDivisions(8); //split into 8 pieces for streaming.
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;
writer4->SetNumberOfStreamDivisions(8); //demand splitting into 8 pieces for streaming, but faked non-linearity will disable streaming
TRY_EXPECT_NO_EXCEPTION( writer4->Update() );

std::cout << "Test passed." << std::endl;
return EXIT_SUCCESS;

}
Loading

0 comments on commit f973208

Please sign in to comment.