// ____ ______ __ // / __ \ / ____// / // / /_/ // / / / // / ____// /___ / /___ PixInsight Class Library // /_/ \____//_____/ PCL 2.4.23 // ---------------------------------------------------------------------------- // pcl/FFTRegistration.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_FFTRegistration_h #define __PCL_FFTRegistration_h /// \file pcl/FFTRegistration.h #include #include namespace pcl { // ---------------------------------------------------------------------------- /*! * \class FFTRegistrationEngine * \brief Base class of %FFT-based image registration algorithms * * Image registration based on phase correlation via fast Fourier transforms. * * References * * \li Araiza, R., Xie, H. & al., 2002. Automatic referencing of multi-spectral * images. Proceedings of 15th IEEE Southwest Symposium on Image Analysis and * Interpretation, Santa Fe, USA, 21-25. * * \li Xie, H. & al., 2000. Automatic image registration based on a %FFT * algorithm and IDL/ENVI. Proceedings of the ICORG-2000 International * Conference on Remote Sensing and GIS/GPS, Hyderabad, India, I-397~I-402. * * \li Harold S., Stone T. & al., 2003. Analysis of image registration noise * due to rotationally dependent aliasing. Journal of Visual Communication and * Image Representation 14, 114-135. * * \li DeCastro, E., Morandi, C., 1987. Registration of translated and rotated * images using finite Fourier transforms. IEEE Transactions on Pattern * Analysis and Machine Intelligence 95, 700-703. */ class PCL_CLASS FFTRegistrationEngine { public: /*! * Constructs an %FFTRegistrationEngine object. */ FFTRegistrationEngine() = default; /*! * Copy constructor. */ FFTRegistrationEngine( const FFTRegistrationEngine& ) = default; /*! * Move constructor. */ FFTRegistrationEngine( FFTRegistrationEngine&& x ) : m_fftReference( std::move( x.m_fftReference ) ) { } /*! * Destroys an %FFTRegistrationEngine object. */ virtual ~FFTRegistrationEngine() { } /*! * Returns true iff this engine has been initialized. */ bool IsInitialized() const { return !m_fftReference.IsEmpty(); } /*! * Initializes this registration engine for the specified reference image * \a image. * * Once initialized, subsequent calls to Evaluate() will compute * registration parameters for target images referred to the same reference * image, until a new initialization is performed, or until the Reset() * member function is called. */ template void Initialize( const pcl::GenericImage

& image ) { Reset(); m_fftReference = DoInitialize( image ); } /*! * Initializes this registration engine for the specified reference * \a image. * * This member function behaves like Initialize( const GenericImage

& ), * except that it receives a reference to ImageVariant. The engine is * initialized for the image transported by the ImageVariant object. */ void Initialize( const ImageVariant& image ) { Reset(); if ( image ) if ( image.IsComplexSample() ) switch ( image.BitsPerSample() ) { case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; case 64: m_fftReference = DoInitialize( static_cast( *image ) ); break; } else if ( image.IsFloatSample() ) switch ( image.BitsPerSample() ) { case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; case 64: m_fftReference = DoInitialize( static_cast( *image ) ); break; } else switch ( image.BitsPerSample() ) { case 8: m_fftReference = DoInitialize( static_cast( *image ) ); break; case 16: m_fftReference = DoInitialize( static_cast( *image ) ); break; case 32: m_fftReference = DoInitialize( static_cast( *image ) ); break; } } /*! * Returns a reference to the discrete Fourier transform of the reference * image. * * The reference image is the image specified in the last call to * Initialize(). This function returns an empty image if this registration * engine has not been initialized. */ const ComplexImage& DFTOfReferenceImage() const { return m_fftReference; } /*! * Resets this registration engine and deallocates all internal data * structures. The engine will have to be initialized before performing new * evaluations of registration parameters. */ void Reset() { m_fftReference.FreeData(); } /*! * Evaluates a target image \a image to compute registration parameters. * * Before calling this function, the engina must be initialized by calling * Initialize() with a reference image. */ template void Evaluate( const pcl::GenericImage

& image ) { PCL_PRECONDITION( IsInitialized() ) if ( IsInitialized() ) DoEvaluate( image ); } /*! * Evaluates a target image \a vimg to compute registration parameters. * * This member function behaves like Evaluate( const GenericImage

& ), * except that it receives a reference to ImageVariant. The engine evaluates * for the image transported by the ImageVariant object. */ void Evaluate( const ImageVariant& image ) { PCL_PRECONDITION( IsInitialized() ) if ( IsInitialized() ) if ( image ) if ( image.IsComplexSample() ) switch ( image.BitsPerSample() ) { case 32: DoEvaluate( static_cast( *image ) ); break; case 64: DoEvaluate( static_cast( *image ) ); break; } else if ( image.IsFloatSample() ) switch ( image.BitsPerSample() ) { case 32: DoEvaluate( static_cast( *image ) ); break; case 64: DoEvaluate( static_cast( *image ) ); break; } else switch ( image.BitsPerSample() ) { case 8: DoEvaluate( static_cast( *image ) ); break; case 16: DoEvaluate( static_cast( *image ) ); break; case 32: DoEvaluate( static_cast( *image ) ); break; } } protected: // DFT of the reference image. ComplexImage m_fftReference; virtual ComplexImage DoInitialize( const pcl::Image& ) = 0; virtual ComplexImage DoInitialize( const pcl::DImage& ) = 0; virtual ComplexImage DoInitialize( const pcl::ComplexImage& ) = 0; virtual ComplexImage DoInitialize( const pcl::DComplexImage& ) = 0; virtual ComplexImage DoInitialize( const pcl::UInt8Image& ) = 0; virtual ComplexImage DoInitialize( const pcl::UInt16Image& ) = 0; virtual ComplexImage DoInitialize( const pcl::UInt32Image& ) = 0; virtual void DoEvaluate( const pcl::Image& ) = 0; virtual void DoEvaluate( const pcl::DImage& ) = 0; virtual void DoEvaluate( const pcl::ComplexImage& ) = 0; virtual void DoEvaluate( const pcl::DComplexImage& ) = 0; virtual void DoEvaluate( const pcl::UInt8Image& ) = 0; virtual void DoEvaluate( const pcl::UInt16Image& ) = 0; virtual void DoEvaluate( const pcl::UInt32Image& ) = 0; }; // ---------------------------------------------------------------------------- /*! * \defgroup fft_registration_functions FFT-Based Registration Operators */ /*! * Initializes a %FFT registration engine or evaluates a target image. * * \param R %FFT registration engine. * \param image An image or ImageVariant for initialization or evaluation. * * If the engine has not still been initialized, it is initialized for the * \e reference image \a image. Once the engine has been initialized, it * evaluates registration parameters for the specified \e target image \a image. * * Returns a reference to the %FFT registration engine \a R. * * \sa FFTRegistrationEngine * * \ingroup fft_registration_functions */ template inline FFTRegistrationEngine& operator <<( FFTRegistrationEngine& R, const O& image ) { if ( !R.IsInitialized() ) R.Initialize( image ); else R.Evaluate( image ); return R; } // ---------------------------------------------------------------------------- /*! * \class FFTTranslation * \brief %FFT registration engine: translation * * %FFTTranslation evaluates translation image registration parameters. It * computes the offsets \e dx and \e dy required to register a target image on * a reference image, using an %FFT-based phase correlation algorithm. * * \sa FFTRotationAndScaling, FFTRegistrationEngine */ class PCL_CLASS FFTTranslation : public FFTRegistrationEngine { public: /*! * Constructs an %FFTTranslation object. */ FFTTranslation() = default; /*! * Destroys an %FFTTranslation object. */ virtual ~FFTTranslation() { } /*! * Returns true iff this registration engine can evaluate translations * greater than or equal to one half of the largest dimension of the * reference image. * * \sa EnableLargeTranslations(), DisableLargeTranslations() */ bool AreLargeTranslationsEnabled() const { return m_largeTranslations; } /*! * Enables or disables evaluation of large translations (>= one half of the * reference image dimension). * * \warning When large translations are enabled, the engine needs to double * the sizes of internal working matrices, which \e quadruplicates the * amount of required memory. * * \sa DisableLargeTranslations(), AreLargeTranslationsEnabled() */ void EnableLargeTranslations( bool enable = true ) { if ( enable != m_largeTranslations ) { Reset(); m_largeTranslations = enable; } } /*! * Disables or enables evaluation of large translations (>= one half of the * reference image dimension). * * This is a convenience member function, equivalent to * EnableLargeTranslations( !disable ) * * \warning When large translations are enabled, the engine needs to double * the sizes of internal working matrices, which \e quadruplicates the * amount of required memory. * * \sa EnableLargeTranslations(), AreLargeTranslationsEnabled() */ void DisableLargeTranslations( bool disable = true ) { EnableLargeTranslations( !disable ); } /*! * Returns the evaluated translation increments in pixels. * * The returned Point object contains the required offsets in the X and Y * directions to register the last evaluated target image on the reference * image set upon initialization. * * \sa DeltaX(), DeltaY() */ const FPoint& Delta() const { return m_delta; } /*! * Returns the evaluated translation increment in the X direction, in * pixels. * * \sa DeltaY(), Delta() */ float DeltaX() const { return m_delta.x; } /*! * Returns the evaluated translation increment in the Y direction, in * pixels. * * \sa DeltaX(), Delta() */ float DeltaY() const { return m_delta.y; } /*! * Returns the peak value read from the phase matrix for the last evaluated * target image. The peak value isn't normalized, that is, it doesn't * necessarily have to be in the [0,1] range. */ float Peak() const { return m_peak; } protected: // Allow translations > size/2. // Warning: a lot of memory may be necessary --four times more. bool m_largeTranslations = false; // Evaluation result. FPoint m_delta = 0.0F; // Peak value detected in the phase matrix. float m_peak = 0.0F; ComplexImage DoInitialize( const pcl::Image& ) override; ComplexImage DoInitialize( const pcl::DImage& ) override; ComplexImage DoInitialize( const pcl::ComplexImage& ) override; ComplexImage DoInitialize( const pcl::DComplexImage& ) override; ComplexImage DoInitialize( const pcl::UInt8Image& ) override; ComplexImage DoInitialize( const pcl::UInt16Image& ) override; ComplexImage DoInitialize( const pcl::UInt32Image& ) override; void DoEvaluate( const pcl::Image& ) override; void DoEvaluate( const pcl::DImage& ) override; void DoEvaluate( const pcl::ComplexImage& ) override; void DoEvaluate( const pcl::DComplexImage& ) override; void DoEvaluate( const pcl::UInt8Image& ) override; void DoEvaluate( const pcl::UInt16Image& ) override; void DoEvaluate( const pcl::UInt32Image& ) override; }; // ---------------------------------------------------------------------------- /*! * \class FFTRotationAndScaling * \brief %FFT registration engine: rotation and scaling * * %FFTRotationAndScaling evaluates rotation and scaling image registration * parameters. It computes the rotation angle and scaling ratio required to * register a target image on a reference image, using an algorithm based on * the Fourier-Mellin transform. * * \warning This class is currently experimental. It is not guaranteed to * provide reliable image registration parameters. * * \sa FFTTranslation, FFTRegistrationEngine */ class PCL_CLASS FFTRotationAndScaling : public FFTRegistrationEngine { public: /*! * Constructs a %FFTRotationAndScaling object. * * Scaling ratio evaluation (see EvaluatesScaling()) is disabled by default. */ FFTRotationAndScaling() = default; /*! * Destroys a %FFTRotationAndScaling object. */ virtual ~FFTRotationAndScaling() { } /*! * Returns true iff this engine evaluates scaling ratios. By default, scale * evaluation is disabled. */ bool EvaluatesScaling() const { return m_evaluateScaling; } /*! * Enables evaluation of scaling ratios. */ void EnableScalingEvaluation( bool enable = true ) { if ( enable != m_evaluateScaling ) { Reset(); m_evaluateScaling = enable; } } /*! * Disables evaluation of scaling ratios. * * This is a convenience member function, equivalent to * EnableScalingEvaluation( !disable ) */ void DisableScalingEvaluation( bool disable = true ) { EnableScalingEvaluation( !disable ); } /*! * Returns the current low frequency cutoff for this registration engine. * * See the documentation for SetLowFrequencyCutoff() for a detailed * description of low-frequency cutoffs. */ float LowFrequencyCutoff() const { return m_lowFrequencyCutoff; } /*! * Returns true iff this engine uses a low-frequency cutoff to reduce the * effects of rotational aliasing. */ bool HasLowFrequencyCutoff() const { return LowFrequencyCutoff() > 0; } /*! * Sets the radius of the low-frequency cutoff. * * The evaluation of rotation and scaling registration parameters can * benefit from a simple low-frequency cutoff operation to reduce rotational * aliasing on the computed DFTs. The value set by this function is the * radius of the cutoff \e hole relative to the largest dimension of the * reference image. The default value is 1/200. A value of zero disables the * low-frequency cutoff feature. */ void SetLowFrequencyCutoff( float r ) { m_lowFrequencyCutoff = Range( r, 0.0F, 0.5F ); } /*! * Returns the evaluated rotation angle in radians. * * The returned value is the required rotation angle to register the last * evaluated target image on the reference image set upon initialization. */ float RotationAngle() const { return m_rotationAngle; } /*! * Returns the evaluated scaling ratio. * * The returned value is the required scaling ratio to register the last * evaluated target image on the reference image set upon initialization. */ float ScalingRatio() const { return m_scalingRatio; } protected: // Evaluate rotation+scaling, or just rotation? bool m_evaluateScaling = false; // Low-frequency cutoff, as a fraction of the DFT radius. float m_lowFrequencyCutoff = 1.0F/200; // Evaluation result float m_rotationAngle = 0.0F; // radians float m_scalingRatio = 1.0F; // pixels ComplexImage DoInitialize( const pcl::Image& ) override; ComplexImage DoInitialize( const pcl::DImage& ) override; ComplexImage DoInitialize( const pcl::ComplexImage& ) override; ComplexImage DoInitialize( const pcl::DComplexImage& ) override; ComplexImage DoInitialize( const pcl::UInt8Image& ) override; ComplexImage DoInitialize( const pcl::UInt16Image& ) override; ComplexImage DoInitialize( const pcl::UInt32Image& ) override; void DoEvaluate( const pcl::Image& ) override; void DoEvaluate( const pcl::DImage& ) override; void DoEvaluate( const pcl::ComplexImage& ) override; void DoEvaluate( const pcl::DComplexImage& ) override; void DoEvaluate( const pcl::UInt8Image& ) override; void DoEvaluate( const pcl::UInt16Image& ) override; void DoEvaluate( const pcl::UInt32Image& ) override; }; // ---------------------------------------------------------------------------- } // pcl #endif // __PCL_FFTRegistration_h // ---------------------------------------------------------------------------- // EOF pcl/FFTRegistration.h - Released 2022-03-12T18:59:29Z