[Insight-users] Streaming RegionOfInterest Shrink
Florian Pierron
F.Pierron at exeter.ac.uk
Fri May 16 05:39:40 EDT 2008
Hi Luis,
Sorry to bother you again :-) but just to finish with what I was doing:
I am using the following pipeline to crop and resample really really big
images on import as mentioned before:
MetaImageIO (with UseStreamedReadingOn) -> RegionOfInterestImageFilter
-> ShrinkImageFilter
Everything was streaming fine (only a small portion of the image was
loaded into memory) except after adding the ShrinkImageFilter. I can
understand that this filter needs the whole input to compute its output
as there is no easy way to tell the upstream filters that the requested
region is in fact a list of small unconnected regions (am I correct or
is there some ways to specify that? Maybe there is because some filters
support streaming...). Anyway, my idea to get around this was to plug in
the SreamingFilter at the end of the ShrinkImageFilter to request
smaller regions. So the pipeline is as follow:
MetaImageIO (with UseStreamedReadingOn) -> RegionOfInterestImageFilter
-> ShrinkImageFilter -> StreamingFilter
Unfortunately the result was similar: the ShrinkImageFilter requests the
whole input! After having a quick look at the code of the
ShrinkImageFilter, I came across this line:
******************************
ShrinkImageFilter<TInputImage,TOutputImage>
::EnlargeOutputRequestedRegion(DataObject *output)
{
// call the superclass' implementation of this method
Superclass::EnlargeOutputRequestedRegion(output);
output->SetRequestedRegionToLargestPossibleRegion(); --> Why setting
the requested region to largest possible region??
}
******************************
So commenting this line worked fine and the ShrinkImageFilter is now
requesting only a small portion of the input.
<Remark>
To optimize computation time and specially memory footprint I have added
the following lines to ShrinkImageFilter::GenerateInputRequestedRegion()
******************************
if (outputRequestedRegionSize[i] == 1)
{
inputRequestedRegionSize[i] = 1;
}
else
{
inputRequestedRegionSize[i]
= outputRequestedRegionSize[i] * (size_t)m_ShrinkFactors[i];
}
******************************
Is there a nicer way to do it? We are requesting much more data that we
actually need to specially when the ShrinkFactor is quite big (in
hundreds in my case). I saw that there are functions to split regions
and so on, so is there a way to define a list of requestedRegion or
something with a similar outcomes (stream at the pixel level)
<EndRemark>
But even after these modifications, the pipeline was still not working
and the whole image was loaded (trying to be loaded) into memory :-(. I
then had a look at the RegionOfInterestImageFilter and I realized that
this filter doesn't take into account the RequestedRegion!? So I
modified the following function as below:
******************************
template <class TInputImage, class TOutputImage>
void
RegionOfInterestImageFilter<TInputImage,TOutputImage>
::GenerateInputRequestedRegion()
{
// call the superclass' implementation of this method
Superclass::GenerateInputRequestedRegion();
// get pointer to the input
typename Superclass::InputImagePointer inputPtr =
const_cast< TInputImage * >( this->GetInput() );
OutputImagePointer outputPtr = this->GetOutput();
if ( !inputPtr || !outputPtr )
{
return;
}
// If the requested region is smaller / contained in m_RegionOfInterest
// then the inputRequestedRegion is cropped to match the requested region
// Otherwise (can this happen?) the inputRequestedRegion is
// NOT cropped and is equal to the m_RegionOfInterest
typename TInputImage::RegionType inputRequestedRegion(
m_RegionOfInterest );
inputRequestedRegion.Crop( outputPtr->GetRequestedRegion() );
inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() ); //
is this really needed?
inputPtr->SetRequestedRegion( inputRequestedRegion );
}
******************************
And in the same way than the ShrinkFilter, I have commented the
output->SetRequestedRegionToLargestPossibleRegion() in
RegionOfInterestImageFilter::EnlargeOutputRequestedRegion ().
I don't understand why the
output->SetRequestedRegionToLargestPossibleRegion() is there for the
ShrinkFilter and RegionOfInterestImageFilter. So if someone with
experience in developing ITK code can have a quick look and check that I
didn't break anything by removing this line, it would be really great!
Find attached the patch for the ShrinkFilter and
RegionOfInterestImageFilter. Let me know if you want me to enter this as
a feature request in the bug tracker
Regards,
Florian
-------- Original Message --------
Subject: Re: [Insight-users] MetaImage: absolute path in
ElementDataFile not working
Date: Tue, 13 May 2008 23:57:39 +0100
From: Florian Pierron <f.pierron at exeter.ac.uk>
To: Luis Ibanez <luis.ibanez at kitware.com>
CC: insight-users at itk.org
References: <48283AE6.3020203 at exeter.ac.uk>
<48284B0D.3010401 at kitware.com> <48296C66.8090809 at exeter.ac.uk>
<4829C215.9090808 at kitware.com> <482A0114.10802 at exeter.ac.uk>
<482A0D9A.6060802 at kitware.com>
Hi Luis,
Sorry for the misunderstanding: yes I was speaking about the
ElementDataFile field inside the .mhd / header file.
The thing is that I don't necessary have the write access on the folder
containing the raw image. That's the reason why I need an absolute path...
To give you the full picture of the problem, I need to read really
really really really big data (300 GB) and resample / crop them on
import. I tried to use the UseStreamedReadingOn on the RawImageIO and
UseStreamingOn on the ImageFileReader followed by a
RegionOfInterestImageFilter and ShrinkImageFilter. But I couldn't get
the streaming work on the RawImageIO. After reading some posts on the
mailing list, it seems that the MetaImageIO is the only streamable
reader. So I created a temporary .mhd file and the streaming seems to
work like a charm now :-). That is simply amazing, thanks for this good
piece of code!
Regards,
Florian
PS: I think the patch I provided to allow absolute path in the
ElementDataFile of an .mha file is quite useful for the reason mentioned
above. Moreover
if the ElementDataFile field is NOT an absolute path, it will work as
before and append the header path to the ElementDataFile. But if the
ElementDataFile field is an absolute path, it will NOT append the header
path. But at the end, you are the one who decides ;-)
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: Patch_ITK-3-4_RegionOfInterestFilter_ShrinkFilter
URL: <http://www.itk.org/pipermail/insight-users/attachments/20080516/604d6a4c/attachment.asc>
More information about the Insight-users
mailing list