This document provides a general overview of the intended use of the NeighborhoodIterator classes and their associated objects for low-level image processing in Itk. For a more detailed description of the API, please refer to the inline Itk documentation and manual.
int nx = 512; int ny = 512; ImageType image(nx,ny); for(int x=1; x<nx-1; x++) { float sum = 0; for(int y=1; y<ny-1; y++) { sum += image(x-1,y-1) + image(x ,y-1) + image(x+1,y-1); sum += image(x-1,y ) + image(x ,y ) + image(x+1,y ); sum += image(x-1,y+1) + image(x ,y+1) + image(x+1,y+1); } }
itk::Image neighborhood iteration and dereferencing is encapsulated in the itk::NeighborhoodIterator classes. ITK NeighborhoodIterators allow for code that is closer to the algorithmic abstraction,
ForAllTheIndicies i in Image GetTheNeighbors n in a 3x3 region around i Compute the mean of all pixels n Write the value to the output at i
Here is how the pseudocode above can be rewritten in ITK using neighborhood iterators: ( In the code examples that follow, some template parameters may have been omitted for clarity. )
1 typedef itk::Image<float, 2> ImageType; 2 typedef itk::SmartNeighborhoodIterator<ImageType> NeighborhoodIterator; 3 typedef itk::ImageRegionIterator<ImageType> ImageIterator; 4 5 ImageType::Pointer input_image = GetImageSomehow(); 6 ImageType::Pointer output_image = GetImageSomehow(); 7 8 // A radius of 1 in all axial directions gives a 3x3x3x3x... neighborhood. 9 NeighborhoodIterator::RadiusType radius; 10 for (unsigned int i = 0; i < ImageType::ImageDimension; ++i) radius[i] = 1; 11 12 // Initializes the iterators on the input & output image regions 13 NeighborhoodIterator it(radius, input_image, 14 output_image->GetRequestedRegion()); 15 ImageIterator out(output_image, output_image->GetRequestedRegion()); 16 17 // Iterates over the input and output 18 for (it.SetToBegin(), out = out.Begin(); ! it.IsAtEnd(); ++it, ++out ) 19 { 20 float accum = 0.0; 21 for (unsigned int i = 0; i < it.Size(); ++i) 22 { 23 accum += it.GetPixel(i); 24 } 25 out.Set(accum/(float)(it.Size())); 26 }
1 typedef itk::Image<float, 5> ImageType;
NeighborhoodOperators are container classes for generating and storing computational kernels such as LaPlacian, Gaussian, derivative, and morphological operators. They provide a generalized interface for creation and access of the operator coefficients.
1 LaPlacianOperator<double, 3> OP;
2 ImageIterator out( outputImage, regionToProcess );
3 NeighborhoodIterator it ( OP.GetRadius(), inputImage, regionToProcess );
4 NeighborhoodInnerProduct IP;
5
6 out = out.Begin();
7 for (it.SetToBegin(); it != it.End(); ++it, ++out)
8 {
9 out.Set( IP( it, OP) );
10 }
1 NeighborhoodIterator::RadiusType radius = {1, 0, 0};
2 NeighborhoodIterator it(radius, inputImage, regionToProcess)
3 ImageRegionIterator out( outputImage, regionToProcess );
4 for (it.SetToBegin(); it != it.End(); ++it, ++out)
5 {
6 out.Set( it.GetPixel(3) - it.GetPixel(2) );
7 }
For any neighborhood operation, conditions at data set boundaries become important. SmartNeighborhoodIterator defines a special class of neighborhood iterators that transparently handle boundary conditions. These iterators store a boundary condition object that is used to calculate a value of requested pixel indicies that lie outside the data set boundary. New boundary condition objects can be defined by a user and plugged into SmartNeighboroodIterators as is appropriate for their algorithm.
typedef NeighborhoodAlgorithm::ImageBoundaryFacesCalculator RegionFinderType; LaPlacianOperator<double, InputImageType::ImageDimension> OP; RegionFinderType regionCalculator; RegionFinderType::FaceListType regions; RegionFinderType::FaceListType::iterator regions_iterator; regions = regionCalculator( inputImage, regionToProcess, it.GetRadius() ); regions_iterator = regions.begin(); ImageIterator out; // // Process non-boundary regions normally. // out = ImageIterator(outputImage, *regions_iterator); NeighborhoodIterator it (OP.GetRadius(), inputImage, *regions_iterator); NeighborhoodInnerProduct IP; out = out.Begin(); for (it.SetToBegin(); it != it.End(); ++it, ++out) { out.Set( IP( it, OP) ); } // // Process each boundary region with boundary conditions. // SmartNeighborhoodInnerProduct SIP; SmartNeighborhoodIterator sit; for (regions_iterator++ ; regions_iterator != regions.end(); regions_iterator++) { out = ImageIterator(outputImage, *regions_iterator); sit = SmartNeighborhoodIterator(OP.GetRadius(), inputImage, *regions_iterator); for (sit.SetToBegin(); sit != sit.End(); ++sit, ++out) { out.Set( SIP( sit, OP) ); } }
Many filters in Itk use the neighborhood iterators and operators. Some canonical examples of their use include the class of AnisotropicDiffusionFunctions and the morphological image filters. itk::WatershedSegmenter also makes extensive use of the neighborhood iterators.