PCL
FFTRegistration.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/FFTRegistration.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_FFTRegistration_h
53 #define __PCL_FFTRegistration_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/ImageVariant.h>
60 
61 namespace pcl
62 {
63 
64 // ----------------------------------------------------------------------------
65 
90 class PCL_CLASS FFTRegistrationEngine
91 {
92 public:
93 
97  FFTRegistrationEngine() = default;
98 
103 
108  : m_fftReference( std::move( x.m_fftReference ) )
109  {
110  }
111 
116  {
117  }
118 
122  bool IsInitialized() const
123  {
124  return !m_fftReference.IsEmpty();
125  }
126 
136  template <class P>
137  void Initialize( const pcl::GenericImage<P>& image )
138  {
139  Reset();
140  m_fftReference = DoInitialize( image );
141  }
142 
151  void Initialize( const ImageVariant& image )
152  {
153  Reset();
154  if ( image )
155  if ( image.IsComplexSample() )
156  switch ( image.BitsPerSample() )
157  {
158  case 32: m_fftReference = DoInitialize( static_cast<const ComplexImage&>( *image ) ); break;
159  case 64: m_fftReference = DoInitialize( static_cast<const DComplexImage&>( *image ) ); break;
160  }
161  else if ( image.IsFloatSample() )
162  switch ( image.BitsPerSample() )
163  {
164  case 32: m_fftReference = DoInitialize( static_cast<const Image&>( *image ) ); break;
165  case 64: m_fftReference = DoInitialize( static_cast<const DImage&>( *image ) ); break;
166  }
167  else
168  switch ( image.BitsPerSample() )
169  {
170  case 8: m_fftReference = DoInitialize( static_cast<const UInt8Image&>( *image ) ); break;
171  case 16: m_fftReference = DoInitialize( static_cast<const UInt16Image&>( *image ) ); break;
172  case 32: m_fftReference = DoInitialize( static_cast<const UInt32Image&>( *image ) ); break;
173  }
174  }
175 
185  {
186  return m_fftReference;
187  }
188 
194  void Reset()
195  {
196  m_fftReference.FreeData();
197  }
198 
205  template <class P>
206  void Evaluate( const pcl::GenericImage<P>& image )
207  {
208  PCL_PRECONDITION( IsInitialized() )
209  if ( IsInitialized() )
210  DoEvaluate( image );
211  }
212 
220  void Evaluate( const ImageVariant& image )
221  {
222  PCL_PRECONDITION( IsInitialized() )
223  if ( IsInitialized() )
224  if ( image )
225  if ( image.IsComplexSample() )
226  switch ( image.BitsPerSample() )
227  {
228  case 32: DoEvaluate( static_cast<const pcl::ComplexImage&>( *image ) ); break;
229  case 64: DoEvaluate( static_cast<const pcl::DComplexImage&>( *image ) ); break;
230  }
231  else if ( image.IsFloatSample() )
232  switch ( image.BitsPerSample() )
233  {
234  case 32: DoEvaluate( static_cast<const pcl::Image&>( *image ) ); break;
235  case 64: DoEvaluate( static_cast<const pcl::DImage&>( *image ) ); break;
236  }
237  else
238  switch ( image.BitsPerSample() )
239  {
240  case 8: DoEvaluate( static_cast<const pcl::UInt8Image&>( *image ) ); break;
241  case 16: DoEvaluate( static_cast<const pcl::UInt16Image&>( *image ) ); break;
242  case 32: DoEvaluate( static_cast<const pcl::UInt32Image&>( *image ) ); break;
243  }
244  }
245 
246 protected:
247 
248  // DFT of the reference image.
249  ComplexImage m_fftReference;
250 
251  virtual ComplexImage DoInitialize( const pcl::Image& ) = 0;
252  virtual ComplexImage DoInitialize( const pcl::DImage& ) = 0;
253  virtual ComplexImage DoInitialize( const pcl::ComplexImage& ) = 0;
254  virtual ComplexImage DoInitialize( const pcl::DComplexImage& ) = 0;
255  virtual ComplexImage DoInitialize( const pcl::UInt8Image& ) = 0;
256  virtual ComplexImage DoInitialize( const pcl::UInt16Image& ) = 0;
257  virtual ComplexImage DoInitialize( const pcl::UInt32Image& ) = 0;
258 
259  virtual void DoEvaluate( const pcl::Image& ) = 0;
260  virtual void DoEvaluate( const pcl::DImage& ) = 0;
261  virtual void DoEvaluate( const pcl::ComplexImage& ) = 0;
262  virtual void DoEvaluate( const pcl::DComplexImage& ) = 0;
263  virtual void DoEvaluate( const pcl::UInt8Image& ) = 0;
264  virtual void DoEvaluate( const pcl::UInt16Image& ) = 0;
265  virtual void DoEvaluate( const pcl::UInt32Image& ) = 0;
266 };
267 
268 // ----------------------------------------------------------------------------
269 
290 template <class O> inline
292 {
293  if ( !R.IsInitialized() )
294  R.Initialize( image );
295  else
296  R.Evaluate( image );
297  return R;
298 }
299 
300 // ----------------------------------------------------------------------------
301 
312 class PCL_CLASS FFTTranslation : public FFTRegistrationEngine
313 {
314 public:
315 
319  FFTTranslation() = default;
320 
324  ~FFTTranslation() override
325  {
326  }
327 
336  {
337  return m_largeTranslations;
338  }
339 
350  void EnableLargeTranslations( bool enable = true )
351  {
352  if ( enable != m_largeTranslations )
353  {
354  Reset();
355  m_largeTranslations = enable;
356  }
357  }
358 
372  void DisableLargeTranslations( bool disable = true )
373  {
374  EnableLargeTranslations( !disable );
375  }
376 
386  const FPoint& Delta() const
387  {
388  return m_delta;
389  }
390 
397  float DeltaX() const
398  {
399  return m_delta.x;
400  }
401 
408  float DeltaY() const
409  {
410  return m_delta.y;
411  }
412 
418  float Peak() const
419  {
420  return m_peak;
421  }
422 
423 protected:
424 
425  // Allow translations > size/2.
426  // Warning: a lot of memory may be necessary --four times more.
427  bool m_largeTranslations = false;
428 
429  // Evaluation result.
430  FPoint m_delta = 0.0F;
431 
432  // Peak value detected in the phase matrix.
433  float m_peak = 0.0F;
434 
435  ComplexImage DoInitialize( const pcl::Image& ) override;
436  ComplexImage DoInitialize( const pcl::DImage& ) override;
437  ComplexImage DoInitialize( const pcl::ComplexImage& ) override;
438  ComplexImage DoInitialize( const pcl::DComplexImage& ) override;
439  ComplexImage DoInitialize( const pcl::UInt8Image& ) override;
440  ComplexImage DoInitialize( const pcl::UInt16Image& ) override;
441  ComplexImage DoInitialize( const pcl::UInt32Image& ) override;
442 
443  void DoEvaluate( const pcl::Image& ) override;
444  void DoEvaluate( const pcl::DImage& ) override;
445  void DoEvaluate( const pcl::ComplexImage& ) override;
446  void DoEvaluate( const pcl::DComplexImage& ) override;
447  void DoEvaluate( const pcl::UInt8Image& ) override;
448  void DoEvaluate( const pcl::UInt16Image& ) override;
449  void DoEvaluate( const pcl::UInt32Image& ) override;
450 };
451 
452 // ----------------------------------------------------------------------------
453 
469 {
470 public:
471 
478 
483  {
484  }
485 
490  bool EvaluatesScaling() const
491  {
492  return m_evaluateScaling;
493  }
494 
498  void EnableScalingEvaluation( bool enable = true )
499  {
500  if ( enable != m_evaluateScaling )
501  {
502  Reset();
503  m_evaluateScaling = enable;
504  }
505  }
506 
513  void DisableScalingEvaluation( bool disable = true )
514  {
515  EnableScalingEvaluation( !disable );
516  }
517 
524  float LowFrequencyCutoff() const
525  {
526  return m_lowFrequencyCutoff;
527  }
528 
534  {
535  return LowFrequencyCutoff() > 0;
536  }
537 
548  void SetLowFrequencyCutoff( float r )
549  {
550  m_lowFrequencyCutoff = Range( r, 0.0F, 0.5F );
551  }
552 
559  float RotationAngle() const
560  {
561  return m_rotationAngle;
562  }
563 
570  float ScalingRatio() const
571  {
572  return m_scalingRatio;
573  }
574 
575 protected:
576 
577  // Evaluate rotation+scaling, or just rotation?
578  bool m_evaluateScaling = false;
579 
580  // Low-frequency cutoff, as a fraction of the DFT radius.
581  float m_lowFrequencyCutoff = 1.0F/200;
582 
583  // Evaluation result
584  float m_rotationAngle = 0.0F; // radians
585  float m_scalingRatio = 1.0F; // pixels
586 
587  ComplexImage DoInitialize( const pcl::Image& ) override;
588  ComplexImage DoInitialize( const pcl::DImage& ) override;
589  ComplexImage DoInitialize( const pcl::ComplexImage& ) override;
590  ComplexImage DoInitialize( const pcl::DComplexImage& ) override;
591  ComplexImage DoInitialize( const pcl::UInt8Image& ) override;
592  ComplexImage DoInitialize( const pcl::UInt16Image& ) override;
593  ComplexImage DoInitialize( const pcl::UInt32Image& ) override;
594 
595  void DoEvaluate( const pcl::Image& ) override;
596  void DoEvaluate( const pcl::DImage& ) override;
597  void DoEvaluate( const pcl::ComplexImage& ) override;
598  void DoEvaluate( const pcl::DComplexImage& ) override;
599  void DoEvaluate( const pcl::UInt8Image& ) override;
600  void DoEvaluate( const pcl::UInt16Image& ) override;
601  void DoEvaluate( const pcl::UInt32Image& ) override;
602 };
603 
604 // ----------------------------------------------------------------------------
605 
606 } // pcl
607 
608 #endif // __PCL_FFTRegistration_h
609 
610 // ----------------------------------------------------------------------------
611 // EOF pcl/FFTRegistration.h - Released 2024-06-18T15:48:54Z
Base class of FFT-based image registration algorithms.
void Initialize(const pcl::GenericImage< P > &image)
const ComplexImage & DFTOfReferenceImage() const
void Initialize(const ImageVariant &image)
void Evaluate(const ImageVariant &image)
FFTRegistrationEngine(const FFTRegistrationEngine &)=default
FFTRegistrationEngine(FFTRegistrationEngine &&x)
void Evaluate(const pcl::GenericImage< P > &image)
FFT registration engine: rotation and scaling
void EnableScalingEvaluation(bool enable=true)
void SetLowFrequencyCutoff(float r)
void DisableScalingEvaluation(bool disable=true)
FFT registration engine: translation
const FPoint & Delta() const
FFTTranslation()=default
float DeltaX() const
void EnableLargeTranslations(bool enable=true)
float DeltaY() const
bool AreLargeTranslationsEnabled() const
void DisableLargeTranslations(bool disable=true)
~FFTTranslation() override
Implements a generic, two-dimensional, shared or local image.
Definition: Image.h:278
A generic point in the two-dimensional space.
Definition: Point.h:100
Acts like a union for all types of images in PCL, with optional class-wide ownership of transported i...
Definition: ImageVariant.h:322
bool IsFloatSample() const noexcept
Definition: ImageVariant.h:441
bool IsComplexSample() const noexcept
Definition: ImageVariant.h:449
int BitsPerSample() const noexcept
Definition: ImageVariant.h:458
Array< T, A > & operator<<(Array< T, A > &x, const V &v)
Definition: Array.h:2295
constexpr const T & Range(const T &x, const T &a, const T &b) noexcept
Definition: Utility.h:190
PCL root namespace.
Definition: AbstractImage.h:77