diff --git a/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx b/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx index 16f1f88060ac..86330c977890 100644 --- a/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx +++ b/Modules/Filtering/ImageGrid/test/itkResampleImageTest7.cxx @@ -19,6 +19,8 @@ #include #include "itkAffineTransform.h" +#include "itkCastImageFilter.h" +#include "itkPipelineMonitorImageFilter.h" #include "itkResampleImageFilter.h" #include "itkStreamingImageFilter.h" #include "itkTestingMacros.h" @@ -79,8 +81,17 @@ itkResampleImageTest7(int, char *[]) ITK_EXERCISE_BASIC_OBJECT_METHODS(resample, ResampleImageFilter, ImageToImageFilter); resample->SetInterpolator(interp); - resample->SetInput(image); - ITK_TEST_SET_GET_VALUE(image.GetPointer(), resample->GetInput()); + // Route the input through CastImageFilter so the streaming-equivalence comparison + // exercises a chunked BufferedRegion, which an in-memory Image alone cannot produce. + // PipelineMonitorImageFilter then records each chunked Update so we can assert the + // filter under test actually saw N executions when streaming requests N divisions. + const auto upstream = itk::CastImageFilter::New(); + upstream->SetInput(image); + using MonitorType = itk::PipelineMonitorImageFilter; + const auto monitor = MonitorType::New(); + monitor->SetInput(upstream->GetOutput()); + resample->SetInput(monitor->GetOutput()); + ITK_TEST_SET_GET_VALUE(monitor->GetOutput(), resample->GetInput()); resample->SetSize(size); ITK_TEST_SET_GET_VALUE(size, resample->GetSize()); @@ -109,12 +120,24 @@ itkResampleImageTest7(int, char *[]) const ImagePointerType outputNoSDI = streamer->GetOutput(); // save output for later comparison outputNoSDI->DisconnectPipeline(); // disconnect to create new output + // Reset the streaming history before the streamed pass so the verify below + // sees only the streamed run's chunks. + monitor->ClearPipelineSavedInformation(); + // Run the resampling filter with streaming image->Modified(); numStreamDiv = 8; // split into numStream pieces for streaming. streamer->SetNumberOfStreamDivisions(numStreamDiv); ITK_TRY_EXPECT_NO_EXCEPTION(streamer->UpdateLargestPossibleRegion()); + // Confirm the upstream chain actually streamed the requested number of chunks. + if (!monitor->VerifyInputFilterExecutedStreaming(static_cast(numStreamDiv))) + { + std::cerr << "Streaming did not chunk the input as expected." << std::endl; + std::cerr << monitor; + return EXIT_FAILURE; + } + // Verify that we only requested a smaller chunk when streaming const ImageRegionType finalRequestedRegion(image->GetRequestedRegion()); ITK_TEST_SET_GET_VALUE(0, finalRequestedRegion.GetIndex(0)); diff --git a/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx b/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx index 01647ad0a6a5..8ef0816eef64 100644 --- a/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx +++ b/Modules/Filtering/ImageGrid/test/itkWarpImageFilterTest.cxx @@ -21,6 +21,7 @@ #include "itkMath.h" #include "itkWarpImageFilter.h" #include "itkCastImageFilter.h" +#include "itkPipelineMonitorImageFilter.h" #include "itkStreamingImageFilter.h" #include "itkVectorImage.h" #include "itkTestingMacros.h" @@ -318,23 +319,40 @@ itkWarpImageFilterTest(int, char *[]) std::cout << "Run ExpandImageFilter with streamer" << std::endl; + // Route the displacement field through a CastImageFilter (streaming-aware no-op) + // and a PipelineMonitorImageFilter so we can assert the warper actually streamed + // its displacement-field input. The image input is intentionally NOT routed + // through a similar chain: WarpImageFilter requests its full image input for any + // output region, so verifying streaming on the image input would always fail. using VectorCasterType = itk::CastImageFilter; auto vcaster = VectorCasterType::New(); - vcaster->SetInput(warper->GetDisplacementField()); + using FieldMonitorType = itk::PipelineMonitorImageFilter; + auto vmonitor = FieldMonitorType::New(); + vmonitor->SetInput(vcaster->GetOutput()); + auto warper2 = WarperType::New(); warper2->SetInput(warper->GetInput()); - warper2->SetDisplacementField(vcaster->GetOutput()); + warper2->SetDisplacementField(vmonitor->GetOutput()); warper2->SetEdgePaddingValue(warper->GetEdgePaddingValue()); using StreamerType = itk::StreamingImageFilter; auto streamer = StreamerType::New(); streamer->SetInput(warper2->GetOutput()); - streamer->SetNumberOfStreamDivisions(3); + constexpr int numStreamDivisions = 3; + streamer->SetNumberOfStreamDivisions(numStreamDivisions); streamer->Update(); + // Confirm the warp actually streamed its displacement-field input. + if (!vmonitor->VerifyInputFilterExecutedStreaming(numStreamDivisions)) + { + std::cerr << "Displacement field did not stream as expected." << std::endl; + std::cerr << vmonitor; + return EXIT_FAILURE; + } + std::cout << "Compare standalone and streamed outputs" << std::endl; Iterator streamIter(streamer->GetOutput(), streamer->GetOutput()->GetBufferedRegion()); diff --git a/Modules/Filtering/ImageGrid/test/itkWarpVectorImageFilterTest.cxx b/Modules/Filtering/ImageGrid/test/itkWarpVectorImageFilterTest.cxx index 1e1d71ff5a57..18ade5c9c502 100644 --- a/Modules/Filtering/ImageGrid/test/itkWarpVectorImageFilterTest.cxx +++ b/Modules/Filtering/ImageGrid/test/itkWarpVectorImageFilterTest.cxx @@ -20,6 +20,7 @@ #include "itkWarpVectorImageFilter.h" #include "itkCastImageFilter.h" +#include "itkPipelineMonitorImageFilter.h" #include "itkStreamingImageFilter.h" #include "itkTestingMacros.h" @@ -297,18 +298,35 @@ itkWarpVectorImageFilterTest(int, char *[]) vcaster->SetInput(warper->GetDisplacementField()); + // PipelineMonitorImageFilter on the displacement-field path so we can assert + // the warper actually streamed that input. WarpVectorImageFilter requests its + // full image input for any output region, so verifying streaming on the image + // input would always fail. + using FieldMonitorType = itk::PipelineMonitorImageFilter; + auto vmonitor = FieldMonitorType::New(); + vmonitor->SetInput(vcaster->GetOutput()); + auto warper2 = WarperType::New(); warper2->SetInput(warper->GetInput()); - warper2->SetDisplacementField(vcaster->GetOutput()); + warper2->SetDisplacementField(vmonitor->GetOutput()); warper2->SetEdgePaddingValue(warper->GetEdgePaddingValue()); using StreamerType = itk::StreamingImageFilter; auto streamer = StreamerType::New(); streamer->SetInput(warper2->GetOutput()); - streamer->SetNumberOfStreamDivisions(3); + constexpr int numStreamDivisions = 3; + streamer->SetNumberOfStreamDivisions(numStreamDivisions); streamer->Update(); + // Confirm the warp actually streamed its displacement-field input. + if (!vmonitor->VerifyInputFilterExecutedStreaming(numStreamDivisions)) + { + std::cerr << "Displacement field did not stream as expected." << std::endl; + std::cerr << vmonitor; + return EXIT_FAILURE; + } + std::cout << "Compare standalone and streamed outputs" << std::endl; Iterator streamIter(streamer->GetOutput(), streamer->GetOutput()->GetBufferedRegion());