PerspectiveTransform.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. * Copyright 2016 ZXing authors
  4. * Copyright 2020 Axel Waggershauser
  5. */
  6. // SPDX-License-Identifier: Apache-2.0
  7. #include "PerspectiveTransform.h"
  8. #include <array>
  9. namespace ZXing {
  10. PerspectiveTransform PerspectiveTransform::inverse() const
  11. {
  12. // Here, the adjoint serves as the inverse:
  13. // Adjoint is the transpose of the cofactor matrix:
  14. return {
  15. a22 * a33 - a23 * a32,
  16. a23 * a31 - a21 * a33,
  17. a21 * a32 - a22 * a31,
  18. a13 * a32 - a12 * a33,
  19. a11 * a33 - a13 * a31,
  20. a12 * a31 - a11 * a32,
  21. a12 * a23 - a13 * a22,
  22. a13 * a21 - a11 * a23,
  23. a11 * a22 - a12 * a21
  24. };
  25. }
  26. PerspectiveTransform PerspectiveTransform::times(const PerspectiveTransform& other) const
  27. {
  28. return {
  29. a11 * other.a11 + a21 * other.a12 + a31 * other.a13,
  30. a11 * other.a21 + a21 * other.a22 + a31 * other.a23,
  31. a11 * other.a31 + a21 * other.a32 + a31 * other.a33,
  32. a12 * other.a11 + a22 * other.a12 + a32 * other.a13,
  33. a12 * other.a21 + a22 * other.a22 + a32 * other.a23,
  34. a12 * other.a31 + a22 * other.a32 + a32 * other.a33,
  35. a13 * other.a11 + a23 * other.a12 + a33 * other.a13,
  36. a13 * other.a21 + a23 * other.a22 + a33 * other.a23,
  37. a13 * other.a31 + a23 * other.a32 + a33 * other.a33
  38. };
  39. }
  40. PerspectiveTransform PerspectiveTransform::UnitSquareTo(const QuadrilateralF& q)
  41. {
  42. auto [x0, y0, x1, y1, x2, y2, x3, y3] = reinterpret_cast<const std::array<PointF::value_t, 8>&>(q);
  43. auto d3 = q[0] - q[1] + q[2] - q[3];
  44. if (d3 == PointF(0, 0)) {
  45. // Affine
  46. return {x1 - x0, x2 - x1, x0,
  47. y1 - y0, y2 - y1, y0,
  48. 0.0f, 0.0f, 1.0f};
  49. } else {
  50. auto d1 = q[1] - q[2];
  51. auto d2 = q[3] - q[2];
  52. auto denominator = cross(d1, d2);
  53. auto a13 = cross(d3, d2) / denominator;
  54. auto a23 = cross(d1, d3) / denominator;
  55. return {x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0,
  56. y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0,
  57. a13, a23, 1.0f};
  58. }
  59. }
  60. PerspectiveTransform::PerspectiveTransform(const QuadrilateralF& src, const QuadrilateralF& dst)
  61. {
  62. if (!IsConvex(src) || !IsConvex(dst))
  63. return;
  64. *this = UnitSquareTo(dst).times(UnitSquareTo(src).inverse());
  65. }
  66. PointF PerspectiveTransform::operator()(PointF p) const
  67. {
  68. auto denominator = a13 * p.x + a23 * p.y + a33;
  69. return {(a11 * p.x + a21 * p.y + a31) / denominator, (a12 * p.x + a22 * p.y + a32) / denominator};
  70. }
  71. } // ZXing