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

957 lines
28 KiB
C++

// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/StructuringElement.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_StructuringElement_h
#define __PCL_StructuringElement_h
/// \file pcl/StructuringElement.h
#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>
#include <pcl/Atomic.h>
#include <pcl/AutoLock.h>
#include <pcl/Math.h>
#include <pcl/Rotate.h> // Reverse()
#include <pcl/StringList.h> // BitmapStructure
#include <pcl/Utility.h>
#include <pcl/Vector.h>
#include <memory.h>
namespace pcl
{
// ----------------------------------------------------------------------------
/*!
* \class StructuringElement
* \brief Abstract base class of all PCL structuring elements.
*
* %StructuringElement defines a square multiway structure that can be used,
* along with a MorphologicalOperator, to build a MorphologicalTransformation.
*
* A structure is a square matrix of Boolean elements. When an element is true
* we say that that element \e exists. Nonexistent (false) structure elements
* are ignored when a morphological operator is applied to an image.
*
* A <em>structuring element</em> works for morphological transformations in a
* similar way to a <em>kernel filter</em> for spatial convolutions: the
* structure is placed centered on a pixel of the image being processed, and
* only those neighbor pixels falling behind existing structure elements are
* taken into account to compute the result of a morphological operator. When
* this operation is repeated for each pixel in an image, it implements a
* <em>morphological transformation</em>.
*
* %StructuringElement holds a <em>multiway structure</em>. Each way is
* actually a separate structure, so a multiway structure actually groups a
* set of structures with the same dimensions. When a multiway structure is
* used to apply a morphological operator, the operator is first applied
* through each way in the structure, and the result is the same operator
* applied to the partial results.
*
* This class is thread-safe. This means that multiple execution threads can
* access the same %StructuringElement instance concurrently to perform
* morphological transformations.
*
* \sa MorphologicalOperator, MorphologicalTransformation
*/
class PCL_CLASS StructuringElement
{
public:
/*!
* Represents an element of a structure existence mask.
*/
typedef uint32 existence_mask_element;
/*!
* Represents a structure existence mask.
*/
typedef GenericVector<existence_mask_element> existence_mask;
/*!
* Represents a set of structure existence masks.
*/
typedef GenericVector<existence_mask> existence_mask_set;
/*!
* A vector type used to store the number of existing structure elements.
*/
typedef GenericVector<int> existence_mask_count;
/*!
* Constructs a default \e box %StructuringElement object of the specified
* \a size in pixels and number of ways \a n.
*/
StructuringElement( int size = 3, int n = 1 )
: m_size( Max( 3, size|1 ) )
, m_mask( Max( 1, n ) )
, m_count( 0, Max( 1, n ) )
{
PCL_PRECONDITION( size >= 3 )
PCL_PRECONDITION( (size & 1) != 0 )
PCL_PRECONDITION( n >= 1 )
for ( int k = 0; k < NumberOfWays(); ++k )
m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
}
/*!
* Copy constructor.
*/
StructuringElement( const StructuringElement& x )
: m_size( x.m_size )
, m_mask( x.NumberOfWays() )
, m_count( 0, x.NumberOfWays() )
{
for ( int k = 0; k < NumberOfWays(); ++k )
m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
}
/*!
* Destroys a %StructuringElement object.
*/
virtual ~StructuringElement()
{
}
/*!
* Returns a pointer to a dynamically allocated duplicate of this
* structuring element.
*/
virtual StructuringElement* Clone() const = 0;
/*!
* Copy assignment operator. Returns a reference to this object.
*/
StructuringElement& operator =( const StructuringElement& x )
{
if ( &x != this )
{
volatile AutoLock lock( m_mutex );
m_size = x.m_size;
m_mask = existence_mask_set( x.NumberOfWays() );
m_count = existence_mask_count( 0, x.NumberOfWays() );
m_reflected = false;
m_initialized = 0;
for ( int k = 0; k < NumberOfWays(); ++k )
m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
}
return *this;
}
/*!
* Returns the number of ways in this structure.
*/
int NumberOfWays() const
{
return int( m_mask.Length() );
}
/*!
* Returns the size of this structure in pixels.
*/
int Size() const
{
return m_size;
}
/*!
* Returns the total number of structure elements, or Size()*Size(). Note
* that this includes both existing and nonexistent structure elements.
*/
int NumberOfElements() const
{
return m_size*m_size;
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* The default implementation of this member function returns true if all
* elements in the k-th way are reported as existing elements by the
* ElementExists() member function.
*
* \note This is a performance-critical routine. When possible, derived
* classes should reimplement it in more efficient ways (for example, a
* circular structure is never a box structure).
*/
virtual bool IsBox( int k ) const
{
PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
Initialize();
return m_count[k] == NumberOfElements();
}
/*!
* Returns true iff a given element exists in this structure.
*
* \param i column position (X-coordinate) of the requested structure
* element. Must be 0 <= i < n, where n is the structure size.
*
* \param j row position (Y-coordinate) of the requested structure
* element. Must be 0 <= j < n, where n is the structure size.
*
* \param k Way index. Must be 0 <= k < m, where m is the number of ways
* defined in this structure.
*/
virtual bool ElementExists( int i, int j, int k ) const
{
PCL_PRECONDITION( i >= 0 && i < m_size )
PCL_PRECONDITION( j >= 0 && j < m_size )
PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
return true;
}
/*!
* Gets the subset of pixel sample values that correspond to existing
* elements in a way of this structure.
*
* \param[out] h1 %Vector of samples from the input \a h array that
* correspond to existing structure elements.
*
* \param[out] nh1 The number of existing elements in the k-th way of
* this structure. This is also the number of samples
* stored in the \a h1 vector.
*
* \param h Input array of samples. Must be the starting address of a
* square matrix of \a n samples stored in row order, where \a n
* is the number of elements in this structure (equal to
* NumberOfElements()).
*
* \param k Way index. Must be 0 <= k < m, where m is the number of ways
* defined in this structure.
*
* \note This function is thread-safe.
*/
template <typename T>
void PeekElements( T* h1, int& nh1, const T* h, int k ) const
{
PCL_PRECONDITION( h1 != 0 )
PCL_PRECONDITION( h != 0 )
PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
Initialize();
nh1 = 0;
for ( existence_mask::const_iterator m = m_mask[k].Begin(), m1 = m_mask[k].End(); m < m1; ++m, ++h )
if ( *m )
{
*h1++ = *h;
++nh1;
}
}
/*!
* Reflects this structure.
*
* Structure reflection is equivalent to a 180 degrees rotation of the
* underlying structure mask for each way. This member function is called
* internally by MorphologicalTransformation to apply dilation operators.
*/
void Reflect()
{
Initialize();
for ( existence_mask_set::iterator i = m_mask.Begin(); i != m_mask.End(); ++i )
pcl::Reverse( i->Begin(), i->End() );
m_reflected = !m_reflected;
}
/*!
* Returns true iff this structure has been reflected. Note that after an
* even number of successive reflections (which is a no-op) this member
* function will return false.
*/
bool IsReflected() const
{
return m_reflected;
}
/*!
* Initializes the internal <em>existence tables</em>.
*
* A structure is a square matrix of Boolean elements. When an element is
* true we say that that element \e exists. Nonexistent (false) structure
* elements are ignored when a morphological operator is applied to
* transform an image.
*
* StructuringElement (and derived classes) uses a set of precomputed
* <em>existence tables</em> that greatly improves performance of
* morphological transformations, especially for complex structures. Calling
* this member function forces the immediate calculation of existence
* tables, if they haven't already been calculated previously. If the
* existence tables already exist, this function does nothing.
*
* You normally should not need to call this member function directly, as
* existence tables are automatically calculated when required.
*
* \note This is a thread-safe routine. It can be safely called from
* multiple running threads.
*/
void Initialize() const
{
if ( !m_initialized )
{
volatile AutoLock lock( m_mutex );
if ( m_initialized.Load() == 0 )
{
int N = NumberOfWays();
for ( int k = 0; k < N; ++k )
{
m_count[k] = 0; // redundant, but doesn't hurt
existence_mask::iterator m = m_mask[k].Begin();
for ( int i = 0; i < m_size; ++i )
for ( int j = 0; j < m_size; ++j, ++m )
if ( ElementExists( i, j, k ) )
{
*m = 1;
++m_count[k];
}
else
*m = 0;
}
m_initialized.Store( 1 );
}
}
}
private:
/*
* Structure size.
*/
int m_size;
/*
* Element existence masks (one mask per way).
* An element exists iff its corresponding mask element is nonzero.
*/
mutable existence_mask_set m_mask;
/*
* Number of existing elements for each way.
*/
mutable existence_mask_count m_count;
/*
* Flag true when the structure has been reflected.
*/
bool m_reflected = false;
/*
* Flag true when existence masks have been calculated.
*/
mutable AtomicInt m_initialized;
/*
* Thread synchronization.
*/
mutable Mutex m_mutex;
};
// ----------------------------------------------------------------------------
/*!
* \class BoxStructure
* \brief Standard box (square) structure.
*
* A <em>block structure</em> defines all of its elements. For example, a box
* structure of size 5 is:
*
* <pre>
* x x x x x
* x x x x x
* x x x x x
* x x x x x
* x x x x x
* </pre>
*
* where existing elements are marked as 'x'.
*
* \sa CircularStructure, OrthogonalStructure, DiagonalStructure, StarStructure
*/
class PCL_CLASS BoxStructure : public StructuringElement
{
public:
/*!
* Constructs a standard block structure of the specified \a size.
*/
BoxStructure( int size )
: StructuringElement( size, 1 )
{
}
/*!
* Copy constructor.
*/
BoxStructure( const BoxStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new BoxStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %BoxStructure, this member function always
* returns true.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k == 0 )
return true;
}
};
// ----------------------------------------------------------------------------
/*!
* \class CircularStructure
* \brief Standard circular structure.
*
* The <em>standard circular structure</em> of size 7 is defined as follows:
*
* <pre>
* · · x x x · ·
* · x x x x x ·
* x x x x x x x
* x x x x x x x
* x x x x x x x
* · x x x x x ·
* · · x x x · ·
* </pre>
*
* where existing elements are marked as 'x' and nonexisting elements are
* denoted as '·'.
*
* Circular structures can help in preserving small structures, especially
* rounded ones, like stars.
*
* \sa ThreeWayStructure, OrthogonalStructure, DiagonalStructure, StarStructure
*/
class PCL_CLASS CircularStructure : public StructuringElement
{
public:
/*!
* Constructs a standard circular structure of the specified \a diameter.
*/
CircularStructure( int diameter )
: StructuringElement( diameter, 1 )
{
}
/*!
* Copy constructor.
*/
CircularStructure( const CircularStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new CircularStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %CircularStructure, this member function always
* returns false.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k == 0 )
return false;
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k == 0 )
float n2 = 0.5F*Size();
float di = i+0.5F - n2;
float dj = j+0.5F - n2;
return di*di + dj*dj <= n2*n2;
}
};
// ----------------------------------------------------------------------------
/*!
* \class OrthogonalStructure
* \brief Standard orthogonal structure.
*
* An <em>orthogonal structure</em> of size 5 is defined as follows:
*
* <pre>
* · · x · ·
* · · x · ·
* x x x x x
* · · x · ·
* · · x · ·
* </pre>
*
* where existing elements are marked as 'x' and nonexisting elements are
* denoted as '·'.
*
* \sa ThreeWayStructure, CircularStructure, DiagonalStructure, StarStructure
*/
class PCL_CLASS OrthogonalStructure : public StructuringElement
{
public:
/*!
* Constructs an orthogonal structure of the specified \a size.
*/
OrthogonalStructure( int size )
: StructuringElement( size, 1 )
{
}
/*!
* Copy constructor.
*/
OrthogonalStructure( const OrthogonalStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new OrthogonalStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %OrthogonalStructure, this member function always
* returns false.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k == 0 )
return false;
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k == 0 )
int n2 = Size() >> 1;
return i == n2 || j == n2;
}
};
// ----------------------------------------------------------------------------
/*!
* \class DiagonalStructure
* \brief Standard diagonal structure.
*
* A <em>diagonal structure</em> of size 5 is defined as follows:
*
* <pre>
* x · · · x
* · x · x ·
* · · x · ·
* · x · x ·
* x · · · x
* </pre>
*
* where existing elements are marked as 'x' and nonexisting elements are
* denoted as '·'.
*
* \sa ThreeWayStructure, CircularStructure, OrthogonalStructure, StarStructure
*/
class PCL_CLASS DiagonalStructure : public StructuringElement
{
public:
/*!
* Constructs a diagonal structure of the specified \a size.
*/
DiagonalStructure( int size )
: StructuringElement( size, 1 )
{
}
/*!
* Copy constructor.
*/
DiagonalStructure( const DiagonalStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new DiagonalStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %DiagonalStructure, this member function always
* returns false.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k == 0 )
return false;
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k == 0 )
return j == i || j == Size()-i-1;
}
};
// ----------------------------------------------------------------------------
/*!
* \class StarStructure
* \brief Standard star structure.
*
* A <em>star structure</em> of size 7 is defined as follows:
*
* <pre>
* · · · x · · ·
* · x · x · x ·
* · · x x x · ·
* x x x x x x x
* · · x x x · ·
* · x · x · x ·
* · · · x · · ·
* </pre>
*
* where existing elements are marked as 'x' and nonexisting elements are
* denoted as '·'.
*
* \sa ThreeWayStructure, CircularStructure, OrthogonalStructure,
* DiagonalStructure
*/
class PCL_CLASS StarStructure : public StructuringElement
{
public:
/*!
* Constructs a star structure of the specified \a size.
*/
StarStructure( int size )
: StructuringElement( size, 1 )
{
}
/*!
* Copy constructor.
*/
StarStructure( const StarStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new StarStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %StarStructure, this member function always
* returns false.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k == 0 )
return false;
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k == 0 )
int n2 = Size() >> 1;
if ( i == n2 || j == n2 )
return true;
if ( j == i || j == Size()-i-1 )
{
float n2 = 0.5F*Size();
float di = i+0.5F - n2;
float dj = j+0.5F - n2;
return di*di + dj*dj <= n2*n2;
}
return false;
}
};
// ----------------------------------------------------------------------------
/*!
* \class ThreeWayStructure
* \brief Standard three-way structure.
*
* The <em>standard three-way structure</em> of size 5 is defined as follows:
*
* <pre>
* Way #0 Way #1 Way #2
*
* · · x · · x · · · x · · · · ·
* · · x · · · x · x · · · · · ·
* x x · x x · · · · · · · x · ·
* · · x · · · x · x · · · · · ·
* · · x · · x · · · x · · · · ·
* </pre>
*
* where existing elements are marked as 'x' and nonexisting elements are
* denoted as '·'.
*
* The standard three-way structure leads to ranking operations where data
* from different spatial directions are ranked separately. When used to apply
* morphological operators, standard three-way structures can preserve edges
* better than box structures, especially when applied recursively.
*
* \sa CircularStructure, OrthogonalStructure, DiagonalStructure, StarStructure
*/
class PCL_CLASS ThreeWayStructure : public StructuringElement
{
public:
/*!
* Constructs a standard three-way structure of the specified \a size.
*/
ThreeWayStructure( int size )
: StructuringElement( size, 3 )
{
}
/*!
* Copy constructor.
*/
ThreeWayStructure( const ThreeWayStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new ThreeWayStructure( *this );
}
/*!
* Returns true iff this is a <em>box structure</em>. All elements in a box
* structure are <em>existing elements</em>.
*
* As reimplemented by %ThreeWayStructure, this member function always
* returns false.
*/
bool IsBox( int k ) const override
{
PCL_PRECONDITION( k >= 0 && k < 3 )
return false;
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k >= 0 && k < 3 )
int n2 = Size() >> 1;
switch ( k )
{
default:
case 0: // central element
return i == n2 && j == n2;
case 1: // horizontal and vertical elements
return i == n2 || j == n2;
case 2: // diagonal elements
return (j == i || j == Size()-i-1) && i != n2;
}
}
};
// ----------------------------------------------------------------------------
/*!
* \class BitmapStructure
* \brief A structuring element where static strings are used to define custom
* existence matrices.
*
* %BitmapStructure allows you to build a structuring element using character
* strings to define the existence of structure elements. Each string defines a
* structure way, where 'x' characters correspond to existing structure
* elements. For example, the following array of static strings:
*
* <pre>
* const char* B[] = { "--x--"
* "-xxx-"
* "xxxxx"
* "-xxx-"
* "--x--",
* //
* "-xxx-"
* "xxxxx"
* "xxxxx"
* "xxxxx"
* "-xxx-" };
* </pre>
*
* would define a 5x5 structure with two ways. 'x' characters define existing
* elements; other character values ('-' in this case) are interpreted as
* nonexistent elements. The corresponding %BitmapStructure object would be
* constructed as follows:
*
* <tt>BitmapStructure S( B, 5, 2 );</tt>
*
* This class is a convenient, straightforward approach to defining multi-way
* custom structuring elements that can be used directly with the
* MorphologicalTransformation class.
*/
class PCL_CLASS BitmapStructure : public StructuringElement
{
public:
/*!
* Represents a structure bitmap. Each bitmap defines the existence matrix
* for a \e way of the structuring element.
*/
typedef IsoString bitmap;
/*!
* Represents a set of bitmaps used to define the structure ways in a
* %BitmapStructure object.
*/
typedef IsoStringList bitmap_set;
/*!
* Constructs a %BitmapStructure object of the specified \a size and \a n
* number of ways.
*
* \param bitmaps An array of null-terminated strings representing the
* set of ways in this structuring element. There must be
* \a n contiguous null-terminated strings of length
* \a size*size characters at the address specified by
* this argument. In these strings, 'x' characters
* correspond to existing structure elements; other
* character values will be interpreted as nonexistent
* structure elements.
*
* \param size Size of this structure. Must be an odd integer >= 3.
*
* \param n Number of ways in this structure. Must be >= 1.
*/
BitmapStructure( const char** bitmaps, int size, int n = 1 )
: StructuringElement( size, n )
{
PCL_PRECONDITION( bitmaps != nullptr )
PCL_PRECONDITION( *bitmaps != '\0' )
for ( int i = 0; i < NumberOfWays(); ++i )
m_bitmaps.Add( bitmap( bitmaps[i] ) );
}
/*!
* Copy constructor.
*/
BitmapStructure( const BitmapStructure& ) = default;
/*!
*/
StructuringElement* Clone() const override
{
return new BitmapStructure( *this );
}
/*!
*/
bool ElementExists( int i, int j, int k ) const override
{
PCL_PRECONDITION( i >= 0 && i < Size() )
PCL_PRECONDITION( j >= 0 && j < Size() )
PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
return m_bitmaps[k][i + j*Size()] == 'x';
}
protected:
bitmap_set m_bitmaps;
};
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_StructuringElement_h
// ----------------------------------------------------------------------------
// EOF pcl/StructuringElement.h - Released 2022-03-12T18:59:29Z