Support for XISF

This commit is contained in:
2022-04-12 08:17:18 +02:00
parent e5cd25cc77
commit 0fb27266c7
278 changed files with 209068 additions and 7 deletions
+406
View File
@@ -0,0 +1,406 @@
// ____ ______ __
// / __ \ / ____// /
// / /_/ // / / /
// / ____// /___ / /___ PixInsight Class Library
// /_/ \____//_____/ PCL 2.4.23
// ----------------------------------------------------------------------------
// pcl/Homography.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_Homography_h
#define __PCL_Homography_h
/// \file pcl/Homography.h
#include <pcl/Defs.h>
#include <pcl/Diagnostics.h>
#include <pcl/Algebra.h>
#include <pcl/Array.h>
#include <pcl/Matrix.h>
#include <pcl/Point.h>
namespace pcl
{
// ----------------------------------------------------------------------------
/*!
* \class Homography
* \brief Homography geometric transformation.
*
* A two-dimensional projective transformation, or \e homography, is a
* line-preserving geometric transformation between two sets of points in the
* plane. More formally, if P represents the set of points in the plane, a
* homography is an invertible mapping H from P^2 to itself such that three
* points p1, p2, p3 are collinear if and only if H(p1), H(p2), H(p3) do.
*
* Homographies have important practical applications in the field of computer
* vision. On the PixInsight platform, this class is an essential component of
* image registration and astrometry processes.
*/
template <class P = DPoint>
class PCL_CLASS Homography
{
public:
/*!
* Represents a reference point in two dimensions.
*/
typedef P point;
/*!
* Represents a list of two-dimensional reference points involved in a
* homography transformation.
*/
typedef Array<point> point_list;
/*!
* Default constructor. Constructs a no-op transformation with a unit matrix
* transformation matrix.
*/
Homography()
: m_H( Matrix::UnitMatrix( 3 ) )
{
}
/*!
* Constructor from a given homography matrix.
*/
Homography( const Matrix& H )
: m_H( H )
{
}
/*!
* Constructor from two 2D point lists.
*
* Computes a homography transformation to generate a list \a P2 of
* transformed points from a list \a P1 of original points. In other words,
* the computed homography H works as follows:
*
* P2 = H( P1 )
*
* The transformation matrix is calculated by the Direct Linear
* Transformation (DLT) method. Both point lists must contain at least four
* points.
*
* If one of the specified point lists contains less than four points, or if
* no homography can be estimated from the specified point lists (which
* leads to a singular transformation matrix), this constructor throws an
* appropriate Error exception.
*
* \b References
*
* R. Hartley, <em>In defense of the eight-point algorithm.</em> IEEE
* Transactions on Pattern Analysis and Machine Intelligence, vol. 19, pp.
* 580593, June 1997.
*/
Homography( const point_list& P1, const point_list& P2 )
: m_H( DLT( P1, P2 ) )
{
}
/*!
* Copy constructor.
*/
Homography( const Homography& ) = default;
/*!
* Copy assignment operator.
*/
Homography& operator =( const Homography& ) = default;
/*!
* Move constructor.
*/
Homography( Homography&& ) = default;
/*!
* Move assignment operator.
*/
Homography& operator =( Homography&& ) = default;
/*!
* Coordinate transformation operator. Applies the homography matrix to the
* specified \a x and \a y coordinates. Returns the transformed point as a
* two-dimensional point with real coordinates.
*/
template <typename T>
DPoint operator ()( T x, T y ) const
{
double w = m_H[2][0]*x + m_H[2][1]*y + m_H[2][2];
PCL_CHECK( 1 + w != 1 )
return DPoint( (m_H[0][0]*x + m_H[0][1]*y + m_H[0][2])/w,
(m_H[1][0]*x + m_H[1][1]*y + m_H[1][2])/w );
}
/*!
* Point transformation operator. Applies the homography matrix to the
* coordinates of the specified point \a p. Returns the transformed point as
* a two-dimensional point with real coordinates.
*/
template <typename T>
DPoint operator ()( const GenericPoint<T>& p ) const
{
return operator ()( p.x, p.y );
}
/*!
* Returns the inverse of this homography transformation.
*
* If this transformation has been computed from two point lists \a P1 and
* \a P2:
*
* P2 = H( P1 )
*
* then this function returns a transformation H1 such that:
*
* P1 = H1( P2 )
*/
Homography Inverse() const
{
return Homography( m_H.Inverse() );
}
/*!
* Returns the homography transformation matrix.
*/
operator const Matrix&() const
{
return m_H;
}
/*!
* Returns true iff this transformation has been initialized and is valid.
*/
bool IsValid() const
{
return !m_H.IsEmpty();
}
/*!
* Returns true iff this is an affine homography transformation.
*
* An affine homography is a special type of a general homography where the
* last row of the 3x3 transformation matrix is equal to (0, 0, 1). This
* function verifies that this property holds for the current transformation
* matrix (if it is valid) up to the machine epsilon for the \c double
* numeric type.
*/
bool IsAffine() const
{
return IsValid()
&& Abs( m_H[2][0] ) <= std::numeric_limits<double>::epsilon()
&& Abs( m_H[2][1] ) <= std::numeric_limits<double>::epsilon()
&& 1 - Abs( m_H[2][2] ) <= std::numeric_limits<double>::epsilon();
}
/*!
* Ensures that the transformation uniquely references its internal matrix
* data.
*/
void EnsureUnique()
{
m_H.EnsureUnique();
}
private:
Matrix m_H;
/*
* Normalization of reference points.
*/
struct NormalizedPoints
{
Array<DPoint> N; // the normalized points
Matrix T; // 3x3 normalization matrix
NormalizedPoints( const point_list& points )
{
/*
* Calculate the centroid of the input set of points.
*/
DPoint centroid( 0 );
for ( const auto& p : points )
centroid += p;
centroid /= points.Length();
/*
* Calculate mean centroid distance and move origin to the centroid.
*/
double d0 = 0;
for ( const auto& p : points )
{
double x = p.x - centroid.x;
double y = p.y - centroid.y;
N << DPoint( x, y );
d0 += Sqrt( x*x + y*y );
}
d0 /= points.Length();
/*
* Scale point coordinates.
*/
double scale = Const<double>::sqrt2()/d0;
for ( auto& p : N )
p *= scale;
/*
* Form the normalization matrix.
*/
T = Matrix( scale, 0.0, -scale*centroid.x,
0.0, scale, -scale*centroid.y,
0.0, 0.0, 1.0 );
}
};
/*
* Implementation of the Direct Linear Transformation (DLT) method to
* compute a normalized homography matrix.
*/
static Matrix DLT( const point_list& P1, const point_list& P2 )
{
int n = Min( P1.Length(), P2.Length() );
if ( n < 4 )
throw Error( "Homography::DLT(): Less than four points specified." );
/*
* Normalize all points.
*/
NormalizedPoints p1( P1 );
NormalizedPoints p2( P2 );
/*
* Setup cross product matrix A.
*/
Matrix A( 2*n, 9 );
for ( int i = 0; i < n; ++i )
{
double x1 = p1.N[i].x;
double y1 = p1.N[i].y;
double x2 = p2.N[i].x;
double y2 = p2.N[i].y;
double* A0 = A[2*i];
double* A1 = A[2*i + 1];
//double* A2 = A[3*i + 2]; <-- linearly dependent eqn.
A0[0] = A0[1] = A0[2] = 0;
A0[3] = -x1;
A0[4] = -y1;
A0[5] = -1;
A0[6] = y2*x1;
A0[7] = y2*y1;
A0[8] = y2;
A1[0] = x1;
A1[1] = y1;
A1[2] = 1;
A1[3] = A1[4] = A1[5] = 0;
A1[6] = -x2*x1;
A1[7] = -x2*y1;
A1[8] = -x2;
/* <-- linearly dependent eqn.
A2[0] = -y2*x1;
A2[1] = -y2*y1;
A2[2] = -y2;
A2[3] = x2*x1;
A2[4] = x2*y1;
A2[5] = x2;
A2[6] = A2[7] = A2[8] = 0;
*/
}
/*
* SVD of cross product matrix.
*/
InPlaceSVD svd( A );
/*
* For sanity, set to zero all insignificant singular values.
*/
for ( int i = 0; i < svd.W.Length(); ++i )
if ( Abs( svd.W[i] ) <= std::numeric_limits<double>::epsilon() )
svd.W[i] = 0;
/*
* Locate the smallest nonzero singular value.
*/
int i = svd.IndexOfSmallestSingularValue();
/*
* The components of the homography matrix are those of the smallest
* eigenvector, i.e. the column vector of V corresponding to the smallest
* singular value.
*/
Matrix H( svd.V[0][i], svd.V[1][i], svd.V[2][i],
svd.V[3][i], svd.V[4][i], svd.V[5][i],
svd.V[6][i], svd.V[7][i], svd.V[8][i] );
if ( Abs( H[2][2] ) <= std::numeric_limits<double>::epsilon() )
throw Error( "Homography::DLT(): Singular matrix." );
/*
* Denormalize matrix components.
*/
H = p2.T.Inverse() * H * p1.T;
/*
* Normalize matrix so that H[2][2] = 1.
*/
return H *= 1/H[2][2];
}
};
// ----------------------------------------------------------------------------
} // pcl
#endif // __PCL_Homography_h
// ----------------------------------------------------------------------------
// EOF pcl/Homography.h - Released 2022-03-12T18:59:29Z