[Insight-users] Submission: NaryMaximumImageFilter

Zachary Pincus zpincus@stanford.edu
Sun May 16 10:59:59 EDT 2004


--Apple-Mail-2--979782696
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Hello,

Here's a simple image filter that calculates the maximum of a set of 
several images. This is sometimes useful.

Also the amazingly small amount of code I had to write for this is a 
testament to the good design decisions (and hard work) of the ITK 
folks, what with the simple and logical functor classes and functor 
image filters.

One question, if I may: what are the semantics of an InPlaceImageFilter 
that takes multiple input images? Which input is overwritten? (I assume 
input 0...)

Thanks,

Zach Pincus

Department of Biochemistry and Program in Biomedical Informatics
Stanford University School of Medicine


--Apple-Mail-2--979782696
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name="itkNaryMaximumImageFilter.h"
Content-Disposition: attachment;
	filename=itkNaryMaximumImageFilter.h

#ifndef __itkNaryMaximumImageFilter_h
#define __itkNaryMaximumImageFilter_h

#include "itkNaryFunctorImageFilter.h"
#include "itkNumericTraits.h"


namespace itk
{
  
/** \class NaryMaximumImageFilter
 * \brief Implements an operator computing the pixel-wise maximum of several images.
 *
 * This class is parametrized over the types of the input images and the type of
 * the output image. 
 * Numeric conversions (castings) are done by the C++ defaults.
 *
 * The pixel type of the output images must have a valid defintion of
 * the operator<. This condition is required because internally this filter will
 * perform an operation similar to:
 *
 *		const OutputPixelType query_value = static_cast<OutputPixelType>(pixel_from_input_n);
 *		if(current_maximum < query_value)
 *			{
 *			current_maximum = query_value; 
 *			}
 * (where current_maximum is also of type OutputPixelType)
 * 
 * for each of the n input images.
 * 
 * For example, this filter could be used directly to find a "maximum projection"
 * of a series of images, often used in preliminary analysis of time-series data.
 * \ingroup IntensityImageFilters  Multithreaded
 */

namespace Functor {  
  
template< class TInput, class TOutput >
class Maximum1
{
public:
  typedef typename NumericTraits< TOutput >::ValueType OutputValueType; 
  // not sure if this typedef really makes things more clear... could just use TOutput?
  
  Maximum1() {}
  ~Maximum1() {}
  inline TOutput operator()( const TOutput & A, const TInput & B)
  {
	  const OutputValueType queryValue = static_cast<OutputValueType>(B);
    if(A < queryValue)
	  {
      return queryValue; 
	  }
	else
	  {
	  return A;
	  }
  }
  
  bool operator != (const Maximum1&) const
  {
    return false;
  }
};

}
template <class TInputImage, class TOutputImage>
class ITK_EXPORT NaryMaximumImageFilter :
    public
NaryFunctorImageFilter<TInputImage,TOutputImage, 
                       Functor::Maximum1<  typename TInputImage::PixelType, 
                                       typename TOutputImage::PixelType>   >
{
public:
  /** Standard class typedefs. */
  typedef NaryMaximumImageFilter  Self;
  typedef NaryFunctorImageFilter<TInputImage,TOutputImage, 
                                 Functor::Maximum1< typename TInputImage::PixelType, 
                                                typename TOutputImage::PixelType> >  Superclass;
  typedef SmartPointer<Self>   Pointer;
  typedef SmartPointer<const Self>  ConstPointer;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);
  
protected:
  NaryMaximumImageFilter() {}
  virtual ~NaryMaximumImageFilter() {}

private:
  NaryMaximumImageFilter(const Self&); //purposely not implemented
  void operator=(const Self&); //purposely not implemented

};

} // end namespace itk


#endif

--Apple-Mail-2--979782696
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="itkNaryMaximumImageFilterTest.cxx"
Content-Disposition: attachment;
	filename=itkNaryMaximumImageFilterTest.cxx

#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <itkImage.h>
#include <itkNaryMaximumImageFilter.h>
#include <itkImageRegionIteratorWithIndex.h>
#include <iostream>



// Define the dimension of the images
const unsigned int myDimension = 3;

// Declare the types of the images
typedef itk::Image<float, myDimension>  myInputImageType;
typedef itk::Image<float, myDimension>  myOutputImageType;

// Declare the type of the index to access images
typedef itk::Index<myDimension>         myIndexType;

// Declare the type of the size 
typedef itk::Size<myDimension>          mySizeType;

// Declare the type of the Region
typedef itk::ImageRegion<myDimension>        myRegionType;

// Declare the type of the Iterators
typedef itk::ImageRegionIteratorWithIndex<myInputImageType>  myInImageIteratorType;
typedef itk::ImageRegionIteratorWithIndex<myOutputImageType> myOutImageIteratorType;

// Declare the type for the ADD filter
typedef itk::NaryMaximumImageFilter<
                              myInputImageType,
                              myOutputImageType  >  myFilterType;
 



// Function for image initialization
void InitializeImage( myInputImageType * image, double value   )
{

  myInputImageType::Pointer inputImage( image );

  // Define their size, and start index
  mySizeType size;
  size[0] = 2;
  size[1] = 2;
  size[2] = 2;

  myIndexType start;
  start.Fill(0);

  myRegionType region;
  region.SetIndex( start );
  region.SetSize( size );
  
  inputImage->SetLargestPossibleRegion( region );
  inputImage->SetBufferedRegion( region );
  inputImage->SetRequestedRegion( region );
  inputImage->Allocate();

  myInImageIteratorType it( inputImage, 
                     inputImage->GetRequestedRegion() );
  
  it.GoToBegin();
  while( !it.IsAtEnd() ) 
    {
    it.Set( value );
    ++it;
    }


}



// Function for image printing
void PrintImage( myInputImageType * image, const char *)
{
  // Create an iterator for going through the image
  myInImageIteratorType it( image, 
                          image->GetRequestedRegion() );
  
  it.GoToBegin();
  //  Print the content of the image
  //std::cout << text << std::endl;
  while( !it.IsAtEnd() ) 
  {
    std::cout << it.Get() << std::endl;
    ++it;
  }

}






int main(int, char *[]) //itkNaryAddImageFilterTest(int, char* [] ) 
{

  // Create two images
  myInputImageType::Pointer inputImageA  = myInputImageType::New();
  myInputImageType::Pointer inputImageB  = myInputImageType::New();
  
  static const int minValue = 12;
  static const int maxValue = 13;
  InitializeImage( inputImageA, minValue );
  InitializeImage( inputImageB, maxValue );

  PrintImage( inputImageA, "Input image A" ); 
  PrintImage( inputImageB, "Input image B" ); 

  // Create an ADD Filter                                
  myFilterType::Pointer filter = myFilterType::New();


  // Connect the input images
  filter->SetInput( 0, inputImageA ); 
  filter->SetInput( 1, inputImageB );

  // Get the Smart Pointer to the Filter Output 
  myOutputImageType::Pointer outputImage = filter->GetOutput();

  
  // Execute the filter
  filter->Update();

  PrintImage( outputImage, "Resulting image 1" ); 

  myOutImageIteratorType it( outputImage, 
						  outputImage->GetRequestedRegion() );
  it.GoToBegin();
  while( !it.IsAtEnd() ) 
  {
	  if (it.Get() != maxValue)
	    {
	    std::cerr << "Test Failed!" << std::endl;
		  return -1;
	    }
	  ++it;
  }
  
  // now try it the other way
  InitializeImage( inputImageA, minValue );
  InitializeImage( inputImageB, maxValue );
  filter->SetInput( 1, inputImageA ); 
  filter->SetInput( 0, inputImageB );
  filter->InPlaceOff(); // let's make sure this works too, while we're at it...
  filter->Update();
  
  PrintImage( outputImage, "Resulting image 2" ); 
  
  myOutImageIteratorType it2( outputImage, 
							 outputImage->GetRequestedRegion() );
  it2.GoToBegin();
  while( !it2.IsAtEnd() ) 
  {
	  if (it2.Get() != maxValue)
	  {
		  std::cerr << "Test Failed!" << std::endl;
		  return -1;
	  }
	  ++it2;
  }
  
  std::cerr << "Test Passed!" << std::endl;
  // All objects should be automatically destroyed at this point
  return 0;

}





--Apple-Mail-2--979782696--




More information about the Insight-users mailing list