How to make SmoothingRecursiveGaussianImageFilter supports RequestedRegion

Hi,
In a nutshell, I’m trying to make SmoothingRecursiveGaussianImageFilter not overwriting the user RequestedRegion.

The current behavior of the filter is that it modifies the output’s requested region to be the largest possible region by overriding GenerateInputRequestedRegion and EnlargeOutputRequestedRegion:

SmoothingRecursiveGaussianImageFilter does not support streaming and that’s why it asks for the whole data.

Below is a toy example where I generate a big random image, subtract a constant from and smooth a tiny ROI of it by invoking filter->GetOutput()->SetRequestedRegion(ROI);

#include "itkImage.h"
#include "itkRandomImageSource.h"
#include "itkSmoothingRecursiveGaussianImageFilter.h"
#include "itkSubtractImageFilter.h"

int main(int argc, char** argv)
{
    const unsigned int Dimension = 2;
    typedef itk::Image< unsigned char, Dimension > ImageType;
    typedef itk::Image< float, Dimension > FImageType;

    // Define image index and size
    ImageType::IndexType index;
    index.Fill(0);
    ImageType::SizeType bigSize;
    bigSize.Fill(10000);

    // Define a tiny ROI
    ImageType::SizeType smallSize;
    smallSize.Fill(10);

    // Generate random image
    typedef itk::RandomImageSource<ImageType> RandomSourceType;
    RandomSourceType::Pointer randomImageSource = RandomSourceType::New();
    randomImageSource->SetNumberOfThreads(1); // to produce the always the same random results
    randomImageSource->SetSize(bigSize);

    // Subtract a constant
    typedef itk::SubtractImageFilter<ImageType, ImageType> SubtractImageFilterType;
    SubtractImageFilterType::Pointer subtractFilter = SubtractImageFilterType::New();
    subtractFilter->SetInput1(randomImageSource->GetOutput());
    subtractFilter->SetConstant2(10);

    // Smooth    
    using SmoothFilterType = itk::SmoothingRecursiveGaussianImageFilter<ImageType, FImageType>;
    typename SmoothFilterType::Pointer smoothFilter = SmoothFilterType::New();
    smoothFilter->SetInput(subtractFilter->GetOutput());
    smoothFilter->SetSigma(.7);
    smoothFilter->GetOutput()->SetRequestedRegion(smallSize); // has no effect (overridden by Update())
    smoothFilter->Update();

    std::cout << "randomImageSource Requested Region after update" << std::endl;
    randomImageSource->GetOutput()->GetRequestedRegion().Print(std::cout);

    std::cout << "subtractFilter Requested Region after update" << std::endl;
    subtractFilter->GetOutput()->GetRequestedRegion().Print(std::cout);

    std::cout << "smoothFilter Requested Region after update" << std::endl;
    smoothFilter->GetOutput()->GetRequestedRegion().Print(std::cout);

    return 0;
}

Which spits out:

randomImageSource Requested Region after update
ImageRegion (0000022C5D8B4390)
  Dimension: 2
  Index: [0, 0]
  Size: [10000, 10000]
subtractFilter Requested Region after update
ImageRegion (000002933C1C91B0)
  Dimension: 2
  Index: [0, 0]
  Size: [10000, 10000]
smoothFilter Requested Region after update
ImageRegion (000002933C1CD830)
  Dimension: 2
  Index: [0, 0]
  Size: [10000, 10000]

So far the behavior is expected.

Now I override SmoothingRecursiveGaussianImageFilter to
re-establish the default pipeline upstream behavior. So I create a new filter, SmoothingRecursiveGaussianImageFilter2 as follow:

#ifndef itkSmoothingRecursiveGaussianImageFilter2_h
#define itkSmoothingRecursiveGaussianImageFilter2_h

#include "itkSmoothingRecursiveGaussianImageFilter.h"
#include "itkImage.h"

namespace itk
{
template <typename TInputImage, typename TOutputImage = TInputImage>
class ITK_TEMPLATE_EXPORT SmoothingRecursiveGaussianImageFilter2 : public SmoothingRecursiveGaussianImageFilter<TInputImage, TOutputImage>
{
public:
  ITK_DISALLOW_COPY_AND_MOVE(SmoothingRecursiveGaussianImageFilter2);

  /** Standard class type aliases. */
  using Self = SmoothingRecursiveGaussianImageFilter2;
  using Pointer = SmartPointer<Self>;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

protected:
  SmoothingRecursiveGaussianImageFilter2() {};
  ~SmoothingRecursiveGaussianImageFilter2() override = default;

  /** Re-establish the default upstream PropagateRequestedRegion.
   *
   * \sa ImageToImageFilter::GenerateInputRequestedRegion() */
  void
  GenerateInputRequestedRegion() override {};

  /** Re-establish the default upstream PropagateRequestedRegion.
   *
   * \sa ImageToImageFilter::EnlargeOutputRequestedRegion() */
  void
  EnlargeOutputRequestedRegion(DataObject * output) override {};
};
} // end namespace itk

#endif

And then replace the original smoothing filter in the toy example above by the overridden one. Which returns:

randomImageSource Requested Region after update
ImageRegion (0000022C5D8B4390)
 Dimension: 2
 Index: [0, 0]
 Size: [10000, 10000]
subtractFilter Requested Region after update
ImageRegion (00000225E43926B0)
 Dimension: 2
 Index: [0, 0]
 Size: [10000, 10000]
smoothFilter2 Requested Region after update
ImageRegion (00000225E4394270)
 Dimension: 2
 Index: [0, 0]
 Size: [10, 10]

The good thing is that the RequestedRegion of the smoothing filter is not overridden anymore. However, knowing that the subtraction filter accepts streaming, I’m struggling to find out why the RequestedRegion is not propagating upstream (the default behavior).

Any help is appreciated!

NOTE: I’m not interested in cropping the image beforehand, so that’s not an option for me.