PCL
GaussianFilter.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/GaussianFilter.h - Released 2024-06-18T15:48:54Z
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-2024 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 (https://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_GaussianFilter_h
53 #define __PCL_GaussianFilter_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/KernelFilter.h>
60 #include <pcl/Math.h>
61 
62 namespace pcl
63 {
64 
65 // ----------------------------------------------------------------------------
66 
97 class PCL_CLASS GaussianFilter : public KernelFilter
98 {
99 public:
100 
105  GaussianFilter() = default;
106 
112  GaussianFilter( float sigma, float epsilon = 0.01, const String& name = String() )
113  {
114  Initialize( sigma, epsilon, 1, 0 );
115  Rename( name );
116  }
117 
124  GaussianFilter( float sigma, float epsilon, float rho, float theta = 0, const String& name = String() )
125  {
126  Initialize( sigma, epsilon, rho, theta );
127  Rename( name );
128  }
129 
135  GaussianFilter( int n, float epsilon = 0.01, const String& name = String() )
136  {
137  Initialize( n, epsilon, 1, 0 );
138  Rename( name );
139  }
140 
147  GaussianFilter( int n, float epsilon, float rho, float theta = 0, const String& name = String() )
148  {
149  Initialize( n, epsilon, rho, theta );
150  Rename( name );
151  }
152 
156  GaussianFilter( const GaussianFilter& ) = default;
157 
162 
165  KernelFilter* Clone() const override
166  {
167  return new GaussianFilter( *this );
168  }
169 
179  SeparableFilter AsSeparableFilter( float tolerance = __PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE ) const override
180  {
181  if ( m_rho == 1 )
182  {
183  FVector v = coefficients.RowVector( Size()>>1 );
184  return SeparableFilter( v, v );
185  }
186  return SeparableFilter();
187  }
188 
196  bool IsSeparable() const override
197  {
198  return m_rho == 1;
199  }
200 
204  GaussianFilter& operator =( const GaussianFilter& x )
205  {
206  (void)KernelFilter::operator =( x );
207  m_sigma = x.m_sigma;
208  m_epsilon = x.m_epsilon;
209  m_rho = x.m_rho;
210  m_theta = x.m_theta;
211  return *this;
212  }
213 
217  GaussianFilter& operator =( GaussianFilter&& x )
218  {
219  (void)KernelFilter::operator =( std::move( x ) );
220  m_sigma = x.m_sigma;
221  m_epsilon = x.m_epsilon;
222  m_rho = x.m_rho;
223  m_theta = x.m_theta;
224  return *this;
225  }
226 
231  float SigmaX() const
232  {
233  return m_sigma;
234  }
235 
240  float SigmaY() const
241  {
242  return m_rho*m_sigma;
243  }
244 
251  float Sigma() const
252  {
253  return SigmaX();
254  }
255 
259  float Truncation() const
260  {
261  return m_epsilon;
262  }
263 
268  float AspectRatio() const
269  {
270  return m_rho;
271  }
272 
278  float RotationAngle() const
279  {
280  return m_theta;
281  }
282 
287  double FWHMx() const
288  {
289  return 2.3548200450309493 * m_sigma;
290 
291  }
292 
297  double FWHMy() const
298  {
299  return m_rho * FWHMx();
300 
301  }
302 
309  double FWHM() const
310  {
311  return FWHMx();
312  }
313 
319  void Set( float sigma, float epsilon, float rho, float theta )
320  {
321  Initialize( sigma, epsilon, rho, theta );
322  }
323 
329  void Set( float sigma, float epsilon, float rho )
330  {
331  Initialize( sigma, epsilon, rho, m_theta );
332  }
333 
339  void Set( float sigma, float epsilon )
340  {
341  Initialize( sigma, epsilon, m_rho, m_theta );
342  }
343 
349  void Set( float sigma )
350  {
351  Initialize( sigma, m_epsilon, m_rho, m_theta );
352  }
353 
357  void SetSigma( float sigma )
358  {
359  Set( sigma );
360  }
361 
366  void SetTruncation( float epsilon )
367  {
368  Set( m_sigma, epsilon );
369  }
370 
375  void SetAspectRatio( float rho )
376  {
377  Set( m_sigma, m_epsilon, rho );
378  }
379 
384  void SetRotationAngle( float theta )
385  {
386  Set( m_sigma, m_epsilon, m_rho, theta );
387  }
388 
395  void Resize( int n ) override
396  {
397  Initialize( n, m_epsilon, m_rho, m_theta );
398  }
399 
403  friend void Swap( GaussianFilter& x1, GaussianFilter& x2 )
404  {
405  pcl::Swap( static_cast<KernelFilter&>( x1 ), static_cast<KernelFilter&>( x2 ) );
406  pcl::Swap( x1.m_sigma, x2.m_sigma );
407  pcl::Swap( x1.m_rho, x2.m_rho );
408  pcl::Swap( x1.m_theta, x2.m_theta );
409  pcl::Swap( x1.m_epsilon, x2.m_epsilon );
410  }
411 
412 private:
413 
414  float m_sigma = 2; // standard deviation, horizontal axis
415  float m_rho = 1; // vertical:horizontal axes ratio
416  float m_theta = 0; // rotation angle in radians, [0,+pi]
417  float m_epsilon = 0.01F; // maximum truncation error in sigma units
418 
419  void Initialize( float s, float e, float r, float a )
420  {
421  PCL_PRECONDITION( s > 0 )
422  PCL_PRECONDITION( e > 0 )
423  PCL_PRECONDITION( r >= 0 && r <= 1 )
424  PCL_PRECONDITION( a >= 0 && a <= Const<float>::pi() )
425  m_sigma = Abs( s );
426  m_epsilon = Abs( e );
427  m_rho = Range( r, 0.0F, 1.0F );
428  m_theta = Range( a, 0.0F, Const<float>::pi() );
429  KernelFilter::Resize( 1 + (Max( 1, RoundInt( m_sigma * Sqrt( -2*Ln( m_epsilon ) ) ) ) << 1) );
430  Rebuild();
431  }
432 
433  void Initialize( int n, float e, float r, float a )
434  {
435  PCL_PRECONDITION( n == 0 || n >= 3 && (n & 1) != 0 )
436  PCL_PRECONDITION( e > 0 )
437  PCL_PRECONDITION( r >= 0 && r <= 1 )
438  PCL_PRECONDITION( a >= 0 && a <= Const<float>::pi() )
439  KernelFilter::Resize( n );
440  m_epsilon = Abs( e );
441  m_sigma = (Size() >> 1)/Sqrt( -2*Ln( m_epsilon ) );
442  m_rho = Range( r, 0.0F, 1.0F );
443  m_theta = Range( a, 0.0F, Const<float>::pi() );
444  Rebuild();
445  }
446 
447  void Rebuild()
448  {
449  int size = Size();
450  if ( size == 0 )
451  return;
452 
453  float* __restrict__ h = *coefficients;
454  double sx = m_sigma;
455  double sy = m_rho * sx;
456 
457  if ( m_theta == 0 || m_rho == 1 )
458  {
459  double twosx2 = 2*sx*sx;
460  double twosy2 = 2*sy*sy;
461  for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy )
462  if ( dy > 0 )
463  for ( int dx = 0; dx < size; ++dx, ++h )
464  *h = *(h - ((dy+dy)*size));
465  else
466  for ( int dx = -n2; dx <= n2; ++dx, ++h )
467  *h = (dx > 0) ? *(h - (dx+dx)) : float( Exp( -(dx*dx/twosx2 + dy*dy/twosy2) ) );
468  }
469  else
470  {
471  double st, ct; SinCos( double( m_theta ), st, ct );
472  double sct = st*ct;
473  double st2 = st*st;
474  double ct2 = ct*ct;
475  double twosx2 = 2*sx*sx;
476  double twosy2 = 2*sy*sy;
477  double p1 = ct2/twosx2 + st2/twosy2;
478  double p2 = sct/twosy2 - sct/twosx2;
479  double p3 = st2/twosx2 + ct2/twosy2;
480  for ( int n2 = size >> 1, dy = -n2; dy <= n2; ++dy )
481  {
482  double twop2dy = 2*p2*dy;
483  double p3dy2 = p3*dy*dy;
484  for ( int dx = -n2; dx <= n2; ++dx, ++h )
485  *h = float( Exp( -(p1*dx*dx + twop2dy*dx + p3dy2) ) );
486  }
487  }
488  }
489 };
490 
491 // ----------------------------------------------------------------------------
492 
493 } // pcl
494 
495 #endif // __PCL_GaussianFilter_h
496 
497 // ----------------------------------------------------------------------------
498 // EOF pcl/GaussianFilter.h - Released 2024-06-18T15:48:54Z
Fundamental numeric constants.
Definition: Constants.h:73
A kernel filter implementing a discrete Gaussian distribution in two dimensions.
void Set(float sigma, float epsilon, float rho, float theta)
GaussianFilter(int n, float epsilon, float rho, float theta=0, const String &name=String())
friend void Swap(GaussianFilter &x1, GaussianFilter &x2)
void SetSigma(float sigma)
void Resize(int n) override
void Set(float sigma)
float Sigma() const
GaussianFilter()=default
GaussianFilter(float sigma, float epsilon, float rho, float theta=0, const String &name=String())
float RotationAngle() const
double FWHMx() const
void Set(float sigma, float epsilon, float rho)
SeparableFilter AsSeparableFilter(float tolerance=__PCL_DEFAULT_FILTER_SEPARABILITY_TOLERANCE) const override
GaussianFilter(float sigma, float epsilon=0.01, const String &name=String())
void SetAspectRatio(float rho)
GaussianFilter(const GaussianFilter &)=default
double FWHMy() const
float AspectRatio() const
bool IsSeparable() const override
void SetRotationAngle(float theta)
KernelFilter * Clone() const override
void Set(float sigma, float epsilon)
void SetTruncation(float epsilon)
float SigmaY() const
double FWHM() const
GaussianFilter(GaussianFilter &&)=default
float Truncation() const
GaussianFilter(int n, float epsilon=0.01, const String &name=String())
float SigmaX() const
Generic vector of arbitrary length.
Definition: Vector.h:107
Kernel filter in two dimensions.
Definition: KernelFilter.h:90
Separable filter in two dimensions.
Unicode (UTF-16) string.
Definition: String.h:8113
Complex< T > Sqrt(const Complex< T > &c) noexcept
Definition: Complex.h:674
Complex< T > Exp(const Complex< T > &c) noexcept
Definition: Complex.h:714
Complex< T > Ln(const Complex< T > &c) noexcept
Definition: Complex.h:725
T Abs(const Complex< T > &c) noexcept
Definition: Complex.h:429
void SinCos(T x, T &sx, T &cx) noexcept
Definition: Math.h:1030
int RoundInt(T x) noexcept
Definition: Math.h:1503
void Swap(GenericPoint< T > &p1, GenericPoint< T > &p2) noexcept
Definition: Point.h:1459
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
Definition: Utility.h:190
constexpr const T & Max(const T &a, const T &b) noexcept
Definition: Utility.h:119
PCL root namespace.
Definition: AbstractImage.h:77