PCL
StructuringElement.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.1.19
6 // ----------------------------------------------------------------------------
7 // pcl/StructuringElement.h - Released 2019-11-07T10:59:34Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2019 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (http://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_StructuringElement_h
53 #define __PCL_StructuringElement_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/Atomic.h>
61 #include <pcl/AutoLock.h>
62 #include <pcl/Math.h>
63 #include <pcl/Rotate.h> // Reverse()
64 #include <pcl/StringList.h> // BitmapStructure
65 #include <pcl/Utility.h>
66 #include <pcl/Vector.h>
67 
68 #include <memory.h>
69 
70 namespace pcl
71 {
72 
73 // ----------------------------------------------------------------------------
74 
107 class PCL_CLASS StructuringElement
108 {
109 public:
110 
115 
120 
125 
130 
135  StructuringElement( int size = 3, int n = 1 ) :
136  m_size( Max( 3, size|1 ) ),
137  m_mask( Max( 1, n ) ),
138  m_count( 0, Max( 1, n ) )
139  {
140  PCL_PRECONDITION( size >= 3 )
141  PCL_PRECONDITION( (size & 1) != 0 )
142  PCL_PRECONDITION( n >= 1 )
143  for ( int k = 0; k < NumberOfWays(); ++k )
144  m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
145  }
146 
151  m_size( x.m_size ),
152  m_mask( x.NumberOfWays() ),
153  m_count( 0, x.NumberOfWays() )
154  {
155  for ( int k = 0; k < NumberOfWays(); ++k )
156  m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
157  }
158 
163  {
164  }
165 
170  virtual StructuringElement* Clone() const = 0;
171 
175  StructuringElement& operator =( const StructuringElement& x )
176  {
177  if ( &x != this )
178  {
179  volatile AutoLock lock( m_mutex );
180  m_size = x.m_size;
181  m_mask = existence_mask_set( x.NumberOfWays() );
182  m_count = existence_mask_count( 0, x.NumberOfWays() );
183  m_reflected = false;
184  m_initialized = 0;
185  for ( int k = 0; k < NumberOfWays(); ++k )
186  m_mask[k] = existence_mask( existence_mask_element( 0 ), NumberOfElements() );
187  }
188  return *this;
189  }
190 
194  int NumberOfWays() const
195  {
196  return int( m_mask.Length() );
197  }
198 
202  int Size() const
203  {
204  return m_size;
205  }
206 
211  int NumberOfElements() const
212  {
213  return m_size*m_size;
214  }
215 
228  virtual bool IsBox( int k ) const
229  {
230  PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
231  Initialize();
232  return m_count[k] == NumberOfElements();
233  }
234 
247  virtual bool ElementExists( int i, int j, int k ) const
248  {
249  PCL_PRECONDITION( i >= 0 && i < m_size )
250  PCL_PRECONDITION( j >= 0 && j < m_size )
251  PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
252  return true;
253  }
254 
276  template <typename T>
277  void PeekElements( T* h1, int& nh1, const T* h, int k ) const
278  {
279  PCL_PRECONDITION( h1 != 0 )
280  PCL_PRECONDITION( h != 0 )
281  PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
282  Initialize();
283  nh1 = 0;
284  for ( existence_mask::const_iterator m = m_mask[k].Begin(), m1 = m_mask[k].End(); m < m1; ++m, ++h )
285  if ( *m )
286  {
287  *h1++ = *h;
288  ++nh1;
289  }
290  }
291 
299  void Reflect()
300  {
301  Initialize();
302  for ( existence_mask_set::iterator i = m_mask.Begin(); i != m_mask.End(); ++i )
303  pcl::Reverse( i->Begin(), i->End() );
304  m_reflected = !m_reflected;
305  }
306 
312  bool IsReflected() const
313  {
314  return m_reflected;
315  }
316 
338  void Initialize() const
339  {
340  if ( !m_initialized )
341  {
342  volatile AutoLock lock( m_mutex );
343  if ( m_initialized.Load() == 0 )
344  {
345  int N = NumberOfWays();
346  for ( int k = 0; k < N; ++k )
347  {
348  m_count[k] = 0; // redundant, but doesn't hurt
349  existence_mask::iterator m = m_mask[k].Begin();
350  for ( int i = 0; i < m_size; ++i )
351  for ( int j = 0; j < m_size; ++j, ++m )
352  if ( ElementExists( i, j, k ) )
353  {
354  *m = 1;
355  ++m_count[k];
356  }
357  else
358  *m = 0;
359  }
360 
361  m_initialized.Store( 1 );
362  }
363  }
364  }
365 
366 private:
367 
368  /*
369  * Structure size.
370  */
371  int m_size;
372 
373  /*
374  * Element existence masks (one mask per way).
375  * An element exists iff its corresponding mask element is nonzero.
376  */
377  mutable existence_mask_set m_mask;
378 
379  /*
380  * Number of existing elements for each way.
381  */
382  mutable existence_mask_count m_count;
383 
384  /*
385  * Flag true when the structure has been reflected.
386  */
387  bool m_reflected = false;
388 
389  /*
390  * Flag true when existence masks have been calculated.
391  */
392  mutable AtomicInt m_initialized;
393 
394  /*
395  * Thread synchronization.
396  */
397  mutable Mutex m_mutex;
398 };
399 
400 // ----------------------------------------------------------------------------
401 
421 class PCL_CLASS BoxStructure : public StructuringElement
422 {
423 public:
424 
428  BoxStructure( int size ) : StructuringElement( size, 1 )
429  {
430  }
431 
435  BoxStructure( const BoxStructure& ) = default;
436 
439  StructuringElement* Clone() const override
440  {
441  return new BoxStructure( *this );
442  }
443 
451  bool IsBox( int k ) const override
452  {
453  PCL_PRECONDITION( k == 0 )
454  return true;
455  }
456 };
457 
458 // ----------------------------------------------------------------------------
459 
484 class PCL_CLASS CircularStructure : public StructuringElement
485 {
486 public:
487 
491  CircularStructure( int diameter ) : StructuringElement( diameter, 1 )
492  {
493  }
494 
498  CircularStructure( const CircularStructure& ) = default;
499 
502  StructuringElement* Clone() const override
503  {
504  return new CircularStructure( *this );
505  }
506 
514  bool IsBox( int k ) const override
515  {
516  PCL_PRECONDITION( k == 0 )
517  return false;
518  }
519 
522  bool ElementExists( int i, int j, int k ) const override
523  {
524  PCL_PRECONDITION( i >= 0 && i < Size() )
525  PCL_PRECONDITION( j >= 0 && j < Size() )
526  PCL_PRECONDITION( k == 0 )
527  float n2 = 0.5F*Size();
528  float di = i+0.5F - n2;
529  float dj = j+0.5F - n2;
530  return di*di + dj*dj <= n2*n2;
531  }
532 };
533 
534 // ----------------------------------------------------------------------------
535 
555 class PCL_CLASS OrthogonalStructure : public StructuringElement
556 {
557 public:
558 
562  OrthogonalStructure( int size ) : StructuringElement( size, 1 )
563  {
564  }
565 
569  OrthogonalStructure( const OrthogonalStructure& ) = default;
570 
573  StructuringElement* Clone() const override
574  {
575  return new OrthogonalStructure( *this );
576  }
577 
585  bool IsBox( int k ) const override
586  {
587  PCL_PRECONDITION( k == 0 )
588  return false;
589  }
590 
593  bool ElementExists( int i, int j, int k ) const override
594  {
595  PCL_PRECONDITION( i >= 0 && i < Size() )
596  PCL_PRECONDITION( j >= 0 && j < Size() )
597  PCL_PRECONDITION( k == 0 )
598  int n2 = Size() >> 1;
599  return i == n2 || j == n2;
600  }
601 };
602 
603 // ----------------------------------------------------------------------------
604 
624 class PCL_CLASS DiagonalStructure : public StructuringElement
625 {
626 public:
627 
631  DiagonalStructure( int size ) : StructuringElement( size, 1 )
632  {
633  }
634 
638  DiagonalStructure( const DiagonalStructure& ) = default;
639 
642  StructuringElement* Clone() const override
643  {
644  return new DiagonalStructure( *this );
645  }
646 
654  bool IsBox( int k ) const override
655  {
656  PCL_PRECONDITION( k == 0 )
657  return false;
658  }
659 
662  bool ElementExists( int i, int j, int k ) const override
663  {
664  PCL_PRECONDITION( i >= 0 && i < Size() )
665  PCL_PRECONDITION( j >= 0 && j < Size() )
666  PCL_PRECONDITION( k == 0 )
667  return j == i || j == Size()-i-1;
668  }
669 };
670 
671 // ----------------------------------------------------------------------------
672 
695 class PCL_CLASS StarStructure : public StructuringElement
696 {
697 public:
698 
702  StarStructure( int size ) : StructuringElement( size, 1 )
703  {
704  }
705 
709  StarStructure( const StarStructure& ) = default;
710 
713  StructuringElement* Clone() const override
714  {
715  return new StarStructure( *this );
716  }
717 
725  bool IsBox( int k ) const override
726  {
727  PCL_PRECONDITION( k == 0 )
728  return false;
729  }
730 
733  bool ElementExists( int i, int j, int k ) const override
734  {
735  PCL_PRECONDITION( i >= 0 && i < Size() )
736  PCL_PRECONDITION( j >= 0 && j < Size() )
737  PCL_PRECONDITION( k == 0 )
738  int n2 = Size() >> 1;
739  if ( i == n2 || j == n2 )
740  return true;
741  if ( j == i || j == Size()-i-1 )
742  {
743  float n2 = 0.5F*Size();
744  float di = i+0.5F - n2;
745  float dj = j+0.5F - n2;
746  return di*di + dj*dj <= n2*n2;
747  }
748  return false;
749  }
750 };
751 
752 // ----------------------------------------------------------------------------
753 
780 class PCL_CLASS ThreeWayStructure : public StructuringElement
781 {
782 public:
783 
787  ThreeWayStructure( int size ) : StructuringElement( size, 3 )
788  {
789  }
790 
794  ThreeWayStructure( const ThreeWayStructure& ) = default;
795 
798  StructuringElement* Clone() const override
799  {
800  return new ThreeWayStructure( *this );
801  }
802 
810  bool IsBox( int k ) const override
811  {
812  PCL_PRECONDITION( k >= 0 && k < 3 )
813  return false;
814  }
815 
818  bool ElementExists( int i, int j, int k ) const override
819  {
820  PCL_PRECONDITION( i >= 0 && i < Size() )
821  PCL_PRECONDITION( j >= 0 && j < Size() )
822  PCL_PRECONDITION( k >= 0 && k < 3 )
823  int n2 = Size() >> 1;
824  switch ( k )
825  {
826  default:
827  case 0: // central element
828  return i == n2 && j == n2;
829  case 1: // horizontal and vertical elements
830  return i == n2 || j == n2;
831  case 2: // diagonal elements
832  return (j == i || j == Size()-i-1) && i != n2;
833  }
834  }
835 };
836 
837 // ----------------------------------------------------------------------------
838 
874 class PCL_CLASS BitmapStructure : public StructuringElement
875 {
876 public:
877 
882  typedef IsoString bitmap;
883 
889 
907  BitmapStructure( const char** bitmaps, int size, int n = 1 ) :
908  StructuringElement( size, n )
909  {
910  PCL_PRECONDITION( bitmaps != nullptr )
911  PCL_PRECONDITION( *bitmaps != '\0' )
912  for ( int i = 0; i < NumberOfWays(); ++i )
913  m_bitmaps.Add( bitmap( bitmaps[i] ) );
914  }
915 
919  BitmapStructure( const BitmapStructure& ) = default;
920 
923  StructuringElement* Clone() const override
924  {
925  return new BitmapStructure( *this );
926  }
927 
930  bool ElementExists( int i, int j, int k ) const override
931  {
932  PCL_PRECONDITION( i >= 0 && i < Size() )
933  PCL_PRECONDITION( j >= 0 && j < Size() )
934  PCL_PRECONDITION( k >= 0 && k < NumberOfWays() )
935  return m_bitmaps[k][i + j*Size()] == 'x';
936  }
937 
938 protected:
939 
940  bitmap_set m_bitmaps;
941 };
942 
943 // ----------------------------------------------------------------------------
944 
945 } // pcl
946 
947 #endif // __PCL_StructuringElement_h
948 
949 // ----------------------------------------------------------------------------
950 // EOF pcl/StructuringElement.h - Released 2019-11-07T10:59:34Z
bool ElementExists(int i, int j, int k) const override
Abstract base class of all PCL structuring elements.
GenericVector< existence_mask_element > existence_mask
StructuringElement * Clone() const override
Adaptive mutual exclusion lock variable.
Definition: Mutex.h:208
Atomic operations on integers.
Definition: Atomic.h:94
Dynamic list of 8-bit strings.
void PeekElements(T *h1, int &nh1, const T *h, int k) const
PCL root namespace.
Definition: AbstractImage.h:76
bool IsBox(int k) const override
StructuringElement * Clone() const override
StructuringElement * Clone() const override
Standard box (square) structure.
bool ElementExists(int i, int j, int k) const override
StructuringElement * Clone() const override
virtual bool ElementExists(int i, int j, int k) const
A structuring element where static strings are used to define custom existence matrices.
StructuringElement(const StructuringElement &x)
bool ElementExists(int i, int j, int k) const override
Generic vector of arbitrary length.
Definition: Vector.h:106
StructuringElement(int size=3, int n=1)
Standard three-way structure.
constexpr const T & Max(const T &a, const T &b)
Definition: Utility.h:119
virtual bool IsBox(int k) const
bool ElementExists(int i, int j, int k) const override
bool ElementExists(int i, int j, int k) const override
bool ElementExists(int i, int j, int k) const override
Automatic mutex lock/unlock.
Definition: AutoLock.h:83
BitmapStructure(const char **bitmaps, int size, int n=1)
bool IsBox(int k) const override
StructuringElement * Clone() const override
const T * const_iterator
Definition: Vector.h:128
bool IsBox(int k) const override
GenericVector< existence_mask > existence_mask_set
Standard circular structure.
bool IsBox(int k) const override
StructuringElement * Clone() const override
Standard diagonal structure.
bool IsBox(int k) const override
StructuringElement * Clone() const override
bool IsBox(int k) const override
GenericVector< int > existence_mask_count
Standard star structure.
Standard orthogonal structure.
unsigned int uint32
Definition: Defs.h:600
Eight-bit string (ISO/IEC-8859-1 or UTF-8 string)
Definition: String.h:5387