[Insight-developers] Re: [Insight-users] One error and one is
sue with itkImagePCAShapeModelEstimator
Miller, James V (Research)
millerjv at crd.ge.com
Mon, 17 May 2004 09:48:23 -0400
Zachary,
The RequestedRegion is what filters need to operate on. The pipeline
(and filters) are designed so that the RequestedRegion should always
be a subset of the BufferedRegion. Since your GenerateInputRequestedRegion
sets the RequestedRegion to the LargestPossibleRegion, it
should be safe to use the RequestedRegion (and not the BufferedRegion
in the CalculateInnerProducts).
What your estimator needs is for the calculation of the PCA to occur
over regions of the inputs that are the same size. This means the
GenerateInputRequestedRegion method needs to guarentee the inputs have
the same RequestedRegion size.
Currently, you are driving this from the "first" input. This is a
reasonable choice. Another option is to scan all the inputs to find the
smallest input and make that the master. Then it becomes a question of
how to how to change the start indices if you end up changing the size.
The cleanest thing to do, however, is to probably drive this off an
output requested region. The outputs should be images so this seems
reasonable. The input RequestedRegions are then just copies of "an"
output RequestedRegion. I think the default pipeline implementations
should handle this appropriately (meaning the filter probably does not
need a GenerateInputRequestedRegion method or an
EnlargeOutputRequestedRegion
method). The PCA decomposition will be on whatever RequestedRegion
is asked for on output. If someone calls UpdateLargestPossibleRegion()
on the estimator, then the PCA decomposition will be over the entire image.
This will displace the complexity to the user. Where they will use a
series of ExtractImageFilters, RegionOfInterestImageFilters, and
ChangeInformationFilters to get all the inputs a consistent size... If
we do not displace the complexity to the user, then the filter needs
to know which portions of each input to use in the PCA. For instance,
lets say I have a number of images, each having a small object that
I want to model. In medical image analysis, it is rare that the object
of interest will appear at the same spot in each image. Therefore, I would
expect to have to align and crop a block around the object to send it to the
PCA.
Adding this complexity to the PCA filter seems unnecessary. The PCA filter
should probably just check the inputs are the same size.
Jim
-----Original Message-----
From: Zachary Pincus [mailto:zpincus at stanford.edu]
Sent: Sunday, May 16, 2004 7:02 AM
To: Luis Ibanez; insight-developers at itk.org
Subject: [Insight-developers] Re: [Insight-users] One error and one
issue with itkImagePCAShapeModelEstimator
> 1) It seems reasonable to allow the ImagePCAShapeModelEstimator
> to accept images of different origin, different StartIndex
> and only enforce the pixel spacing and the image size (in
> pixel along every dimension) to be the same among all the
> input images.
>
> Please send us a patch...
I've included a new implementation of the GenerateInputRequestedRegion
method of itkPCAShapeModelEstimatorClass so images with regions with
different indices, but the same size (and spacing) can work.
Now, the original behavior (which I did not change) is to set all input
requested regions to the largest possible region, and claim to use
that. However, elsewhere in the code (CalculateInnerProducts), the
buffered region of the inputs is what is actually used...
Perhaps it would be better if this were all done with the requested
region? If the user bothered to set them, why blow them away? Or would
that break too much code that relies on not having to set a requested
region?
Anhyow, the diff is pretty messy since this is basically a different
function, so I've just pasted in the new function.
Also attached is a modified test case that exercises this new
functionality, and diffs to the old test.
Zach Pincus
Department of Biochemistry and Program in Biomedical Informatics
Stanford University School of Medicine
New GenerateInputRequestedRegion:
/**
* Requires all of the inputs to have a LargestPosibleRegion and
Spacing the of
* same size.
*/
template<class TInputImage, class TOutputImage>
void
ImagePCAShapeModelEstimator<TInputImage,TOutputImage>
::GenerateInputRequestedRegion()
{
Superclass::GenerateInputRequestedRegion();
// Calling this causes problems because it sets the input requested
regions
// to various output requested regions, which might not overlap,
since the inputs
// and outputs aren't very closely linked in the PCA case.
// If we REALLY want to call this, then some heroics are necessary to
undo
// the damage it does. Specifically, we will have to set all the
inputs'
// requested regions back to *their* LargestPossibleRegion, and not
that of
// some random output.
if ( this->GetInput(0) )
{
// Get the requested region and spacing of the first input
this->GetInput(0)->SetRequestedRegionToLargestPossibleRegion();
typename TInputImage::RegionType masterRequestedRegion =
this->GetInput(0)->GetRequestedRegion();
typename TInputImage::SpacingType masterSpacing =
this->GetInput(0)->GetSpacing();
// Set the requested region of the remaining input to their largest
possible
// regions, and make sure the sizes and spacings are proper.
unsigned int idx;
for (idx = 1; idx < this->GetNumberOfInputs(); ++idx)
{
if ( this->GetInput(idx) )
{
this->GetInput(idx)->SetRequestedRegionToLargestPossibleRegion();
typename TInputImage::RegionType requestedRegion =
this->GetInput(idx)->GetRequestedRegion();
typename TInputImage::SpacingType spacing =
this->GetInput(0)->GetSpacing();
if( masterRequestedRegion.GetSize() !=
requestedRegion.GetSize() ||
masterSpacing != spacing)
{
itkExceptionMacro("Size and spacing of input " << idx <<
" is not the same as that of input 0" );
}
} // if ( this->GetIntput(idx))
} // for idx
} // if( this->GetInput(0) )
}
Diffs for new and old test code
(itkImagePCAShapeModelEstimatorTest.cxx):
< Old
> New
83c83
< InputImageType::IndexType index;
---
> InputImageType::IndexType index, index2;
85c85,87
< InputImageType::RegionType region;
---
> index2.Fill(4);
>
> InputImageType::RegionType region, region2;
89a92,94
> region2.SetSize( inputImageSize );
> region2.SetIndex( index2 );
>
105,106c110,111
< image2->SetLargestPossibleRegion( region );
< image2->SetBufferedRegion( region );
---
> image2->SetLargestPossibleRegion( region2 );
> image2->SetBufferedRegion( region2 );