Iterate Over a Region With a Shaped Neighborhood Iterator#

Synopsis#

Iterate over a region of an image with a shaped neighborhood.

Results#

Output:

By default there are 0 active indices.
Now there are 2 active indices.
1 7
New position:
Centered at [0, 0]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [0, -1]
Centered at [0, 0]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [0, 1]
New position:
Centered at [1, 0]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [1, -1]
Centered at [1, 0]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [1, 1]
New position:
Centered at [2, 0]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [2, -1]
Centered at [2, 0]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [2, 1]

[...]

New position:
Centered at [7, 9]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [7, 8]
Centered at [7, 9]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [7, 10]
New position:
Centered at [8, 9]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [8, 8]
Centered at [8, 9]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [8, 10]
New position:
Centered at [9, 9]
Neighborhood index 1 is offset [0, -1] and has value 0 The real index is [9, 8]
Centered at [9, 9]
Neighborhood index 7 is offset [0, 1] and has value 0 The real index is [9, 10]

Code#

C++#

#include "itkImage.h"
#include "itkShapedNeighborhoodIterator.h"
#include "itkImageRegionIterator.h"
#include "itkNeighborhoodAlgorithm.h"

int
main()
{
  constexpr unsigned int Dimension = 2;

  // Notice that char type pixel values will not appear
  // properly on the command prompt therefore for the
  // demonstration purposes it is best to use the int
  // type, however in real applications iterators have
  // no problems with char type images.
  // using ImageType = itk::Image<unsigned char, 2>;
  using PixelType = unsigned int;

  using ImageType = itk::Image<PixelType, Dimension>;

  auto image = ImageType::New();

  ImageType::IndexType start{};

  auto size = ImageType::SizeType::Filled(10);

  ImageType::RegionType region(start, size);

  image->SetRegions(region);
  image->Allocate();
  image->FillBuffer(0);

  using IteratorType = itk::ShapedNeighborhoodIterator<ImageType>;
  IteratorType::RadiusType radius;
  radius.Fill(1);

  IteratorType iterator(radius, image, image->GetLargestPossibleRegion());
  std::cout << "By default there are " << iterator.GetActiveIndexListSize() << " active indices." << std::endl;

  IteratorType::OffsetType top = { { 0, -1 } };
  iterator.ActivateOffset(top);
  IteratorType::OffsetType bottom = { { 0, 1 } };
  iterator.ActivateOffset(bottom);

  std::cout << "Now there are " << iterator.GetActiveIndexListSize() << " active indices." << std::endl;

  IteratorType::IndexListType                 indexList = iterator.GetActiveIndexList();
  IteratorType::IndexListType::const_iterator listIterator = indexList.begin();
  while (listIterator != indexList.end())
  {
    std::cout << *listIterator << " ";
    ++listIterator;
  }
  std::cout << std::endl;

  // Note that ZeroFluxNeumannBoundaryCondition is used by default so even
  // pixels outside of the image will have valid values (equivalent to
  // their neighbors just inside the image)
  for (iterator.GoToBegin(); !iterator.IsAtEnd(); ++iterator)
  {
    std::cout << "New position: " << std::endl;
    IteratorType::ConstIterator ci = iterator.Begin();

    while (!ci.IsAtEnd())
    {
      std::cout << "Centered at " << iterator.GetIndex() << std::endl;
      std::cout << "Neighborhood index " << ci.GetNeighborhoodIndex() << " is offset " << ci.GetNeighborhoodOffset()
                << " and has value " << ci.Get() << " The real index is "
                << iterator.GetIndex() + ci.GetNeighborhoodOffset() << std::endl;
      ++ci;
    }
  }

  std::cout << std::endl;

  return EXIT_SUCCESS;
}

Classes demonstrated#

template<typename TImage, typename TBoundaryCondition = ZeroFluxNeumannBoundaryCondition<TImage>>
class ShapedNeighborhoodIterator : public itk::ConstShapedNeighborhoodIterator<TImage, ZeroFluxNeumannBoundaryCondition<TImage>>

A neighborhood iterator which can take on an arbitrary shape.

using ImageType = Image<float, 3>;
ShapedNeighborhoodIterator<ImageType> it(radius, image, region);
ShapedNeighborhoodIterator<ImageType>::OffsetType offset = {{0,0,0}};
it.ActivateOffset(offset);
General Information

The ShapedNeighborhoodIterator is a refinement of NeighborhoodIterator which allows the user to specify which of the neighborhood elements are active and which will be ignored. This is useful for applications which only need to work with a subset of the neighborhood around a pixel such as morphological operations or cellular automata. This iterator can also be used, for example, to specify “cross-shaped” neighborhood where only elements along a spatial axes are significant.

Constructing a shaped neighborhood iterator

A shaped neighborhood iterator is constructed by constructing a list of active neighbor locations. The list is called the ActiveIndexList. The methods ActivateOffset, DeactivateOffset, and ClearActiveList are used to construct the ActiveIndexList. The argument to Activate/DeactivateOffset is an itk::Offset which represents the ND spatial offset from the center of the neighborhood. For example, to activate the center pixel in the neighborhood, you would do the following:

where radius, image, and region are as described in NeighborhoodIterator.

Once a neighborhood location has been activated, iteration (operator++, operator–, operator+=, operator-=) will update the value at the active location. Note that values at inactive locations will NOT be valid if queried.

A second way to access active shaped neighborhood values is through a ShapedNeighborhoodIterator::Iterator or ConstShapedNeighborhoodIterator::ConstIterator. The following example demonstrates the use of these iterators.

Accessing elements in a shaped neighborhood.

To access the value at an active neighborhood location, you can use the standard GetPixel, SetPixel methods. SetPixel is not defined for ConstShapedNeighborhoodIterator. The class will not complain if you attempt to access a value at a non-active location, but be aware that the result will be undefined. Error checking is not done in this case for the sake of efficiency.

using ImageType = Image<float, 3>;
ShapedNeighborhoodIterator<ImageType> it(radius, image, region);
...
it.ActivateOffset(offset1);
it.ActivateOffset(offset2);
it.ActivateOffset(offset3);
// etc..
...
for (auto i = it.Begin(); ! i.IsAtEnd(); ++i)
{ i.Set(i.Get() + 1.0); }
// you may also use i != i.End(), but IsAtEnd() may be slightly faster.

You can also iterate backward through the neighborhood active list.

i = it.End();
--i;
while (i != it.Begin())
{
  i.Set(i.Get() + 1.0);
  --i;
}
 i.Set(i.Get() + 1.0);

The Get() Set() syntax was chosen versus defining operator* for these iterators because lvalue vs. rvalue context information is needed to determine whether bounds checking must take place.

See also

Neighborhood

See also

ImageConstIterator

See also

ConditionalConstIterator

See also

ConstNeighborhoodIterator

See also

ConstShapedNeighborhoodIterator

See also

ConstSliceIterator

See also

CorrespondenceDataStructureIterator

See also

FloodFilledFunctionConditionalConstIterator

See also

FloodFilledImageFunctionConditionalConstIterator

See also

FloodFilledImageFunctionConditionalIterator

See also

FloodFilledSpatialFunctionConditionalConstIterator

See also

FloodFilledSpatialFunctionConditionalIterator

See also

ImageConstIterator

See also

ImageConstIteratorWithIndex

See also

ImageIterator

See also

ImageIteratorWithIndex

See also

ImageLinearConstIteratorWithIndex

See also

ImageLinearIteratorWithIndex

See also

ImageRandomConstIteratorWithIndex

See also

ImageRandomIteratorWithIndex

See also

ImageRegionConstIterator

See also

ImageRegionConstIteratorWithIndex

See also

ImageRegionExclusionConstIteratorWithIndex

See also

ImageRegionExclusionIteratorWithIndex

See also

ImageRegionIterator

See also

ImageRegionIteratorWithIndex

See also

ImageRegionReverseConstIterator

See also

ImageRegionReverseIterator

See also

ImageReverseConstIterator

See also

ImageReverseIterator

See also

ImageSliceConstIteratorWithIndex

See also

ImageSliceIteratorWithIndex

See also

NeighborhoodIterator

See also

PathConstIterator

See also

PathIterator

See also

ShapedNeighborhoodIterator

See also

SliceIterator

See also

ImageConstIteratorWithIndex

See also

ShapedImageNeighborhoodRange

MORE INFORMATION

For a complete description of the ITK Image Iterators and their API, please see the Iterators chapter in the ITK Software Guide. The ITK Software Guide is available in print and as a free .pdf download from https://www.itk.org.

ITK Sphinx Examples:

See itk::ShapedNeighborhoodIterator for additional documentation.