Request for Changes-22: Add Masked Iterator Decorator

From OTBWiki
Jump to: navigation, search

Status

Summary

This RFC adds a new decorator class to adapt an existing iterator to ignore masked pixels.

Rationale

Using an iterator over an image region associated with a mask (no-data for example) requires manually avoiding masked pixels during the for loop. The new otbMaskedIteratorDecorator provides a generic iterator that combines two iterators. One over the image and another over the mask. The iteration interface methods are wrapped to skip over masked pixels. This approach allows using masks with most iterators without creating a masked version for each.

Implementation details

Classes and files

A       Modules/Filtering/ImageManipulation/include/otbMaskedIteratorDecorator.h
A       Modules/Filtering/ImageManipulation/include/otbMaskedIteratorDecorator.hxx
M       Modules/Filtering/ImageManipulation/test/CMakeLists.txt
M       Modules/Filtering/ImageManipulation/test/otbImageManipulationTestDriver.cxx
A       Modules/Filtering/ImageManipulation/test/otbMaskedIteratorDecorator.cxx
Default Constructor arguments

Constructor arguments are:

  • pointer to the image
  • pointer to the mask (can be null if no mask)
  • an image region

The class otb::MaskedIteratorDecorator is templated over the image iterator type and the mask iterator type :

template <typename TIterator, typename TMaskIterator = TIterator > class MaskedIteratorDecorator {...};

Type for mask and image in the constructor are derived from the class iterator types :

TIterator::ImageType
TMaskIterator::ImageType

Iterators needing other argument that (image,region) will need a specialization of this class.

If mask and image have different largest possible regions, an exception is thrown in the constructor.

isAtBegin implementation

Because the first pixel of the original iteration region might be masked, the "begin" location has to be computed. This is done in the private method ComputeMaskedBegin(), called in the constructor. Of course, this means that the new iterator will be in an invalid state before GoToBegin() is called. This seems to be the case with other iterators also.

Open ended iterator API

The ITK iterator API is open ended, meaning the decorator cannot wrap and forward all possible methods. Therefore the GetImageIterator() and GetMaskIterator() methods are also provided.

Applications

No application changes.

Tests

Tests are added for the new iterator with different decorated types.

The following filters are tested and compatible:

itk::ImageRegionIterator
itk::ImageRegionConstIterator

The following iterators may not be compatible due to the singleton MersenneTwister used to perform random jumps.

itk::ImageRandomConstIteratorWithIndex
itk::ImageRandomIteratorWithIndex
itk::ImageRandomNonRepeatingConstIteratorWithIndex
itk::ImageRandomNonRepeatingIteratorWithIndex

The following iterator has a buggy GoToEnd();

otb::SubsampledImageRegionIterator

The following iterators have a different iteration mechanism :

itk::ImageScanlineIterator
itk::ImageScanlineConstIterator

The following are not tested but probably compatible:

itk::PathIterator
itk::NeighborhoodIterator
itk::DataObjectIterator
itk::LineIterator
itk::SliceIterator

The following are not compatible (for details see Modules/Filtering/ImageManipulation/test/otbMaskedIteratorDecorator.cxx):

itk::ImageLinearIteratorWithIndex
itk::ReflectiveImageRegionIterator
itk::ImageRegionExclusionConstIteratorWithIndex
itk::ImageRegionIteratorWithIndex
itk::ImageRegionReverseIterator
otb::PolyLineImageIterator
itk::ImageRandomConstIteratorWithOnlyIndex

Documentation

Doxygen comments are included.

Additional notes

Full diff: [[1]]

This RFC is part of Request_for_Comments-20:_New_sampling_module_for_the_classification_framework.

Future improvements should focus on the itk::ScanlineIterator as it is an optimized iterator advised by ITK.