[Insight-users] Accumulate a dimension
Emiliano Beronich
emiliano at veccsa.com
Thu Oct 7 10:26:29 EDT 2004
Thanks James for your suggestion. Starting from
itkGetAverageSliceImageFilter, I have made a new filter that does what I
wanted. It was almost completely rewritten, that's why I called it with
a new name. I called itkAccumulateImageFilter because that is the main
idea: Each pixel is the cumulative sum of the pixels along the collapsed
dimension. The filter reduce the largest size of the accumulated
dimension to 1 (only on the accumulated). I have tested it and it's working.
I think it's not very difficult to modify the filter to accumulate more
than one dimension (i.e. reducing a 4D to a 2D Image). It isn't what I
need at the moment, so I'm fine with it.
I would be happy to contribute the code to the community of ITK. I think
this code could close the bug 1224, opened by myself.
Regards,
Emiliano
Miller, James V (Research) wrote:
> You might want to try the BasicFilters/itkGetAverageSliceImageFilter.h
>
> This filter isn't well documented, but I believe its intention is to take
> a ND image and output a (N-1)D image where each pixel is the average of the
> pixels along the collapsed dimension.
>
> I don't think this filter has been tested much. So if you have a problem
> please let us know and we'll try to fix it.
>
> Jim
>
>
-------------- next part --------------
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile: itkAccumulateImageFilter.h,v $
Language: C++
Date: $Date: 2004/10/06 12:00:00 $
Version: $Revision: 1.4 $
Copyright (c) Insight Software Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef __itkAccumulateImageFilter_h
#define __itkAccumulateImageFilter_h
#include "itkImageToImageFilter.h"
namespace itk
{
/** \class AccumulateImageFilter
* \brief Implements an accumulation of an image along a selected direction.
*
* This class accumulates an image along a dimension and reduce the size
* of this dimension to 1. The dimension being accumulated is set by
* AccumulatedDimension.
*
* Each pixel is the cumulative sum of the pixels along the collapsed
* dimension and reduce the size of the accumulated dimension to 1 (only
* on the accumulated).
*
* The dimensions of the InputImage and the OutputImage must be the same.
*
*
*
* This class is parameterized over the type of the input image and
* the type of the output image.
*
*
* \author Emiliano Beronich
* This filter was contributed by Emiliano Beronich
*
* \ingroup IntensityImageFilters Singlethreaded
*/
template <class TInputImage, class TOutputImage>
class ITK_EXPORT AccumulateImageFilter : public ImageToImageFilter<TInputImage,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef AccumulateImageFilter Self;
typedef ImageToImageFilter<TInputImage,TOutputImage> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(AccumulateImageFilter, ImageToImageFilter);
/** Some convenient typedefs. */
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputImagePointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointer;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
/** ImageDimension enumeration */
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputImage::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int,
TOutputImage::ImageDimension);
/** Set the direction in which to accumulate the data.
It must be set before the update of the filter.*/
itkGetMacro( AccumulatedDimension, unsigned int );
itkSetMacro( AccumulatedDimension, unsigned int );
/** Perform a division by the size of the accumulated dimension after the
accumulation is done. If true, the output image is the average of the accumulated
dimension, if false the output is the sum of the pixels along the selected direction.
The default value is false.**/
itkSetMacro( AverageOutput, bool );
itkGetMacro( AverageOutput, bool );
protected:
AccumulateImageFilter();
virtual ~AccumulateImageFilter() {};
void PrintSelf(std::ostream& os, Indent indent) const;
/** Apply changes to the output image information. */
virtual void GenerateOutputInformation();
/** Apply changes to the input image requested region. */
virtual void GenerateInputRequestedRegion();
/** This method implements the actual accumulation of the image.
*
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
void GenerateData(void);
private:
AccumulateImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
unsigned int m_AccumulatedDimension;
bool m_AverageOutput;
};
} // end namespace itk
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkAccumulateImageFilter.txx"
#endif
#endif
-------------- next part --------------
/*=========================================================================
Program: Insight Segmentation & Registration Toolkit
Module: $RCSfile: itkAccumulateImageFilter.txx,v $
Language: C++
Date: $Date: 2004/10/06 12:00:00 $
Version: $Revision: 1.6 $
Copyright (c) Insight Software Consortium. All rights reserved.
See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
#ifndef _itkAccumulateImageFilter_txx
#define _itkAccumulateImageFilter_txx
#include "itkAccumulateImageFilter.h"
#include "itkImageRegionIterator.h"
#include "itkImageRegionConstIterator.h"
namespace itk
{
/**
* Constructor
*/
template <class TInputImage, class TOutputImage >
AccumulateImageFilter<TInputImage,TOutputImage >
::AccumulateImageFilter()
{
this->SetNumberOfRequiredInputs( 1 );
m_AccumulatedDimension=-1;
m_AverageOutput = false;
}
template <class TInputImage, class TOutputImage>
void
AccumulateImageFilter<TInputImage,TOutputImage>
::GenerateOutputInformation()
{
itkDebugMacro("GenerateOutputInformation Start");
typename TOutputImage::RegionType outputRegion;
typename TInputImage::IndexType inputIndex;
typename TInputImage::SizeType inputSize;
typename TOutputImage::SizeType outputSize;
typename TOutputImage::IndexType outputIndex;
typename TInputImage::SpacingType inSpacing;
typename TInputImage::PointType inOrigin;
typename TOutputImage::SpacingType outSpacing;
typename TOutputImage::PointType outOrigin;
// Get pointers to the input and output
typename Superclass::OutputImagePointer output = this->GetOutput();
typename Superclass::InputImagePointer input = const_cast< TInputImage * >( this->GetInput() );
inputIndex = input->GetLargestPossibleRegion().GetIndex();
inputSize = input->GetLargestPossibleRegion().GetSize();
inSpacing = input->GetSpacing();
inOrigin = input->GetOrigin();
// Set the LargestPossibleRegion of the output.
// Reduce the size of the accumulated dimension.
for(int i = 0; i<InputImageDimension; i++) {
if (i != m_AccumulatedDimension) {
outputSize[i] = inputSize[i];
outputIndex[i] = inputIndex[i];
outSpacing[i] = inSpacing[i];
outOrigin[i] = inOrigin[i];
} else {
outputSize[i] = 1;
outputIndex[i] = 0;
outSpacing[i] = inSpacing[i]*inputSize[i];
outOrigin[i] = inOrigin[i] + (i-1)*inSpacing[i]/2;
}
}
outputRegion.SetSize(outputSize);
outputRegion.SetIndex(outputIndex);
output->SetOrigin(outOrigin);
output->SetSpacing(outSpacing);
output->SetLargestPossibleRegion(outputRegion);
itkDebugMacro("GenerateOutputInformation End");
}
template <class TInputImage, class TOutputImage>
void
AccumulateImageFilter<TInputImage,TOutputImage>
::GenerateInputRequestedRegion()
{
itkDebugMacro("GenerateInputRequestedRegion Start");
Superclass::GenerateInputRequestedRegion();
if ( this->GetInput() )
{
typename TInputImage::RegionType RequestedRegion;
typename TInputImage::SizeType inputSize;
typename TInputImage::IndexType inputIndex;
typename TInputImage::SizeType inputLargSize;
typename TInputImage::IndexType inputLargIndex;
typename TOutputImage::SizeType outputSize;
typename TOutputImage::IndexType outputIndex;
outputIndex = this->GetOutput()->GetRequestedRegion().GetIndex();
outputSize = this->GetOutput()->GetRequestedRegion().GetSize();
inputLargSize = this->GetInput()->GetLargestPossibleRegion().GetSize();
inputLargIndex = this->GetInput()->GetLargestPossibleRegion().GetIndex();
for(int i=0; i<TInputImage::ImageDimension; i++)
{
if(i!=m_AccumulatedDimension)
{
inputSize[i] = outputSize[i];
inputIndex[i] = outputIndex[i];
}
else
{
inputSize[i]=inputLargSize[i];
inputIndex[i]=inputLargIndex[i];
}
}
RequestedRegion.SetSize(inputSize);
RequestedRegion.SetIndex(inputIndex);
InputImagePointer input = const_cast< TInputImage * > ( this->GetInput() );
input->SetRequestedRegion (RequestedRegion);
}
itkDebugMacro("GenerateInputRequestedRegion End");
}
/**
* GenerateData Performs the accumulation
*/
template <class TInputImage, class TOutputImage >
void
AccumulateImageFilter<TInputImage,TOutputImage>
::GenerateData( void )
{
if(m_AccumulatedDimension<0 || m_AccumulatedDimension>=TInputImage::ImageDimension)
{
itkExceptionMacro(<<"AccumulateImageFilter: wrong Dimension to accumulate. Quitting!\n");
}
typename Superclass::InputImageConstPointer inputImage = this->GetInput();
typename TOutputImage::Pointer outputImage = this->GetOutput();
outputImage->SetBufferedRegion( outputImage->GetRequestedRegion() );
outputImage->Allocate();
// Accumulate over the Nth dimension ( = m_AccumulatedDimension)
// and divide by the size of the accumulated dimension.
typedef itk::ImageRegionIterator<TOutputImage> outputIterType;
outputIterType outputIter(outputImage, outputImage->GetBufferedRegion());
typedef itk::ImageRegionConstIterator<TInputImage> inputIterType;
TInputImage::RegionType AccumulatedRegion;
TInputImage::SizeType AccumulatedSize = inputImage->GetLargestPossibleRegion().GetSize();
TInputImage::IndexType AccumulatedIndex = inputImage->GetLargestPossibleRegion().GetIndex();
TOutputImage::PixelType SizeAccumulatedDimension = AccumulatedSize[m_AccumulatedDimension];
TOutputImage::PixelType IndexAccumulatedDimension = AccumulatedIndex[m_AccumulatedDimension];
for(int i=0; i< InputImageDimension; i++) {
if (i != m_AccumulatedDimension ) {
AccumulatedSize[i] = 1;
}
}
AccumulatedRegion.SetSize(AccumulatedSize);
outputIter.GoToBegin();
while(!outputIter.IsAtEnd())
{
TOutputImage::IndexType OutputIndex = outputIter.GetIndex();
for(int i=0; i<InputImageDimension; i++) {
if (i != m_AccumulatedDimension) {
AccumulatedIndex[i] = OutputIndex[i];
} else {
AccumulatedIndex[i] = IndexAccumulatedDimension;
}
}
AccumulatedRegion.SetIndex(AccumulatedIndex);
inputIterType inputIter(inputImage, AccumulatedRegion);
inputIter.GoToBegin();
TOutputImage::PixelType Value=0;
while(!inputIter.IsAtEnd())
{
Value+=inputIter.Get();
++inputIter;
}
outputIter.Set (Value);
++outputIter;
}
// Performs a division to get an averaged output
if (m_AverageOutput) {
outputIter.GoToBegin();
while(!outputIter.IsAtEnd())
{
outputIter.Set(outputIter.Get()/SizeAccumulatedDimension);
++outputIter;
}
}
}
template <class TInputImage, class TOutputImage >
void
AccumulateImageFilter<TInputImage,TOutputImage>::
PrintSelf(std::ostream& os, Indent indent) const
{
Superclass::PrintSelf(os,indent);
os << indent << "AccumulatedDimension: " << m_AccumulatedDimension << std::endl;
}
} // end namespace itk
#endif
More information about the Insight-users
mailing list