[Insight-developers] itkImageSource - alternative implementation of
::AllocateOutputs()
Hauke Heibel
heibel at cs.tum.edu
Fri Oct 5 03:16:04 EDT 2007
Hi there,
I am working with algorithms that process data slice-wise, i.e. in chunks of
one dimension smaller than the actual volume. From what I have learned yet
from the mailing lists this happens to happen quite often and it is working
nicely.
The specific application I was working on was a slice viewer - in my special
case the slices were 2D images, but it can also be 3D volumes in case of 4D
data (3D + time). I wanted to execute the filter-pipeline as offered by ITK
via RequestedRegions on separate slices, since only the slice being
visualized needed to be processed. Everything was working nicely. The only
thing I was confused about in the beginning was the fact, that in the case I
was changing from slice i to slice i+1 or i-1, the computation restarted in
cases the slice was processed before.
After some time I recognized that this behavior was enforced by design so I
was trying to take a slightly deeper look into the pipeline. I found out
that the discrepancy between the Buffered- and RequestedRegion is causing
this behavior (ignoring the pipeline modification for a second). So I was
wondering if it is possible to not reallocate but enlarge the buffered
region in cases where a full slice (remember that it is equal to the input
volume decreased by one dimension) being adjacent to the existing
BufferedRegion is requested. Digging a bit deeper I found out, that this is
possible by overwriting the virtual function
ImageSource<TOutputImage>::AllocateOutputs(). Now I am curious whether the
special version of ::AllocateOutputs() I came up with can be used in general
and if it would hurt the pipeline in any way, i.e. I am asking if it is
possible without breaking the design to change
ImageSource<TOutputImage>::AllocateOutputs() to:
template <class TOutputImage> void
ImageSource<TOutputImage>::AllocateOutputs()
{
OutputImagePointer outputPtr;
// Allocate the output memory
for (unsigned int i=0; i < this->GetNumberOfOutputs(); i++)
{
outputPtr = this->GetOutput(i);
const RegionType& buff_region =
outputPtr->GetBufferedRegion();
const RegionType& req_region =
outputPtr->GetRequestedRegion();
// This should obviously always be the case
assert(!req_region.IsInside(buff_region));
assert(buff_region.ImageDimension-1 ==
req_region.ImageDimension-1);
// If the requested slice is adjacent to the
buffered slice(s) simply expand the region.
// It should also be a complete slice and
not just a sub-image within a slice.
if
(buff_region.Slice(buff_region.ImageDimension-1) ==
req_region.Slice(req_region.ImageDimension-1) &&
itk::AreRegionsAdjacent(buff_region,
req_region))
{
outputPtr->SetBufferedRegion(itk::GetEnclosingRegion(buff_region,
req_region));
}
else
{
// This is the standard
implementation.
outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
}
outputPtr->Allocate();
}
}
The methods itk::AreRegionsAdjacent and itk::GetEnclosingRegion are utility
functions I have written myself to make the code more readable (maybe they
could go into the class ImageRegion, right now I have them in an
itkImageRegionTools header as functions of the namespace itk).
I am looking forward to your opinions and the missing code will of course be
shared as soon as it is required.
Regards,
Hauke
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.itk.org/mailman/private/insight-developers/attachments/20071005/fa8bac53/attachment.html
More information about the Insight-developers
mailing list