Iterate Over A Region With A Shaped Neighborhood Iterator Manually

Synopsis

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

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"

// 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 ImageType = itk::Image<unsigned int, 2>;

void
CreateImage(ImageType::Pointer image);

int
main(int, char *[])
{
  ImageType::Pointer image = ImageType::New();
  CreateImage(image);

  using IteratorType = itk::ShapedNeighborhoodIterator<ImageType>;

  itk::Size<2> 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;
}

void
CreateImage(ImageType::Pointer image)
{
  ImageType::IndexType start;
  start.Fill(0);

  ImageType::SizeType size;
  size.Fill(10);

  ImageType::RegionType region(start, size);

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

Classes demonstrated