Support for XISF
This commit is contained in:
+956
@@ -0,0 +1,956 @@
|
||||
// ____ ______ __
|
||||
// / __ \ / ____// /
|
||||
// / /_/ // / / /
|
||||
// / ____// /___ / /___ 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
|
||||
Reference in New Issue
Block a user