/************************************************************************/ /* */ /* Copyright 1998-2002 by Ullrich Koethe */ /* Cognitive Systems Group, University of Hamburg, Germany */ /* */ /* This file is part of the VIGRA computer vision library. */ /* The VIGRA Website is */ /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* Please direct questions, bug reports, and contributions to */ /* koethe@informatik.uni-hamburg.de or */ /* vigra@kogs1.informatik.uni-hamburg.de */ /* */ /* Permission is hereby granted, free of charge, to any person */ /* obtaining a copy of this software and associated documentation */ /* files (the "Software"), to deal in the Software without */ /* restriction, including without limitation the rights to use, */ /* copy, modify, merge, publish, distribute, sublicense, and/or */ /* sell copies of the Software, and to permit persons to whom the */ /* Software is furnished to do so, subject to the following */ /* conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the */ /* Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* OTHER DEALINGS IN THE SOFTWARE. */ /* */ /************************************************************************/ #ifndef VIGRA_LOCALMINMAX_HXX #define VIGRA_LOCALMINMAX_HXX #include #include #include "vigra/utilities.hxx" #include "vigra/stdimage.hxx" #include "vigra/initimage.hxx" #include "vigra/labelimage.hxx" #include "vigra/pixelneighborhood.hxx" namespace vigra { /** \addtogroup LocalMinMax Local Minima and Maxima Detect local minima and maxima of the gray level, including extremal plateaus larger than 1 pixel */ //@{ namespace detail { template void localMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood, Compare compare) { int w = slr.x - sul.x - 2; int h = slr.y - sul.y - 2; int i,x,y; sul += Diff2D(1,1); dul += Diff2D(1,1); for(y=0; y sc(sx); for(i = 0; i < Neighborhood::DirectionCount; ++i, ++sc) { if(!compare(v, sa(sc))) break; } if(i == Neighborhood::DirectionCount) da.set(marker, dx); } } } } // namespace detail /********************************************************/ /* */ /* localMinima */ /* */ /********************************************************/ /** \brief Find local minima in an image. The minima are found only when the have a size of one pixel. Use \ref extendedLocalMinima() to find minimal plateaus. Minima are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be less-comparable. A pixel at the image border will never be marked as minimum. Pass \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode to determine the neighborhood where pixel values are compared. The function uses accessors. Declarations: pass arguments explicitly: \code namespace vigra { template void localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode()) } \endcode use argument objects in conjunction with \ref ArgumentObjectFactories: \code namespace vigra { template void localMinima(triple src, pair dest, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode()) } \endcode Usage: \#include "vigra/localminmax.hxx"
Namespace: vigra \code vigra::BImage src(w,h), minima(w,h); // init destiniation image minima = 0; vigra::localMinima(srcImageRange(src), destImage(minima)); \endcode Required Interface: \code SrcImageIterator src_upperleft, src_lowerright; DestImageIterator dest_upperleft; SrcAccessor src_accessor; DestAccessor dest_accessor; SrcAccessor::value_type u = src_accessor(src_upperleft); u < u DestValue marker; dest_accessor.set(marker, dest_upperleft); \endcode */ template inline void localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood) { detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood, std::less()); } template inline void localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker) { localMinima(sul, slr, sa, dul, da, marker, EightNeighborCode()); } template inline void localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da) { localMinima(sul, slr, sa, dul, da, NumericTraits::one(), EightNeighborCode()); } template inline void localMinima(triple src, pair dest, DestValue marker, Neighborhood neighborhood) { localMinima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood); } template inline void localMinima(triple src, pair dest, DestValue marker) { localMinima(src.first, src.second, src.third, dest.first, dest.second, marker, EightNeighborCode()); } template inline void localMinima(triple src, pair dest) { localMinima(src.first, src.second, src.third, dest.first, dest.second, NumericTraits::one(), EightNeighborCode()); } /********************************************************/ /* */ /* localMaxima */ /* */ /********************************************************/ /** \brief Find local maxima in an image. The maxima are found only when the have a size of one pixel. Use \ref extendedLocalMaxima() to find maximal plateaus. Maxima are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be less-comparable. A pixel at the image border will never be marked as maximum. The function uses accessors. Declarations: pass arguments explicitly: \code namespace vigra { template void localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode()) } \endcode use argument objects in conjunction with \ref ArgumentObjectFactories: \code namespace vigra { template void localMaxima(triple src, pair dest, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode()) } \endcode Usage: \#include "vigra/localminmax.hxx"
Namespace: vigra \code vigra::BImage src(w,h), maxima(w,h); // init destiniation image maxima = 0; vigra::localMaxima(srcImageRange(src), destImage(maxima)); \endcode Required Interface: \code SrcImageIterator src_upperleft, src_lowerright; DestImageIterator dest_upperleft; SrcAccessor src_accessor; DestAccessor dest_accessor; SrcAccessor::value_type u = src_accessor(src_upperleft); u < u DestValue marker; dest_accessor.set(marker, dest_upperleft); \endcode */ template inline void localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood) { detail::localMinMax(sul, slr, sa, dul, da, marker, neighborhood, std::greater()); } template inline void localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker) { localMaxima(sul, slr, sa, dul, da, marker, EightNeighborCode()); } template inline void localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da) { localMaxima(sul, slr, sa, dul, da, NumericTraits::one(), EightNeighborCode()); } template inline void localMaxima(triple src, pair dest, DestValue marker, Neighborhood neighborhood) { localMaxima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood); } template inline void localMaxima(triple src, pair dest, DestValue marker) { localMaxima(src.first, src.second, src.third, dest.first, dest.second, marker, EightNeighborCode()); } template inline void localMaxima(triple src, pair dest) { localMaxima(src.first, src.second, src.third, dest.first, dest.second, NumericTraits::one(), EightNeighborCode()); } namespace detail { template void extendedLocalMinMax(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood, Compare compare, Equal equal) { typedef typename SrcAccessor::value_type SrcType; int w = slr.x - sul.x; int h = slr.y - sul.y; int i,x,y; BasicImage labels(w,h); int number_of_regions = labelImage(sul, slr, sa, labels.upperLeft(), labels.accessor(), (Neighborhood::DirectionCount == 8), equal); // assume that a region is a extremum until the opposite is proved std::vector isExtremum(number_of_regions+1, (unsigned char)1); BasicImage::traverser ly = labels.upperLeft(); for(y=0; y::traverser lx(ly); for(x=0; x sc(sx); NeighborhoodCirculator::traverser, Neighborhood> lc(lx); for(i=0; i::Iterator lx(ly); for(x=0; xEqualityFunctor with tolerance, one can allow for plateaus that are not quite constant (this is often necessary with float pixel values). Pass \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode to determine the neighborhood where pixel values are compared. Minimal regions are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be equality-comparable and less-comparable. A pixel or region touching the image border will never be marked as minimum or minimal plateau. The function uses accessors. Declarations: pass arguments explicitly: \code namespace vigra { template > void extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode(), EqualityFunctor equal = EqualityFunctor()) } \endcode use argument objects in conjunction with \ref ArgumentObjectFactories: \code namespace vigra { template > void extendedLocalMinima(triple src, pair dest, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode(), EqualityFunctor equal = EqualityFunctor()) } \endcode Usage: \#include "vigra/localminmax.hxx"
Namespace: vigra \code // optional: define an equality functor template struct EqualWithToleranceFunctor { EqualWithToleranceFunctor(T tolerance) : t(tolerance) {} bool operator()(T l, T r) const { return vigra::abs(l-r) <= t; } T t; }; vigra::BImage src(w,h), minima(w,h); // init destiniation image minima.init(0); vigra::extendedLocalMinima(srcImageRange(src), destImage(minima)); // allow plateaus with tolerance minima.init(0); vigra::extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0, EqualWithToleranceFunctor(1)); \endcode Required Interface: \code SrcImageIterator src_upperleft, src_lowerright; DestImageIterator dest_upperleft; SrcAccessor src_accessor; DestAccessor dest_accessor; SrcAccessor::value_type u = src_accessor(src_upperleft); EqualityFunctor equal; u == u equal(u, u); u < u DestValue marker; dest_accessor.set(marker, dest_upperleft); \endcode */ template inline void extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood, EqualityFunctor equal) { typedef typename SrcAccessor::value_type SrcType; detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, neighborhood, std::less(), equal); } template inline void extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood) { typedef typename SrcAccessor::value_type SrcType; extendedLocalMinima(sul, slr, sa, dul, da, marker, neighborhood, std::equal_to()); } template inline void extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker) { typedef typename SrcAccessor::value_type SrcType; extendedLocalMinima(sul, slr, sa, dul, da, marker, EightNeighborCode()); } template inline void extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da) { extendedLocalMinima(sul, slr, sa, dul, da, NumericTraits::one()); } template inline void extendedLocalMinima(triple src, pair dest, DestValue marker, Neighborhood neighborhood, EqualityFunctor equal) { extendedLocalMinima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood, equal); } template inline void extendedLocalMinima(triple src, pair dest, DestValue marker, Neighborhood neighborhood) { extendedLocalMinima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood); } template inline void extendedLocalMinima(triple src, pair dest, DestValue marker) { extendedLocalMinima(src.first, src.second, src.third, dest.first, dest.second, marker); } template inline void extendedLocalMinima(triple src, pair dest) { extendedLocalMinima(src.first, src.second, src.third, dest.first, dest.second); } /********************************************************/ /* */ /* extendedLocalMaxima */ /* */ /********************************************************/ /** \brief Find local maximal regions in an image. This function finds regions of uniform pixel value whose neighboring regions are all have smaller values (maximal plateaus of arbitrary size). By default, the pixels in a plateau have exactly identical values. By passing an EqualityFunctor with tolerance, one can allow for plateaus that are not quite constant (this is often necessary with float pixel values). Pass \ref vigra::EightNeighborCode or \ref vigra::FourNeighborCode to determine the neighborhood where pixel values are compared. Maximal regions are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be equality-comparable and less-comparable. A pixel or region touching the image border will never be marked as maximum or maximal plateau. The function uses accessors. Declarations: pass arguments explicitly: \code namespace vigra { template > void extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode(), EqualityFunctor equal = EqualityFunctor()) } \endcode use argument objects in conjunction with \ref ArgumentObjectFactories: \code namespace vigra { template > void extendedLocalMaxima(triple src, pair dest, DestValue marker = NumericTraits::one(), Neighborhood neighborhood = EightNeighborCode(), EqualityFunctor equal = EqualityFunctor()) } \endcode Usage: \#include "vigra/localminmax.hxx"
Namespace: vigra \code // optional: define an equality functor template struct EqualWithToleranceFunctor { EqualWithToleranceFunctor(T tolerance) : t(tolerance) {} bool operator()(T l, T r) const { return vigra::abs(l-r) <= t; } T t; }; vigra::BImage src(w,h), maxima(w,h); // init destiniation image maxima.init(0); vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima)); // allow plateaus with tolerance maxima.init(0); vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0, EqualWithToleranceFunctor(1)); \endcode Required Interface: \code SrcImageIterator src_upperleft, src_lowerright; DestImageIterator dest_upperleft; SrcAccessor src_accessor; DestAccessor dest_accessor; SrcAccessor::value_type u = src_accessor(src_upperleft); EqualityFunctor equal; u == u equal(u, u); u < u DestValue marker; dest_accessor.set(marker, dest_upperleft); \endcode */ template inline void extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood, EqualityFunctor equal) { typedef typename SrcAccessor::value_type SrcType; detail::extendedLocalMinMax(sul, slr, sa, dul, da, marker, neighborhood, std::greater(), equal); } template inline void extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker, Neighborhood neighborhood) { typedef typename SrcAccessor::value_type SrcType; extendedLocalMaxima(sul, slr, sa, dul, da, marker, neighborhood, std::equal_to()); } template inline void extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da, DestValue marker) { typedef typename SrcAccessor::value_type SrcType; extendedLocalMaxima(sul, slr, sa, dul, da, marker, EightNeighborCode()); } template inline void extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa, DestIterator dul, DestAccessor da) { extendedLocalMaxima(sul, slr, sa, dul, da, NumericTraits::one()); } template inline void extendedLocalMaxima(triple src, pair dest, DestValue marker, Neighborhood neighborhood, EqualityFunctor equal) { extendedLocalMaxima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood, equal); } template inline void extendedLocalMaxima(triple src, pair dest, DestValue marker, Neighborhood neighborhood) { extendedLocalMaxima(src.first, src.second, src.third, dest.first, dest.second, marker, neighborhood); } template inline void extendedLocalMaxima(triple src, pair dest, DestValue marker) { extendedLocalMaxima(src.first, src.second, src.third, dest.first, dest.second, marker); } template inline void extendedLocalMaxima(triple src, pair dest) { extendedLocalMaxima(src.first, src.second, src.third, dest.first, dest.second); } //@} } // namespace vigra #endif // VIGRA_LOCALMINMAX_HXX