PCL
Homography.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.7.0
6 // ----------------------------------------------------------------------------
7 // pcl/Homography.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_Homography_h
53 #define __PCL_Homography_h
54 
56 
57 #include <pcl/Defs.h>
58 #include <pcl/Diagnostics.h>
59 
60 #include <pcl/Algebra.h>
61 #include <pcl/Array.h>
62 #include <pcl/Matrix.h>
63 #include <pcl/Point.h>
64 
65 namespace pcl
66 {
67 
68 // ----------------------------------------------------------------------------
69 
84 class PCL_CLASS Homography
85 {
86 public:
87 
93  : m_H( Matrix::UnitMatrix( 3 ) )
94  {
95  }
96 
100  Homography( const Matrix& H )
101  : m_H( H )
102  {
103  }
104 
129  template <class point_list1, class point_list2>
130  Homography( const point_list1& P1, const point_list2& P2 )
131  : m_H( DLT( P1, P2 ) )
132  {
133  }
134 
138  Homography( const Homography& ) = default;
139 
143  Homography& operator =( const Homography& ) = default;
144 
148  Homography( Homography&& ) = default;
149 
153  Homography& operator =( Homography&& ) = default;
154 
162  template <typename T1, typename T2>
163  void Apply( T1& x, T2& y ) const
164  {
165  double fx = double( x );
166  double fy = double( y );
167  double w = m_H[2][0]*fx + m_H[2][1]*fy + m_H[2][2];
168  PCL_CHECK( 1 + w != 1 )
169  x = T1( (m_H[0][0]*fx + m_H[0][1]*fy + m_H[0][2])/w );
170  y = T2( (m_H[1][0]*fx + m_H[1][1]*fy + m_H[1][2])/w );
171  }
172 
179  template <typename T>
181  {
182  Apply( p.x, p.y );
183  return p;
184  }
185 
191  DPoint operator ()( double x, double y ) const
192  {
193  DPoint p( x, y );
194  Apply( p.x, p.y );
195  return p;
196  }
197 
203  template <typename T>
204  DPoint operator ()( const GenericPoint<T>& p ) const
205  {
206  return operator ()( double( p.x ), double( p.y ) );
207  }
208 
222  {
223  return Homography( m_H.Inverse() );
224  }
225 
230  {
231  return m_H;
232  }
233 
237  operator const Matrix&() const
238  {
239  return TransformationMatrix();
240  }
241 
245  bool IsValid() const
246  {
247  return !m_H.IsEmpty();
248  }
249 
259  bool IsAffine() const
260  {
261  return IsValid()
262  && Abs( m_H[2][0] ) <= std::numeric_limits<double>::epsilon()
263  && Abs( m_H[2][1] ) <= std::numeric_limits<double>::epsilon()
264  && 1 - Abs( m_H[2][2] ) <= std::numeric_limits<double>::epsilon();
265  }
266 
271  {
272  m_H.EnsureUnique();
273  }
274 
275 private:
276 
277  Matrix m_H;
278 
279  /*
280  * Normalization of reference points.
281  */
282  struct NormalizedPoints
283  {
284  Array<DPoint> N; // the normalized points
285  Matrix T; // 3x3 normalization matrix
286 
287  template <class point_list>
288  NormalizedPoints( const point_list& points )
289  {
290  /*
291  * Calculate the centroid of the input set of points.
292  */
293  DPoint centroid( 0 );
294  for ( const auto& p : points )
295  centroid += DPoint( p.x, p.y );
296  centroid /= points.Length();
297 
298  /*
299  * Calculate mean centroid distance and move origin to the centroid.
300  */
301  double d0 = 0;
302  for ( const auto& p : points )
303  {
304  double dx = double( p.x ) - centroid.x;
305  double dy = double( p.y ) - centroid.y;
306  N << DPoint( dx, dy );
307  d0 += Sqrt( dx*dx + dy*dy );
308  }
309  d0 /= points.Length();
310 
311  /*
312  * Scale point coordinates.
313  */
314  double scale = Const<double>::sqrt2()/d0;
315  for ( auto& p : N )
316  p *= scale;
317 
318  /*
319  * Form the normalization matrix.
320  */
321  T = Matrix( scale, 0.0, -scale*centroid.x,
322  0.0, scale, -scale*centroid.y,
323  0.0, 0.0, 1.0 );
324  }
325  };
326 
327  /*
328  * Implementation of the Direct Linear Transformation (DLT) method to
329  * compute a normalized homography matrix.
330  */
331  template <class point_list1, class point_list2>
332  static Matrix DLT( const point_list1& P1, const point_list2& P2 )
333  {
334  int n = int( Min( P1.Length(), P2.Length() ) );
335  if ( n < 4 )
336  throw Error( "Homography::DLT(): Less than four points specified." );
337 
338  /*
339  * Normalize all points.
340  */
341  NormalizedPoints p1( P1 );
342  NormalizedPoints p2( P2 );
343 
344  /*
345  * Setup cross product matrix A.
346  */
347  Matrix A( 2*n, 9 );
348  for ( int i = 0; i < n; ++i )
349  {
350  double x1 = p1.N[i].x;
351  double y1 = p1.N[i].y;
352  double x2 = p2.N[i].x;
353  double y2 = p2.N[i].y;
354  double* A0 = A[2*i];
355  double* A1 = A[2*i + 1];
356  //double* A2 = A[3*i + 2]; <-- linearly dependent eqn.
357 
358  A0[0] = A0[1] = A0[2] = 0;
359  A0[3] = -x1;
360  A0[4] = -y1;
361  A0[5] = -1;
362  A0[6] = y2*x1;
363  A0[7] = y2*y1;
364  A0[8] = y2;
365 
366  A1[0] = x1;
367  A1[1] = y1;
368  A1[2] = 1;
369  A1[3] = A1[4] = A1[5] = 0;
370  A1[6] = -x2*x1;
371  A1[7] = -x2*y1;
372  A1[8] = -x2;
373 
374  /* <-- linearly dependent eqn.
375  A2[0] = -y2*x1;
376  A2[1] = -y2*y1;
377  A2[2] = -y2;
378  A2[3] = x2*x1;
379  A2[4] = x2*y1;
380  A2[5] = x2;
381  A2[6] = A2[7] = A2[8] = 0;
382  */
383  }
384 
385  /*
386  * SVD of cross product matrix.
387  */
388  InPlaceSVD svd( A );
389 
390  /*
391  * For sanity, set to zero all insignificant singular values.
392  */
393  for ( int i = 0; i < svd.W.Length(); ++i )
394  if ( Abs( svd.W[i] ) <= std::numeric_limits<double>::epsilon() )
395  svd.W[i] = 0;
396 
397  /*
398  * Locate the smallest nonzero singular value.
399  */
400  int i = svd.IndexOfSmallestSingularValue();
401 
402  /*
403  * The components of the homography matrix are those of the smallest
404  * eigenvector, i.e. the column vector of V corresponding to the smallest
405  * singular value.
406  */
407  Matrix H( svd.V[0][i], svd.V[1][i], svd.V[2][i],
408  svd.V[3][i], svd.V[4][i], svd.V[5][i],
409  svd.V[6][i], svd.V[7][i], svd.V[8][i] );
410 
411  if ( Abs( H[2][2] ) <= std::numeric_limits<double>::epsilon() )
412  throw Error( "Homography::DLT(): Singular matrix." );
413 
414  /*
415  * Denormalize matrix components.
416  */
417  H = p2.T.Inverse() * H * p1.T;
418 
419  /*
420  * Normalize matrix so that H[2][2] = 1.
421  */
422  return H *= 1/H[2][2];
423  }
424 };
425 
426 // ----------------------------------------------------------------------------
427 
428 } // pcl
429 
430 #endif // __PCL_Homography_h
431 
432 // ----------------------------------------------------------------------------
433 // EOF pcl/Homography.h - Released 2024-06-18T15:48:54Z
static constexpr T sqrt2()
Definition: Constants.h:179
Generic dynamic matrix of arbitrary dimensions.
Definition: Matrix.h:123
A generic point in the two-dimensional space.
Definition: Point.h:100
component x
Abscissa (horizontal, or X-axis coordinate).
Definition: Point.h:111
component y
Ordinate (vertical, or Y-axis coordinate).
Definition: Point.h:112
Homography geometric transformation.
Definition: Homography.h:85
Homography(const point_list1 &P1, const point_list2 &P2)
Definition: Homography.h:130
Homography(const Homography &)=default
GenericPoint< T > & Apply(GenericPoint< T > &p) const
Definition: Homography.h:180
const Matrix & TransformationMatrix() const
Definition: Homography.h:229
void Apply(T1 &x, T2 &y) const
Definition: Homography.h:163
Homography(Homography &&)=default
void EnsureUnique()
Definition: Homography.h:270
Homography Inverse() const
Definition: Homography.h:221
bool IsAffine() const
Definition: Homography.h:259
Homography(const Matrix &H)
Definition: Homography.h:100
bool IsValid() const
Definition: Homography.h:245
64-bit floating point real matrix.
Complex< T > Sqrt(const Complex< T > &c) noexcept
Definition: Complex.h:674
T Abs(const Complex< T > &c) noexcept
Definition: Complex.h:429
constexpr const T & Min(const T &a, const T &b) noexcept
Definition: Utility.h:90
void Apply(FI i, FI j, F f) noexcept(noexcept(f))
Definition: Utility.h:249
PCL root namespace.
Definition: AbstractImage.h:77