1238 lines
47 KiB
C++
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
|