Files
tenmon/3rdparty/include/pcl/MorphologicalOperator.h
T
2022-04-12 08:17:18 +02:00

1238 lines
47 KiB
C++

// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/MorphologicalOperator.h - Released 2022-03-12T18:59:29Z
// ----------------------------------------------------------------------------
// This file is part of the PixInsight Class Library (PCL).
// PCL is a multiplatform C++ framework for development of PixInsight modules.
//
// Copyright (c) 2003-2022 Pleiades Astrophoto S.L. All Rights Reserved.
//
// Redistribution and use in both source and binary forms, with or without
// modification, is permitted provided that the following conditions are met:
//
// 1. All redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. All redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
// of their contributors, may be used to endorse or promote products derived
// from this software without specific prior written permission. For written
// permission, please contact info@pixinsight.com.
//
// 4. All products derived from this software, in any form whatsoever, must
// reproduce the following acknowledgment in the end-user documentation
// and/or other materials provided with the product:
//
// "This product is based on software from the PixInsight project, developed
// by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
//
// Alternatively, if that is where third-party acknowledgments normally
// appear, this acknowledgment must be reproduced in the product itself.
//
// THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
// INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
// DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------------------
#ifndef __PCL_MorphologicalOperator_h
#define __PCL_MorphologicalOperator_h
/// \file pcl/MorphologicalOperator.h
#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>
#include <pcl/Exception.h>
#include <pcl/Math.h>
#include <pcl/PixelTraits.h>
#include <pcl/Selection.h>
#include <pcl/Sort.h>
#include <pcl/String.h>
#include <pcl/Utility.h>
namespace pcl
{
// ----------------------------------------------------------------------------
/*!
* \class MorphologicalOperator
* \brief Abstract base class of all PCL morphological operators.
*
* \sa ErosionFilter, DilationFilter, MedianFilter, SelectionFilter,
* MidpointFilter, AlphaTrimmedMeanFilter
*/
class PCL_CLASS MorphologicalOperator
{
public:
/*!
* Constructs a %MorphologicalOperator object.
*/
MorphologicalOperator() = default;
/*!
* Copy constructor.
*/
MorphologicalOperator( const MorphologicalOperator& ) = default;
/*!
* Destroys a %MorphologicalOperator object.
*/
virtual ~MorphologicalOperator()
{
}
/*!
* Returns a pointer to a dynamically allocated duplicate of this
* morphological operator.
*/
virtual MorphologicalOperator* Clone() const = 0;
/*!
* Returns a human-readable description of this morphological operator.
*/
virtual String Description() const
{
return String();
}
/*!
* \internal
* Returns true iff this object performs a dilation morphological operation.
* This member function is used internally to decide whether to reflect the
* structuring element during morphological transformations.
*/
virtual bool IsDilation() const
{
return false;
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
virtual FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 32-bit floating-point images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
virtual DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 64-bit floating-point images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point complex pixel samples.
*/
virtual ComplexPixelTraits::sample operator ()( ComplexPixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 32-bit complex images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point complex pixel samples.
*/
virtual DComplexPixelTraits::sample operator ()( DComplexPixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 64-bit complex images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
virtual UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 8-bit integer images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
virtual UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 16-bit integer images" );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
virtual UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const
{
throw NotImplemented( *this, "Apply to 32-bit integer images" );
}
};
// ----------------------------------------------------------------------------
/*!
* \class ErosionFilter
* \brief Erosion morphological operator.
*
* The \e erosion morphological operator computes the minimum value in a pixel
* neighborhood.
*/
class PCL_CLASS ErosionFilter : public MorphologicalOperator
{
public:
/*!
*/
MorphologicalOperator* Clone() const override
{
return new ErosionFilter( *this );
}
/*!
*/
String Description() const override
{
return "Erosion";
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
private:
template <typename T>
static T Operate( T* __restrict__ f, size_type n )
{
T x = *f++;
for ( ; --n > 0; ++f )
if ( *f < x )
x = *f;
return x;
}
};
// ----------------------------------------------------------------------------
/*!
* \class DilationFilter
* \brief Dilation morphological operator.
*
* The \e dilation morphological operator computes the maximum value in a pixel
* neighborhood.
*/
class PCL_CLASS DilationFilter : public MorphologicalOperator
{
public:
/*!
*/
MorphologicalOperator* Clone() const override
{
return new DilationFilter( *this );
}
/*!
*/
String Description() const override
{
return "Dilation";
}
/*!
*/
bool IsDilation() const override
{
return true;
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
private:
template <typename T>
static T Operate( T* __restrict__ f, size_type n )
{
T x = *f++;
for ( ; --n > 0; ++f )
if ( x < *f )
x = *f;
return x;
}
};
// ----------------------------------------------------------------------------
/*!
* \class MedianFilter
* \brief Morphological median operator.
*
* The \e median morphological operator (or median order-statistic filter)
* computes the median of the values in a pixel neighborhood.
*/
class PCL_CLASS MedianFilter : public MorphologicalOperator
{
public:
/*!
*/
MorphologicalOperator* Clone() const override
{
return new MedianFilter( *this );
}
/*!
*/
String Description() const override
{
return "Median";
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (FloatPixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (DoublePixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt8PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt16PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt32PixelTraits*)0 );
}
private:
#define CMPXCHG( a, b ) \
if ( f[b] < f[a] ) pcl::Swap( f[a], f[b] )
#define MEAN( a, b ) \
P::FloatToSample( (double( a ) + double( b ))/2 )
template <typename T, class P>
static T Operate( T* __restrict__ f, size_type n, P* )
{
/*
* Use fast, hard-coded selection networks for n <= 24:
*
* Knuth, D. E., The Art of Computer Programming, volume 3: Sorting and
* Searching, Addison Wesley, 1973.
*
* Hillis, W. D., Co-evolving parasites improve simulated evolution as an
* optimization procedure.</em> Langton, C. et al. (Eds.), Artificial
* Life II. Addison Wesley, 1992.
*
* Hugues Juille, Evolution of Non-Deterministic Incremental Algorithms
* as a New Approach for Search in State Spaces, 1995.
*
* Use a quick selection algorithm for n > 24:
*
* William H. Press et al., Numerical Recipes 3rd Edition: The Art of
* Scientific Computing, Cambridge University Press, 2007, Section 8.5.
*
* Robert Sedgewick, Kevin Wayne, Algorithms, 4th Edition, Addison-Wesley
* Professional, 2011, pp 345-347.
*/
switch ( n )
{
case 0: // ?!
return 0;
case 1: // !?
return f[0];
case 2:
return MEAN( f[0], f[1] );
case 3:
CMPXCHG( 0, 1 ); CMPXCHG( 1, 2 );
return pcl::Max( f[0], f[1] );
case 4:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 );
CMPXCHG( 1, 3 );
return MEAN( f[1], f[2] );
case 5:
CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 0, 3 );
CMPXCHG( 1, 4 ); CMPXCHG( 1, 2 ); CMPXCHG( 2, 3 );
return pcl::Max( f[1], f[2] );
case 6:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 0, 2 );
CMPXCHG( 1, 3 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 );
CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 1, 4 );
CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 3, 4 );
return MEAN( f[2], f[3] );
case 7:
CMPXCHG( 0, 5 ); CMPXCHG( 0, 3 ); CMPXCHG( 1, 6 );
CMPXCHG( 2, 4 ); CMPXCHG( 0, 1 ); CMPXCHG( 3, 5 );
CMPXCHG( 2, 6 ); CMPXCHG( 2, 3 ); CMPXCHG( 3, 6 );
CMPXCHG( 4, 5 ); CMPXCHG( 1, 4 ); CMPXCHG( 1, 3 );
return pcl::Min( f[3], f[4] );
case 8:
CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
CMPXCHG( 3, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 );
CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 1, 4 );
CMPXCHG( 3, 6 );
return MEAN( f[3], f[4] );
case 9:
CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 );
CMPXCHG( 0, 1 ); CMPXCHG( 3, 4 ); CMPXCHG( 6, 7 );
CMPXCHG( 1, 2 ); CMPXCHG( 4, 5 ); CMPXCHG( 7, 8 );
CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 ); CMPXCHG( 4, 7 );
CMPXCHG( 3, 6 ); CMPXCHG( 1, 4 ); CMPXCHG( 2, 5 );
CMPXCHG( 4, 7 ); CMPXCHG( 4, 2 ); CMPXCHG( 6, 4 );
return pcl::Min( f[2], f[4] );
case 10:
CMPXCHG( 4, 9 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 7 );
CMPXCHG( 1, 6 ); CMPXCHG( 0, 5 ); CMPXCHG( 1, 4 );
CMPXCHG( 6, 9 ); CMPXCHG( 0, 3 ); CMPXCHG( 5, 8 );
CMPXCHG( 0, 2 ); CMPXCHG( 3, 6 ); CMPXCHG( 7, 9 );
CMPXCHG( 0, 1 ); CMPXCHG( 2, 4 ); CMPXCHG( 5, 7 );
CMPXCHG( 8, 9 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 6 );
CMPXCHG( 7, 8 ); CMPXCHG( 3, 5 ); CMPXCHG( 2, 5 );
CMPXCHG( 6, 8 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 7 );
CMPXCHG( 2, 3 ); CMPXCHG( 6, 7 ); CMPXCHG( 3, 4 );
CMPXCHG( 5, 6 );
return MEAN( f[4], f[5] );
case 11:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 1, 3 );
CMPXCHG( 5, 7 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
CMPXCHG( 8, 10 ); CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 );
CMPXCHG( 9, 10 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 );
CMPXCHG( 5, 9 ); CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 );
CMPXCHG( 6, 10 ); CMPXCHG( 0, 4 ); CMPXCHG( 3, 7 );
CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 4 );
CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 2, 3 );
CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
return pcl::Min( f[5], f[6] );
case 12:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 );
CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 );
CMPXCHG( 1, 2 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 );
CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 ); CMPXCHG( 5, 9 );
CMPXCHG( 2, 6 ); CMPXCHG( 1, 5 ); CMPXCHG( 6, 10 );
CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 ); CMPXCHG( 3, 7 );
CMPXCHG( 4, 8 ); CMPXCHG( 0, 4 ); CMPXCHG( 7, 11 );
CMPXCHG( 1, 4 ); CMPXCHG( 7, 10 ); CMPXCHG( 3, 8 );
CMPXCHG( 2, 3 ); CMPXCHG( 8, 9 ); CMPXCHG( 3, 5 );
CMPXCHG( 6, 8 );
return MEAN( f[5], f[6] );
case 13:
CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 0, 4 );
CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
CMPXCHG( 8, 12 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 0, 2 );
CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 );
CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 2, 8 );
CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
CMPXCHG( 10, 12 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
CMPXCHG( 10, 11 ); CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 );
CMPXCHG( 5, 12 ); CMPXCHG( 3, 6 ); CMPXCHG( 5, 8 );
return pcl::Max( f[5], f[6] );
case 14:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
CMPXCHG( 8, 10 ); CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 );
CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 );
CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 );
CMPXCHG( 3, 7 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
CMPXCHG( 5, 13 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 );
CMPXCHG( 3, 12 ); CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 );
CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 );
CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 );
CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 ); CMPXCHG( 3, 5 );
CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 );
return MEAN( f[6], f[7] );
case 15:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 0, 2 ); CMPXCHG( 4, 6 );
CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 ); CMPXCHG( 1, 3 );
CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 ); CMPXCHG( 0, 4 );
CMPXCHG( 8, 12 ); CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 );
CMPXCHG( 2, 6 ); CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 );
CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
CMPXCHG( 6, 14 ); CMPXCHG( 5, 10 ); CMPXCHG( 6, 9 );
CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 ); CMPXCHG( 7, 11 );
CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 ); CMPXCHG( 7, 13 );
CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 ); CMPXCHG( 9, 10 );
CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 ); CMPXCHG( 6, 8 );
CMPXCHG( 3, 5 ); CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 );
CMPXCHG( 7, 8 );
return pcl::Max( f[6], f[7] );
case 16:
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 0, 2 );
CMPXCHG( 4, 6 ); CMPXCHG( 8, 10 ); CMPXCHG( 12, 14 );
CMPXCHG( 1, 3 ); CMPXCHG( 5, 7 ); CMPXCHG( 9, 11 );
CMPXCHG( 13, 15 ); CMPXCHG( 0, 4 ); CMPXCHG( 8, 12 );
CMPXCHG( 1, 5 ); CMPXCHG( 9, 13 ); CMPXCHG( 2, 6 );
CMPXCHG( 10, 14 ); CMPXCHG( 3, 7 ); CMPXCHG( 11, 15 );
CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 5, 10 );
CMPXCHG( 6, 9 ); CMPXCHG( 3, 12 ); CMPXCHG( 13, 14 );
CMPXCHG( 7, 11 ); CMPXCHG( 1, 2 ); CMPXCHG( 4, 8 );
CMPXCHG( 7, 13 ); CMPXCHG( 2, 8 ); CMPXCHG( 5, 6 );
CMPXCHG( 9, 10 ); CMPXCHG( 3, 8 ); CMPXCHG( 7, 12 );
CMPXCHG( 6, 8 ); CMPXCHG( 10, 12 ); CMPXCHG( 3, 5 );
CMPXCHG( 7, 9 ); CMPXCHG( 5, 6 ); CMPXCHG( 7, 8 );
CMPXCHG( 9, 10 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
return MEAN( f[7], f[8] );
case 17:
CMPXCHG( 0, 16 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
CMPXCHG( 8, 16 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
CMPXCHG( 4, 16 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 2, 16 );
CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 1, 16 );
CMPXCHG( 1, 8 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 );
CMPXCHG( 7, 14 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 );
return pcl::Max( f[7], f[8] );
case 18:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 0, 8 );
CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 );
CMPXCHG( 5, 17 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 );
CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 );
CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 );
CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 );
CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 );
CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 );
CMPXCHG( 16, 17 ); CMPXCHG( 1, 16 ); CMPXCHG( 1, 8 );
CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 );
CMPXCHG( 9, 16 ); CMPXCHG( 5, 8 ); CMPXCHG( 7, 10 );
CMPXCHG( 9, 12 ); CMPXCHG( 7, 8 ); CMPXCHG( 9, 10 );
return MEAN( f[8], f[9] );
case 19:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 );
CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 0, 4 );
CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 );
CMPXCHG( 11, 15 ); CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 );
CMPXCHG( 6, 18 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 0, 2 );
CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 ); CMPXCHG( 5, 7 );
CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 ); CMPXCHG( 12, 14 );
CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 ); CMPXCHG( 2, 16 );
CMPXCHG( 3, 17 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
CMPXCHG( 11, 17 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 );
CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 );
CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 );
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 );
CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 );
CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
return pcl::Min( f[9], f[10] );
case 20:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 3, 19 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 );
CMPXCHG( 11, 19 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 );
CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 );
CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 0, 1 );
CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 3, 10 );
CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
return MEAN( f[9], f[10] );
case 21:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 0, 8 );
CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 );
CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 );
CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
CMPXCHG( 6, 20 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 0, 1 );
CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 );
CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 );
CMPXCHG( 9, 16 ); CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 );
return pcl::Max( f[9], f[10] );
case 22:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 );
CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 );
CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 );
CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 );
CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 ); CMPXCHG( 0, 4 );
CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 );
CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 );
CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 );
CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
CMPXCHG( 17, 19 ); CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 );
CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 );
CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 );
CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 );
CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 );
CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 );
CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 );
CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 );
CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 );
CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 );
CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 );
CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 );
CMPXCHG( 5, 20 ); CMPXCHG( 3, 10 ); CMPXCHG( 5, 12 );
CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 );
CMPXCHG( 7, 10 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
CMPXCHG( 9, 10 ); CMPXCHG( 11, 12 );
return MEAN( f[10], f[11] );
case 23:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
CMPXCHG( 6, 22 ); CMPXCHG( 0, 8 ); CMPXCHG( 1, 9 );
CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 ); CMPXCHG( 4, 12 );
CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 ); CMPXCHG( 7, 15 );
CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 ); CMPXCHG( 10, 18 );
CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 ); CMPXCHG( 13, 21 );
CMPXCHG( 14, 22 ); CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 );
CMPXCHG( 2, 6 ); CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 );
CMPXCHG( 9, 13 ); CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 );
CMPXCHG( 16, 20 ); CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 );
CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 2, 16 );
CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 ); CMPXCHG( 7, 21 );
CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 ); CMPXCHG( 6, 12 );
CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 ); CMPXCHG( 11, 17 );
CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 ); CMPXCHG( 2, 4 );
CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 ); CMPXCHG( 7, 9 );
CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 ); CMPXCHG( 14, 16 );
CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 ); CMPXCHG( 19, 21 );
CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 ); CMPXCHG( 4, 5 );
CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 ); CMPXCHG( 10, 11 );
CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 ); CMPXCHG( 16, 17 );
CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 ); CMPXCHG( 1, 16 );
CMPXCHG( 3, 18 ); CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 );
CMPXCHG( 5, 12 ); CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 );
CMPXCHG( 11, 18 ); CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
return pcl::Min( f[11], f[12] );
case 24:
CMPXCHG( 0, 16 ); CMPXCHG( 1, 17 ); CMPXCHG( 2, 18 );
CMPXCHG( 3, 19 ); CMPXCHG( 4, 20 ); CMPXCHG( 5, 21 );
CMPXCHG( 6, 22 ); CMPXCHG( 7, 23 ); CMPXCHG( 0, 8 );
CMPXCHG( 1, 9 ); CMPXCHG( 2, 10 ); CMPXCHG( 3, 11 );
CMPXCHG( 4, 12 ); CMPXCHG( 5, 13 ); CMPXCHG( 6, 14 );
CMPXCHG( 7, 15 ); CMPXCHG( 8, 16 ); CMPXCHG( 9, 17 );
CMPXCHG( 10, 18 ); CMPXCHG( 11, 19 ); CMPXCHG( 12, 20 );
CMPXCHG( 13, 21 ); CMPXCHG( 14, 22 ); CMPXCHG( 15, 23 );
CMPXCHG( 0, 4 ); CMPXCHG( 1, 5 ); CMPXCHG( 2, 6 );
CMPXCHG( 3, 7 ); CMPXCHG( 8, 12 ); CMPXCHG( 9, 13 );
CMPXCHG( 10, 14 ); CMPXCHG( 11, 15 ); CMPXCHG( 16, 20 );
CMPXCHG( 17, 21 ); CMPXCHG( 18, 22 ); CMPXCHG( 19, 23 );
CMPXCHG( 4, 16 ); CMPXCHG( 5, 17 ); CMPXCHG( 6, 18 );
CMPXCHG( 7, 19 ); CMPXCHG( 4, 8 ); CMPXCHG( 5, 9 );
CMPXCHG( 6, 10 ); CMPXCHG( 7, 11 ); CMPXCHG( 12, 16 );
CMPXCHG( 13, 17 ); CMPXCHG( 14, 18 ); CMPXCHG( 15, 19 );
CMPXCHG( 0, 2 ); CMPXCHG( 1, 3 ); CMPXCHG( 4, 6 );
CMPXCHG( 5, 7 ); CMPXCHG( 8, 10 ); CMPXCHG( 9, 11 );
CMPXCHG( 12, 14 ); CMPXCHG( 13, 15 ); CMPXCHG( 16, 18 );
CMPXCHG( 17, 19 ); CMPXCHG( 20, 22 ); CMPXCHG( 21, 23 );
CMPXCHG( 2, 16 ); CMPXCHG( 3, 17 ); CMPXCHG( 6, 20 );
CMPXCHG( 7, 21 ); CMPXCHG( 2, 8 ); CMPXCHG( 3, 9 );
CMPXCHG( 6, 12 ); CMPXCHG( 7, 13 ); CMPXCHG( 10, 16 );
CMPXCHG( 11, 17 ); CMPXCHG( 14, 20 ); CMPXCHG( 15, 21 );
CMPXCHG( 2, 4 ); CMPXCHG( 3, 5 ); CMPXCHG( 6, 8 );
CMPXCHG( 7, 9 ); CMPXCHG( 10, 12 ); CMPXCHG( 11, 13 );
CMPXCHG( 14, 16 ); CMPXCHG( 15, 17 ); CMPXCHG( 18, 20 );
CMPXCHG( 19, 21 ); CMPXCHG( 0, 1 ); CMPXCHG( 2, 3 );
CMPXCHG( 4, 5 ); CMPXCHG( 6, 7 ); CMPXCHG( 8, 9 );
CMPXCHG( 10, 11 ); CMPXCHG( 12, 13 ); CMPXCHG( 14, 15 );
CMPXCHG( 16, 17 ); CMPXCHG( 18, 19 ); CMPXCHG( 20, 21 );
CMPXCHG( 22, 23 ); CMPXCHG( 1, 16 ); CMPXCHG( 3, 18 );
CMPXCHG( 5, 20 ); CMPXCHG( 7, 22 ); CMPXCHG( 5, 12 );
CMPXCHG( 7, 14 ); CMPXCHG( 9, 16 ); CMPXCHG( 11, 18 );
CMPXCHG( 9, 12 ); CMPXCHG( 11, 14 );
return MEAN( f[11], f[12] );
default:
{
distance_type n2 = distance_type( n >> 1 );
if ( n & 1 )
return *pcl::Select( f, f+n, n2 );
return P::FloatToSample( (double( *pcl::Select( f, f+n, n2 ) )
+ double( *pcl::Select( f, f+n, n2-1 ) ))/2 );
}
}
}
#undef CMPXCHG
#undef MEAN
};
// ----------------------------------------------------------------------------
/*!
* \class SelectionFilter
* \brief Morphological selection operator.
*
* The \e selection morphological operator (or selection order-statistic
* filter) computes the value corresponding to a prescribed percentile in the
* ranked set of values from a pixel neighborhood.
*
* The <em>selection point</em> \a k of the selection operator defines the
* working percentile: for k=0, we have an erosion (or minimum) operator; for
* k=1 we have a dilation (or maximum) operator; k=0.5 defines the median
* operator. Other values work as a balance between erosion and dilation.
*/
class PCL_CLASS SelectionFilter : public MorphologicalOperator
{
public:
/*!
* Default constructor. The default selection point is 0.5, equivalent to a
* median operator.
*/
SelectionFilter() = default;
/*!
* Constructs a %SelectionFilter with selection point \a p.
*/
SelectionFilter( float p )
: k( pcl::Range( p, float( 0 ), float( 1 ) ) )
{
PCL_PRECONDITION( 0 <= p && p <= 1 )
PCL_CHECK( 0 <= k && k <= 1 )
}
/*!
* Copy constructor.
*/
SelectionFilter( const SelectionFilter& ) = default;
/*!
*/
MorphologicalOperator* Clone() const override
{
return new SelectionFilter( *this );
}
/*!
* Returns the selection point of this morphological selection operator.
*/
float SelectionPoint() const
{
return k;
}
/*!
* Sets the selection point of this morphological selection operator.
*/
void SetSelectionPoint( float _k )
{
PCL_PRECONDITION( 0 <= _k && _k <= 1 )
k = pcl::Range( _k, float( 0 ), float( 1 ) );
}
/*!
*/
String Description() const override
{
return String().Format( "Selection, k=%.5f", k );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n );
}
private:
float k = 0.5F;
template <typename T>
T Operate( T* f, size_type n ) const
{
return *pcl::Select( f, f+n, distance_type( pcl::RoundInt( k*(n-1) ) ) );
}
};
// ----------------------------------------------------------------------------
/*!
* \class MidpointFilter
* \brief Midpoint operator.
*
* The \e midpoint operator computes the midpoint value in a pixel
* neighborhood, namely: (minimum + maximum)/2.
*/
class PCL_CLASS MidpointFilter : public MorphologicalOperator
{
public:
/*!
*/
MorphologicalOperator* Clone() const override
{
return new MidpointFilter( *this );
}
/*!
*/
String Description() const override
{
return "Midpoint";
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (FloatPixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (DoublePixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt8PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt16PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt32PixelTraits*)0 );
}
private:
template <typename T, class P>
static T Operate( T* f, size_type n, P* )
{
T* min, * max;
pcl::FindExtremeItems( min, max, f, f+n );
return P::FloatToSample( (double( *min ) + double( *max ))/2 );
}
};
// ----------------------------------------------------------------------------
/*!
* \class AlphaTrimmedMeanFilter
* \brief Alpha-trimmed mean operator
*
* The <em>alpha-trimmed mean</em> operator computes the mean of the remaining
* values in a pixel neighborhood, after suppressing the d/2 lowest and the d/2
* highest values. The point \a d defines the <em>trimming factor</em> of the
* operator. When d=0, we have an arithmetic mean filter. If d=1, the filter is
* the median operator.
*
* The alpha-trimmed operator is not a morphological operator in the strict
* sense, although it allows for the implementation of robust filters that
* share some important properties with morphological filters in practical
* applications.
*/
class PCL_CLASS AlphaTrimmedMeanFilter : public MorphologicalOperator
{
public:
/*!
* Default constructor. The default trimming factor is 0.2, which leads to
* the suppression of a 10% of the lowest and highest neighbor pixels. The
* resulting object is a robust mean filter resilient to outliers in most
* practical cases.
*/
AlphaTrimmedMeanFilter() = default;
/*!
* Constructs a %AlphaTrimmedMeanFilter object with the specified trimming
* factor \a t in the [0,1] range.
*/
AlphaTrimmedMeanFilter( float t )
: d( pcl::Range( t, float( 0 ), float( 1 ) ) )
{
PCL_PRECONDITION( 0 <= t && t <= 1 )
PCL_CHECK( 0 <= d && d <= 1 )
}
/*!
* Copy constructor.
*/
AlphaTrimmedMeanFilter( const AlphaTrimmedMeanFilter& ) = default;
/*!
*/
MorphologicalOperator* Clone() const override
{
return new AlphaTrimmedMeanFilter( *this );
}
/*!
* Returns the trimming factor of this alpha-trimmed mean operator.
*/
float TrimmingFactor() const
{
return d;
}
/*!
* Sets the trimming factor \a t of this alpha-trimmed mean operator.
*/
void SetTrimmingFactor( float t )
{
PCL_PRECONDITION( 0 <= t && t <= 1 )
d = pcl::Range( t, float( 0 ), float( 1 ) );
}
/*!
*/
String Description() const override
{
return String().Format( "Alpha-trimmed mean, d=%.5f", d );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* floating point pixel samples.
*/
FloatPixelTraits::sample operator ()( FloatPixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (FloatPixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 64-bit
* floating point pixel samples.
*/
DoublePixelTraits::sample operator ()( DoublePixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (DoublePixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 8-bit
* unsigned integer pixel samples.
*/
UInt8PixelTraits::sample operator ()( UInt8PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt8PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 16-bit
* unsigned integer pixel samples.
*/
UInt16PixelTraits::sample operator ()( UInt16PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt16PixelTraits*)0 );
}
/*!
* Applies this morphological operator to a vector \a f of \a n 32-bit
* unsigned integer pixel samples.
*/
UInt32PixelTraits::sample operator ()( UInt32PixelTraits::sample* f, size_type n ) const override
{
return Operate( f, n, (UInt32PixelTraits*)0 );
}
private:
float d = 0.2F;
template <typename T, class P>
T Operate( T* f, size_type n, P* ) const
{
pcl::Sort( f, f+n );
double s = 0;
size_type i1 = RoundInt( d*((n - 1) >> 1) );
size_type i2 = n-i1;
for ( size_type i = i1; i < i2; ++i )
s += f[i];
return P::FloatToSample( s/(i2 - i1) );
}
};
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_MorphologicalOperator_h
// ----------------------------------------------------------------------------
// EOF pcl/MorphologicalOperator.h - Released 2022-03-12T18:59:29Z