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.