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()
{
auto 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#
-
template<typename TImage, typename TBoundaryCondition = ZeroFluxNeumannBoundaryCondition<TImage>>
class ShapedNeighborhoodIterator : public itk::ConstShapedNeighborhoodIterator<TImage, TBoundaryCondition> 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.. ... ShapedNeighborhoodIterator<ImageType>::Iterator i; for (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
Neighborhood
- 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.
- See
ImageConstIterator
- See
ConditionalConstIterator
- See
ConstNeighborhoodIterator
- See
ConstShapedNeighborhoodIterator
- See
ConstSliceIterator
- See
CorrespondenceDataStructureIterator
- See
FloodFilledFunctionConditionalConstIterator
- See
FloodFilledImageFunctionConditionalConstIterator
- See
FloodFilledImageFunctionConditionalIterator
- See
FloodFilledSpatialFunctionConditionalConstIterator
- See
FloodFilledSpatialFunctionConditionalIterator
- See
ImageConstIterator
- See
ImageConstIteratorWithIndex
- See
ImageIterator
- See
ImageIteratorWithIndex
- See
ImageLinearConstIteratorWithIndex
- See
ImageLinearIteratorWithIndex
- See
ImageRandomConstIteratorWithIndex
- See
ImageRandomIteratorWithIndex
- See
ImageRegionConstIterator
- See
ImageRegionConstIteratorWithIndex
- See
ImageRegionExclusionConstIteratorWithIndex
- See
ImageRegionExclusionIteratorWithIndex
- See
ImageRegionIterator
- See
ImageRegionIteratorWithIndex
- See
ImageRegionReverseConstIterator
- See
ImageRegionReverseIterator
- See
ImageReverseConstIterator
- See
ImageReverseIterator
- See
ImageSliceConstIteratorWithIndex
- See
ImageSliceIteratorWithIndex
- See
NeighborhoodIterator
- See
PathConstIterator
- See
PathIterator
- See
ShapedNeighborhoodIterator
- See
SliceIterator
- See
ImageConstIteratorWithIndex
- See
ShapedImageNeighborhoodRange
- ITK Sphinx Examples: