node-native-win-utils 1.1.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/README.md +144 -27
  2. package/binding.gyp +18 -5
  3. package/dist/index.d.ts +146 -4
  4. package/dist/index.js +107 -3
  5. package/include/opencv2/core/affine.hpp +678 -0
  6. package/include/opencv2/core/async.hpp +105 -0
  7. package/include/opencv2/core/base.hpp +664 -0
  8. package/include/opencv2/core/bindings_utils.hpp +325 -0
  9. package/include/opencv2/core/bufferpool.hpp +40 -0
  10. package/include/opencv2/core/check.hpp +170 -0
  11. package/include/opencv2/core/core.hpp +48 -0
  12. package/include/opencv2/core/core_c.h +3128 -0
  13. package/include/opencv2/core/cuda/block.hpp +211 -0
  14. package/include/opencv2/core/cuda/border_interpolate.hpp +722 -0
  15. package/include/opencv2/core/cuda/color.hpp +309 -0
  16. package/include/opencv2/core/cuda/common.hpp +131 -0
  17. package/include/opencv2/core/cuda/datamov_utils.hpp +113 -0
  18. package/include/opencv2/core/cuda/detail/color_detail.hpp +2018 -0
  19. package/include/opencv2/core/cuda/detail/reduce.hpp +365 -0
  20. package/include/opencv2/core/cuda/detail/reduce_key_val.hpp +502 -0
  21. package/include/opencv2/core/cuda/detail/transform_detail.hpp +392 -0
  22. package/include/opencv2/core/cuda/detail/type_traits_detail.hpp +191 -0
  23. package/include/opencv2/core/cuda/detail/vec_distance_detail.hpp +121 -0
  24. package/include/opencv2/core/cuda/dynamic_smem.hpp +88 -0
  25. package/include/opencv2/core/cuda/emulation.hpp +269 -0
  26. package/include/opencv2/core/cuda/filters.hpp +293 -0
  27. package/include/opencv2/core/cuda/funcattrib.hpp +79 -0
  28. package/include/opencv2/core/cuda/functional.hpp +805 -0
  29. package/include/opencv2/core/cuda/limits.hpp +128 -0
  30. package/include/opencv2/core/cuda/reduce.hpp +209 -0
  31. package/include/opencv2/core/cuda/saturate_cast.hpp +292 -0
  32. package/include/opencv2/core/cuda/scan.hpp +258 -0
  33. package/include/opencv2/core/cuda/simd_functions.hpp +869 -0
  34. package/include/opencv2/core/cuda/transform.hpp +75 -0
  35. package/include/opencv2/core/cuda/type_traits.hpp +90 -0
  36. package/include/opencv2/core/cuda/utility.hpp +230 -0
  37. package/include/opencv2/core/cuda/vec_distance.hpp +232 -0
  38. package/include/opencv2/core/cuda/vec_math.hpp +923 -0
  39. package/include/opencv2/core/cuda/vec_traits.hpp +288 -0
  40. package/include/opencv2/core/cuda/warp.hpp +139 -0
  41. package/include/opencv2/core/cuda/warp_reduce.hpp +76 -0
  42. package/include/opencv2/core/cuda/warp_shuffle.hpp +162 -0
  43. package/include/opencv2/core/cuda.hpp +1279 -0
  44. package/include/opencv2/core/cuda.inl.hpp +763 -0
  45. package/include/opencv2/core/cuda_stream_accessor.hpp +86 -0
  46. package/include/opencv2/core/cuda_types.hpp +144 -0
  47. package/include/opencv2/core/cv_cpu_dispatch.h +381 -0
  48. package/include/opencv2/core/cv_cpu_helper.h +550 -0
  49. package/include/opencv2/core/cvdef.h +973 -0
  50. package/include/opencv2/core/cvstd.hpp +190 -0
  51. package/include/opencv2/core/cvstd.inl.hpp +197 -0
  52. package/include/opencv2/core/cvstd_wrapper.hpp +154 -0
  53. package/include/opencv2/core/detail/async_promise.hpp +71 -0
  54. package/include/opencv2/core/detail/dispatch_helper.impl.hpp +49 -0
  55. package/include/opencv2/core/detail/exception_ptr.hpp +27 -0
  56. package/include/opencv2/core/directx.hpp +184 -0
  57. package/include/opencv2/core/dualquaternion.hpp +979 -0
  58. package/include/opencv2/core/dualquaternion.inl.hpp +487 -0
  59. package/include/opencv2/core/eigen.hpp +402 -0
  60. package/include/opencv2/core/fast_math.hpp +433 -0
  61. package/include/opencv2/core/hal/hal.hpp +256 -0
  62. package/include/opencv2/core/hal/interface.h +190 -0
  63. package/include/opencv2/core/hal/intrin.hpp +939 -0
  64. package/include/opencv2/core/hal/intrin_avx.hpp +3177 -0
  65. package/include/opencv2/core/hal/intrin_avx512.hpp +3090 -0
  66. package/include/opencv2/core/hal/intrin_cpp.hpp +3321 -0
  67. package/include/opencv2/core/hal/intrin_forward.hpp +191 -0
  68. package/include/opencv2/core/hal/intrin_lasx.hpp +3236 -0
  69. package/include/opencv2/core/hal/intrin_msa.hpp +1887 -0
  70. package/include/opencv2/core/hal/intrin_neon.hpp +2610 -0
  71. package/include/opencv2/core/hal/intrin_rvv.hpp +3320 -0
  72. package/include/opencv2/core/hal/intrin_rvv071.hpp +2545 -0
  73. package/include/opencv2/core/hal/intrin_rvv_scalable.hpp +2080 -0
  74. package/include/opencv2/core/hal/intrin_sse.hpp +3467 -0
  75. package/include/opencv2/core/hal/intrin_sse_em.hpp +180 -0
  76. package/include/opencv2/core/hal/intrin_vsx.hpp +1608 -0
  77. package/include/opencv2/core/hal/intrin_wasm.hpp +2782 -0
  78. package/include/opencv2/core/hal/msa_macros.h +1558 -0
  79. package/include/opencv2/core/hal/simd_utils.impl.hpp +186 -0
  80. package/include/opencv2/core/llapi/llapi.h +102 -0
  81. package/include/opencv2/core/mat.hpp +3775 -0
  82. package/include/opencv2/core/mat.inl.hpp +3422 -0
  83. package/include/opencv2/core/matx.hpp +1536 -0
  84. package/include/opencv2/core/neon_utils.hpp +128 -0
  85. package/include/opencv2/core/ocl.hpp +917 -0
  86. package/include/opencv2/core/ocl_genbase.hpp +69 -0
  87. package/include/opencv2/core/opencl/ocl_defs.hpp +82 -0
  88. package/include/opencv2/core/opencl/opencl_info.hpp +212 -0
  89. package/include/opencv2/core/opencl/opencl_svm.hpp +81 -0
  90. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_clblas.hpp +602 -0
  91. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_clfft.hpp +146 -0
  92. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_core.hpp +371 -0
  93. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_core_wrappers.hpp +272 -0
  94. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_gl.hpp +62 -0
  95. package/include/opencv2/core/opencl/runtime/autogenerated/opencl_gl_wrappers.hpp +42 -0
  96. package/include/opencv2/core/opencl/runtime/opencl_clblas.hpp +53 -0
  97. package/include/opencv2/core/opencl/runtime/opencl_clfft.hpp +53 -0
  98. package/include/opencv2/core/opencl/runtime/opencl_core.hpp +84 -0
  99. package/include/opencv2/core/opencl/runtime/opencl_core_wrappers.hpp +47 -0
  100. package/include/opencv2/core/opencl/runtime/opencl_gl.hpp +53 -0
  101. package/include/opencv2/core/opencl/runtime/opencl_gl_wrappers.hpp +47 -0
  102. package/include/opencv2/core/opencl/runtime/opencl_svm_20.hpp +48 -0
  103. package/include/opencv2/core/opencl/runtime/opencl_svm_definitions.hpp +42 -0
  104. package/include/opencv2/core/opencl/runtime/opencl_svm_hsa_extension.hpp +166 -0
  105. package/include/opencv2/core/opengl.hpp +733 -0
  106. package/include/opencv2/core/openvx/ovx_defs.hpp +48 -0
  107. package/include/opencv2/core/operations.hpp +610 -0
  108. package/include/opencv2/core/optim.hpp +302 -0
  109. package/include/opencv2/core/ovx.hpp +28 -0
  110. package/include/opencv2/core/parallel/backend/parallel_for.openmp.hpp +72 -0
  111. package/include/opencv2/core/parallel/backend/parallel_for.tbb.hpp +153 -0
  112. package/include/opencv2/core/parallel/parallel_backend.hpp +90 -0
  113. package/include/opencv2/core/persistence.hpp +1350 -0
  114. package/include/opencv2/core/private/cv_cpu_include_simd_declarations.hpp +30 -0
  115. package/include/opencv2/core/private.cuda.hpp +169 -0
  116. package/include/opencv2/core/private.hpp +896 -0
  117. package/include/opencv2/core/quaternion.hpp +1696 -0
  118. package/include/opencv2/core/quaternion.inl.hpp +1063 -0
  119. package/include/opencv2/core/saturate.hpp +180 -0
  120. package/include/opencv2/core/simd_intrinsics.hpp +87 -0
  121. package/include/opencv2/core/softfloat.hpp +514 -0
  122. package/include/opencv2/core/sse_utils.hpp +652 -0
  123. package/include/opencv2/core/traits.hpp +417 -0
  124. package/include/opencv2/core/types.hpp +2457 -0
  125. package/include/opencv2/core/types_c.h +2126 -0
  126. package/include/opencv2/core/utility.hpp +1229 -0
  127. package/include/opencv2/core/utils/allocator_stats.hpp +29 -0
  128. package/include/opencv2/core/utils/allocator_stats.impl.hpp +158 -0
  129. package/include/opencv2/core/utils/buffer_area.private.hpp +136 -0
  130. package/include/opencv2/core/utils/configuration.private.hpp +22 -0
  131. package/include/opencv2/core/utils/filesystem.hpp +82 -0
  132. package/include/opencv2/core/utils/filesystem.private.hpp +66 -0
  133. package/include/opencv2/core/utils/fp_control.private.hpp +29 -0
  134. package/include/opencv2/core/utils/fp_control_utils.hpp +69 -0
  135. package/include/opencv2/core/utils/instrumentation.hpp +125 -0
  136. package/include/opencv2/core/utils/lock.private.hpp +119 -0
  137. package/include/opencv2/core/utils/logger.defines.hpp +42 -0
  138. package/include/opencv2/core/utils/logger.hpp +218 -0
  139. package/include/opencv2/core/utils/logtag.hpp +28 -0
  140. package/include/opencv2/core/utils/plugin_loader.private.hpp +165 -0
  141. package/include/opencv2/core/utils/tls.hpp +235 -0
  142. package/include/opencv2/core/utils/trace.hpp +252 -0
  143. package/include/opencv2/core/utils/trace.private.hpp +421 -0
  144. package/include/opencv2/core/va_intel.hpp +75 -0
  145. package/include/opencv2/core/version.hpp +26 -0
  146. package/include/opencv2/core/vsx_utils.hpp +1047 -0
  147. package/include/opencv2/core.hpp +3365 -0
  148. package/include/opencv2/imgcodecs/imgcodecs.hpp +48 -0
  149. package/include/opencv2/imgcodecs/imgcodecs_c.h +1 -0
  150. package/include/opencv2/imgcodecs/ios.h +59 -0
  151. package/include/opencv2/imgcodecs/legacy/constants_c.h +54 -0
  152. package/include/opencv2/imgcodecs/macosx.h +20 -0
  153. package/include/opencv2/imgcodecs.hpp +407 -0
  154. package/include/opencv2/imgproc/bindings.hpp +34 -0
  155. package/include/opencv2/imgproc/detail/gcgraph.hpp +395 -0
  156. package/include/opencv2/imgproc/hal/hal.hpp +246 -0
  157. package/include/opencv2/imgproc/hal/interface.h +46 -0
  158. package/include/opencv2/imgproc/imgproc.hpp +48 -0
  159. package/include/opencv2/imgproc/imgproc_c.h +1177 -0
  160. package/include/opencv2/imgproc/segmentation.hpp +141 -0
  161. package/include/opencv2/imgproc/types_c.h +659 -0
  162. package/include/opencv2/imgproc.hpp +5035 -0
  163. package/include/opencv2/opencv_modules.hpp +17 -0
  164. package/libs/libjpeg-turbo.lib +0 -0
  165. package/libs/libpng.lib +0 -0
  166. package/libs/opencv_core470.lib +0 -0
  167. package/libs/opencv_imgcodecs470.lib +0 -0
  168. package/libs/opencv_imgproc470.lib +0 -0
  169. package/libs/zlib.lib +0 -0
  170. package/package.json +14 -3
  171. package/prebuilds/win32-x64/node.napi.node +0 -0
  172. package/src/cpp/capturewindow.cpp +36 -46
  173. package/src/cpp/main.cpp +10 -2
  174. package/src/cpp/opencv.cpp +425 -0
@@ -0,0 +1,1063 @@
1
+ // This file is part of OpenCV project.
2
+ // It is subject to the license terms in the LICENSE file found in the top-level directory
3
+ // of this distribution and at http://opencv.org/license.html.
4
+ //
5
+ //
6
+ // License Agreement
7
+ // For Open Source Computer Vision Library
8
+ //
9
+ // Copyright (C) 2020, Huawei Technologies Co., Ltd. All rights reserved.
10
+ // Third party copyrights are property of their respective owners.
11
+ //
12
+ // Licensed under the Apache License, Version 2.0 (the "License");
13
+ // you may not use this file except in compliance with the License.
14
+ // You may obtain a copy of the License at
15
+ //
16
+ // http://www.apache.org/licenses/LICENSE-2.0
17
+ //
18
+ // Unless required by applicable law or agreed to in writing, software
19
+ // distributed under the License is distributed on an "AS IS" BASIS,
20
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
+ // See the License for the specific language governing permissions and
22
+ // limitations under the License.
23
+ //
24
+ // Author: Liangqian Kong <chargerKong@126.com>
25
+ // Longbu Wang <riskiest@gmail.com>
26
+
27
+ #ifndef OPENCV_CORE_QUATERNION_INL_HPP
28
+ #define OPENCV_CORE_QUATERNION_INL_HPP
29
+
30
+ #ifndef OPENCV_CORE_QUATERNION_HPP
31
+ #erorr This is not a standalone header. Include quaternion.hpp instead.
32
+ #endif
33
+
34
+ //@cond IGNORE
35
+ ///////////////////////////////////////////////////////////////////////////////////////
36
+ //Implementation
37
+ namespace cv {
38
+
39
+ template <typename T>
40
+ Quat<T>::Quat() : w(0), x(0), y(0), z(0) {}
41
+
42
+ template <typename T>
43
+ Quat<T>::Quat(const Vec<T, 4> &coeff):w(coeff[0]), x(coeff[1]), y(coeff[2]), z(coeff[3]){}
44
+
45
+ template <typename T>
46
+ Quat<T>::Quat(const T qw, const T qx, const T qy, const T qz):w(qw), x(qx), y(qy), z(qz){}
47
+
48
+ template <typename T>
49
+ Quat<T> Quat<T>::createFromAngleAxis(const T angle, const Vec<T, 3> &axis)
50
+ {
51
+ T w, x, y, z;
52
+ T vNorm = std::sqrt(axis.dot(axis));
53
+ if (vNorm < CV_QUAT_EPS)
54
+ {
55
+ CV_Error(Error::StsBadArg, "this quaternion does not represent a rotation");
56
+ }
57
+ const T angle_half = angle * T(0.5);
58
+ w = std::cos(angle_half);
59
+ const T sin_v = std::sin(angle_half);
60
+ const T sin_norm = sin_v / vNorm;
61
+ x = sin_norm * axis[0];
62
+ y = sin_norm * axis[1];
63
+ z = sin_norm * axis[2];
64
+ return Quat<T>(w, x, y, z);
65
+ }
66
+
67
+ template <typename T>
68
+ Quat<T> Quat<T>::createFromRotMat(InputArray _R)
69
+ {
70
+ CV_CheckTypeEQ(_R.type(), cv::traits::Type<T>::value, "");
71
+ if (_R.rows() != 3 || _R.cols() != 3)
72
+ {
73
+ CV_Error(Error::StsBadArg, "Cannot convert matrix to quaternion: rotation matrix should be a 3x3 matrix");
74
+ }
75
+ Matx<T, 3, 3> R;
76
+ _R.copyTo(R);
77
+
78
+ T S, w, x, y, z;
79
+ T trace = R(0, 0) + R(1, 1) + R(2, 2);
80
+ if (trace > 0)
81
+ {
82
+ S = std::sqrt(trace + 1) * T(2);
83
+ x = (R(1, 2) - R(2, 1)) / S;
84
+ y = (R(2, 0) - R(0, 2)) / S;
85
+ z = (R(0, 1) - R(1, 0)) / S;
86
+ w = -T(0.25) * S;
87
+ }
88
+ else if (R(0, 0) > R(1, 1) && R(0, 0) > R(2, 2))
89
+ {
90
+
91
+ S = std::sqrt(T(1.0) + R(0, 0) - R(1, 1) - R(2, 2)) * T(2);
92
+ x = -T(0.25) * S;
93
+ y = -(R(1, 0) + R(0, 1)) / S;
94
+ z = -(R(0, 2) + R(2, 0)) / S;
95
+ w = (R(1, 2) - R(2, 1)) / S;
96
+ }
97
+ else if (R(1, 1) > R(2, 2))
98
+ {
99
+ S = std::sqrt(T(1.0) - R(0, 0) + R(1, 1) - R(2, 2)) * T(2);
100
+ x = (R(0, 1) + R(1, 0)) / S;
101
+ y = T(0.25) * S;
102
+ z = (R(1, 2) + R(2, 1)) / S;
103
+ w = (R(0, 2) - R(2, 0)) / S;
104
+ }
105
+ else
106
+ {
107
+ S = std::sqrt(T(1.0) - R(0, 0) - R(1, 1) + R(2, 2)) * T(2);
108
+ x = (R(0, 2) + R(2, 0)) / S;
109
+ y = (R(1, 2) + R(2, 1)) / S;
110
+ z = T(0.25) * S;
111
+ w = -(R(0, 1) - R(1, 0)) / S;
112
+ }
113
+ return Quat<T> (w, x, y, z);
114
+ }
115
+
116
+ template <typename T>
117
+ Quat<T> Quat<T>::createFromRvec(InputArray _rvec)
118
+ {
119
+ if (!((_rvec.cols() == 1 && _rvec.rows() == 3) || (_rvec.cols() == 3 && _rvec.rows() == 1))) {
120
+ CV_Error(Error::StsBadArg, "Cannot convert rotation vector to quaternion: The length of rotation vector should be 3");
121
+ }
122
+ Vec<T, 3> rvec;
123
+ _rvec.copyTo(rvec);
124
+ T psi = std::sqrt(rvec.dot(rvec));
125
+ if (abs(psi) < CV_QUAT_EPS) {
126
+ return Quat<T> (1, 0, 0, 0);
127
+ }
128
+ Vec<T, 3> axis = rvec / psi;
129
+ return createFromAngleAxis(psi, axis);
130
+ }
131
+
132
+ template <typename T>
133
+ inline Quat<T> Quat<T>::operator-() const
134
+ {
135
+ return Quat<T>(-w, -x, -y, -z);
136
+ }
137
+
138
+
139
+ template <typename T>
140
+ inline bool Quat<T>::operator==(const Quat<T> &q) const
141
+ {
142
+ return (abs(w - q.w) < CV_QUAT_EPS && abs(x - q.x) < CV_QUAT_EPS && abs(y - q.y) < CV_QUAT_EPS && abs(z - q.z) < CV_QUAT_EPS);
143
+ }
144
+
145
+ template <typename T>
146
+ inline Quat<T> Quat<T>::operator+(const Quat<T> &q1) const
147
+ {
148
+ return Quat<T>(w + q1.w, x + q1.x, y + q1.y, z + q1.z);
149
+ }
150
+
151
+ template <typename T>
152
+ inline Quat<T> operator+(const T a, const Quat<T>& q)
153
+ {
154
+ return Quat<T>(q.w + a, q.x, q.y, q.z);
155
+ }
156
+
157
+ template <typename T>
158
+ inline Quat<T> operator+(const Quat<T>& q, const T a)
159
+ {
160
+ return Quat<T>(q.w + a, q.x, q.y, q.z);
161
+ }
162
+
163
+ template <typename T>
164
+ inline Quat<T> operator-(const T a, const Quat<T>& q)
165
+ {
166
+ return Quat<T>(a - q.w, -q.x, -q.y, -q.z);
167
+ }
168
+
169
+ template <typename T>
170
+ inline Quat<T> operator-(const Quat<T>& q, const T a)
171
+ {
172
+ return Quat<T>(q.w - a, q.x, q.y, q.z);
173
+ }
174
+
175
+ template <typename T>
176
+ inline Quat<T> Quat<T>::operator-(const Quat<T> &q1) const
177
+ {
178
+ return Quat<T>(w - q1.w, x - q1.x, y - q1.y, z - q1.z);
179
+ }
180
+
181
+ template <typename T>
182
+ inline Quat<T>& Quat<T>::operator+=(const Quat<T> &q1)
183
+ {
184
+ w += q1.w;
185
+ x += q1.x;
186
+ y += q1.y;
187
+ z += q1.z;
188
+ return *this;
189
+ }
190
+
191
+ template <typename T>
192
+ inline Quat<T>& Quat<T>::operator-=(const Quat<T> &q1)
193
+ {
194
+ w -= q1.w;
195
+ x -= q1.x;
196
+ y -= q1.y;
197
+ z -= q1.z;
198
+ return *this;
199
+ }
200
+
201
+ template <typename T>
202
+ inline Quat<T> Quat<T>::operator*(const Quat<T> &q1) const
203
+ {
204
+ Vec<T, 4> q{w, x, y, z};
205
+ Vec<T, 4> q2{q1.w, q1.x, q1.y, q1.z};
206
+ return Quat<T>(q * q2);
207
+ }
208
+
209
+
210
+ template <typename T>
211
+ Quat<T> operator*(const Quat<T> &q1, const T a)
212
+ {
213
+ return Quat<T>(a * q1.w, a * q1.x, a * q1.y, a * q1.z);
214
+ }
215
+
216
+ template <typename T>
217
+ Quat<T> operator*(const T a, const Quat<T> &q1)
218
+ {
219
+ return Quat<T>(a * q1.w, a * q1.x, a * q1.y, a * q1.z);
220
+ }
221
+
222
+ template <typename T>
223
+ inline Quat<T>& Quat<T>::operator*=(const Quat<T> &q1)
224
+ {
225
+ T qw, qx, qy, qz;
226
+ qw = w * q1.w - x * q1.x - y * q1.y - z * q1.z;
227
+ qx = x * q1.w + w * q1.x + y * q1.z - z * q1.y;
228
+ qy = y * q1.w + w * q1.y + z * q1.x - x * q1.z;
229
+ qz = z * q1.w + w * q1.z + x * q1.y - y * q1.x;
230
+ w = qw;
231
+ x = qx;
232
+ y = qy;
233
+ z = qz;
234
+ return *this;
235
+ }
236
+
237
+ template <typename T>
238
+ inline Quat<T>& Quat<T>::operator/=(const Quat<T> &q1)
239
+ {
240
+ Quat<T> q(*this * q1.inv());
241
+ w = q.w;
242
+ x = q.x;
243
+ y = q.y;
244
+ z = q.z;
245
+ return *this;
246
+ }
247
+ template <typename T>
248
+ Quat<T>& Quat<T>::operator*=(const T q1)
249
+ {
250
+ w *= q1;
251
+ x *= q1;
252
+ y *= q1;
253
+ z *= q1;
254
+ return *this;
255
+ }
256
+
257
+ template <typename T>
258
+ inline Quat<T>& Quat<T>::operator/=(const T a)
259
+ {
260
+ const T a_inv = 1.0 / a;
261
+ w *= a_inv;
262
+ x *= a_inv;
263
+ y *= a_inv;
264
+ z *= a_inv;
265
+ return *this;
266
+ }
267
+
268
+ template <typename T>
269
+ inline Quat<T> Quat<T>::operator/(const T a) const
270
+ {
271
+ const T a_inv = T(1.0) / a;
272
+ return Quat<T>(w * a_inv, x * a_inv, y * a_inv, z * a_inv);
273
+ }
274
+
275
+ template <typename T>
276
+ inline Quat<T> Quat<T>::operator/(const Quat<T> &q) const
277
+ {
278
+ return *this * q.inv();
279
+ }
280
+
281
+ template <typename T>
282
+ inline const T& Quat<T>::operator[](std::size_t n) const
283
+ {
284
+ switch (n) {
285
+ case 0:
286
+ return w;
287
+ case 1:
288
+ return x;
289
+ case 2:
290
+ return y;
291
+ case 3:
292
+ return z;
293
+ default:
294
+ CV_Error(Error::StsOutOfRange, "subscript exceeds the index range");
295
+ }
296
+ }
297
+
298
+ template <typename T>
299
+ inline T& Quat<T>::operator[](std::size_t n)
300
+ {
301
+ switch (n) {
302
+ case 0:
303
+ return w;
304
+ case 1:
305
+ return x;
306
+ case 2:
307
+ return y;
308
+ case 3:
309
+ return z;
310
+ default:
311
+ CV_Error(Error::StsOutOfRange, "subscript exceeds the index range");
312
+ }
313
+ }
314
+
315
+ template <typename T>
316
+ std::ostream & operator<<(std::ostream &os, const Quat<T> &q)
317
+ {
318
+ os << "Quat " << Vec<T, 4>{q.w, q.x, q.y, q.z};
319
+ return os;
320
+ }
321
+
322
+ template <typename T>
323
+ inline T Quat<T>::at(size_t index) const
324
+ {
325
+ return (*this)[index];
326
+ }
327
+
328
+ template <typename T>
329
+ inline Quat<T> Quat<T>::conjugate() const
330
+ {
331
+ return Quat<T>(w, -x, -y, -z);
332
+ }
333
+
334
+ template <typename T>
335
+ inline T Quat<T>::norm() const
336
+ {
337
+ return std::sqrt(dot(*this));
338
+ }
339
+
340
+ template <typename T>
341
+ Quat<T> exp(const Quat<T> &q)
342
+ {
343
+ return q.exp();
344
+ }
345
+
346
+ template <typename T>
347
+ Quat<T> Quat<T>::exp() const
348
+ {
349
+ Vec<T, 3> v{x, y, z};
350
+ T normV = std::sqrt(v.dot(v));
351
+ T k = normV < CV_QUAT_EPS ? 1 : std::sin(normV) / normV;
352
+ return std::exp(w) * Quat<T>(std::cos(normV), v[0] * k, v[1] * k, v[2] * k);
353
+ }
354
+
355
+ template <typename T>
356
+ Quat<T> log(const Quat<T> &q, QuatAssumeType assumeUnit)
357
+ {
358
+ return q.log(assumeUnit);
359
+ }
360
+
361
+ template <typename T>
362
+ Quat<T> Quat<T>::log(QuatAssumeType assumeUnit) const
363
+ {
364
+ Vec<T, 3> v{x, y, z};
365
+ T vNorm = std::sqrt(v.dot(v));
366
+ if (assumeUnit)
367
+ {
368
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::acos(w) / vNorm;
369
+ return Quat<T>(0, v[0] * k, v[1] * k, v[2] * k);
370
+ }
371
+ T qNorm = norm();
372
+ if (qNorm < CV_QUAT_EPS)
373
+ {
374
+ CV_Error(Error::StsBadArg, "Cannot apply this quaternion to log function: undefined");
375
+ }
376
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::acos(w / qNorm) / vNorm;
377
+ return Quat<T>(std::log(qNorm), v[0] * k, v[1] * k, v[2] *k);
378
+ }
379
+
380
+ template <typename T>
381
+ inline Quat<T> power(const Quat<T> &q1, const T alpha, QuatAssumeType assumeUnit)
382
+ {
383
+ return q1.power(alpha, assumeUnit);
384
+ }
385
+
386
+ template <typename T>
387
+ inline Quat<T> Quat<T>::power(const T alpha, QuatAssumeType assumeUnit) const
388
+ {
389
+ if (x * x + y * y + z * z > CV_QUAT_EPS)
390
+ {
391
+ T angle = getAngle(assumeUnit);
392
+ Vec<T, 3> axis = getAxis(assumeUnit);
393
+ if (assumeUnit)
394
+ {
395
+ return createFromAngleAxis(alpha * angle, axis);
396
+ }
397
+ return std::pow(norm(), alpha) * createFromAngleAxis(alpha * angle, axis);
398
+ }
399
+ else
400
+ {
401
+ return std::pow(norm(), alpha) * Quat<T>(w, x, y, z);
402
+ }
403
+ }
404
+
405
+
406
+ template <typename T>
407
+ inline Quat<T> sqrt(const Quat<T> &q, QuatAssumeType assumeUnit)
408
+ {
409
+ return q.sqrt(assumeUnit);
410
+ }
411
+
412
+ template <typename T>
413
+ inline Quat<T> Quat<T>::sqrt(QuatAssumeType assumeUnit) const
414
+ {
415
+ return power(0.5, assumeUnit);
416
+ }
417
+
418
+
419
+ template <typename T>
420
+ inline Quat<T> power(const Quat<T> &p, const Quat<T> &q, QuatAssumeType assumeUnit)
421
+ {
422
+ return p.power(q, assumeUnit);
423
+ }
424
+
425
+
426
+ template <typename T>
427
+ inline Quat<T> Quat<T>::power(const Quat<T> &q, QuatAssumeType assumeUnit) const
428
+ {
429
+ return cv::exp(q * log(assumeUnit));
430
+ }
431
+
432
+ template <typename T>
433
+ inline T Quat<T>::dot(Quat<T> q1) const
434
+ {
435
+ return w * q1.w + x * q1.x + y * q1.y + z * q1.z;
436
+ }
437
+
438
+
439
+ template <typename T>
440
+ inline Quat<T> crossProduct(const Quat<T> &p, const Quat<T> &q)
441
+ {
442
+ return p.crossProduct(q);
443
+ }
444
+
445
+
446
+ template <typename T>
447
+ inline Quat<T> Quat<T>::crossProduct(const Quat<T> &q) const
448
+ {
449
+ return Quat<T> (0, y * q.z - z * q.y, z * q.x - x * q.z, x * q.y - q.x * y);
450
+ }
451
+
452
+ template <typename T>
453
+ inline Quat<T> Quat<T>::normalize() const
454
+ {
455
+ T normVal = norm();
456
+ if (normVal < CV_QUAT_EPS)
457
+ {
458
+ CV_Error(Error::StsBadArg, "Cannot normalize this quaternion: the norm is too small.");
459
+ }
460
+ return Quat<T>(w / normVal, x / normVal, y / normVal, z / normVal) ;
461
+ }
462
+
463
+ template <typename T>
464
+ inline Quat<T> inv(const Quat<T> &q, QuatAssumeType assumeUnit)
465
+ {
466
+ return q.inv(assumeUnit);
467
+ }
468
+
469
+
470
+ template <typename T>
471
+ inline Quat<T> Quat<T>::inv(QuatAssumeType assumeUnit) const
472
+ {
473
+ if (assumeUnit)
474
+ {
475
+ return conjugate();
476
+ }
477
+ T norm2 = dot(*this);
478
+ if (norm2 < CV_QUAT_EPS)
479
+ {
480
+ CV_Error(Error::StsBadArg, "This quaternion do not have inverse quaternion");
481
+ }
482
+ return conjugate() / norm2;
483
+ }
484
+
485
+ template <typename T>
486
+ inline Quat<T> sinh(const Quat<T> &q)
487
+ {
488
+ return q.sinh();
489
+ }
490
+
491
+
492
+ template <typename T>
493
+ inline Quat<T> Quat<T>::sinh() const
494
+ {
495
+ Vec<T, 3> v{x, y ,z};
496
+ T vNorm = std::sqrt(v.dot(v));
497
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::cosh(w) * std::sin(vNorm) / vNorm;
498
+ return Quat<T>(std::sinh(w) * std::cos(vNorm), v[0] * k, v[1] * k, v[2] * k);
499
+ }
500
+
501
+
502
+ template <typename T>
503
+ inline Quat<T> cosh(const Quat<T> &q)
504
+ {
505
+ return q.cosh();
506
+ }
507
+
508
+
509
+ template <typename T>
510
+ inline Quat<T> Quat<T>::cosh() const
511
+ {
512
+ Vec<T, 3> v{x, y ,z};
513
+ T vNorm = std::sqrt(v.dot(v));
514
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::sinh(w) * std::sin(vNorm) / vNorm;
515
+ return Quat<T>(std::cosh(w) * std::cos(vNorm), v[0] * k, v[1] * k, v[2] * k);
516
+ }
517
+
518
+ template <typename T>
519
+ inline Quat<T> tanh(const Quat<T> &q)
520
+ {
521
+ return q.tanh();
522
+ }
523
+
524
+ template <typename T>
525
+ inline Quat<T> Quat<T>::tanh() const
526
+ {
527
+ return sinh() * cosh().inv();
528
+ }
529
+
530
+
531
+ template <typename T>
532
+ inline Quat<T> sin(const Quat<T> &q)
533
+ {
534
+ return q.sin();
535
+ }
536
+
537
+
538
+ template <typename T>
539
+ inline Quat<T> Quat<T>::sin() const
540
+ {
541
+ Vec<T, 3> v{x, y ,z};
542
+ T vNorm = std::sqrt(v.dot(v));
543
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::cos(w) * std::sinh(vNorm) / vNorm;
544
+ return Quat<T>(std::sin(w) * std::cosh(vNorm), v[0] * k, v[1] * k, v[2] * k);
545
+ }
546
+
547
+ template <typename T>
548
+ inline Quat<T> cos(const Quat<T> &q)
549
+ {
550
+ return q.cos();
551
+ }
552
+
553
+ template <typename T>
554
+ inline Quat<T> Quat<T>::cos() const
555
+ {
556
+ Vec<T, 3> v{x, y ,z};
557
+ T vNorm = std::sqrt(v.dot(v));
558
+ T k = vNorm < CV_QUAT_EPS ? 1 : std::sin(w) * std::sinh(vNorm) / vNorm;
559
+ return Quat<T>(std::cos(w) * std::cosh(vNorm), -v[0] * k, -v[1] * k, -v[2] * k);
560
+ }
561
+
562
+ template <typename T>
563
+ inline Quat<T> tan(const Quat<T> &q)
564
+ {
565
+ return q.tan();
566
+ }
567
+
568
+ template <typename T>
569
+ inline Quat<T> Quat<T>::tan() const
570
+ {
571
+ return sin() * cos().inv();
572
+ }
573
+
574
+ template <typename T>
575
+ inline Quat<T> asinh(const Quat<T> &q)
576
+ {
577
+ return q.asinh();
578
+ }
579
+
580
+ template <typename T>
581
+ inline Quat<T> Quat<T>::asinh() const
582
+ {
583
+ return cv::log(*this + cv::power(*this * *this + Quat<T>(1, 0, 0, 0), 0.5));
584
+ }
585
+
586
+ template <typename T>
587
+ inline Quat<T> acosh(const Quat<T> &q)
588
+ {
589
+ return q.acosh();
590
+ }
591
+
592
+ template <typename T>
593
+ inline Quat<T> Quat<T>::acosh() const
594
+ {
595
+ return cv::log(*this + cv::power(*this * *this - Quat<T>(1,0,0,0), 0.5));
596
+ }
597
+
598
+ template <typename T>
599
+ inline Quat<T> atanh(const Quat<T> &q)
600
+ {
601
+ return q.atanh();
602
+ }
603
+
604
+ template <typename T>
605
+ inline Quat<T> Quat<T>::atanh() const
606
+ {
607
+ Quat<T> ident(1, 0, 0, 0);
608
+ Quat<T> c1 = (ident + *this).log();
609
+ Quat<T> c2 = (ident - *this).log();
610
+ return 0.5 * (c1 - c2);
611
+ }
612
+
613
+ template <typename T>
614
+ inline Quat<T> asin(const Quat<T> &q)
615
+ {
616
+ return q.asin();
617
+ }
618
+
619
+ template <typename T>
620
+ inline Quat<T> Quat<T>::asin() const
621
+ {
622
+ Quat<T> v(0, x, y, z);
623
+ T vNorm = v.norm();
624
+ T k = vNorm < CV_QUAT_EPS ? 1 : vNorm;
625
+ return -v / k * (*this * v / k).asinh();
626
+ }
627
+
628
+ template <typename T>
629
+ inline Quat<T> acos(const Quat<T> &q)
630
+ {
631
+ return q.acos();
632
+ }
633
+
634
+ template <typename T>
635
+ inline Quat<T> Quat<T>::acos() const
636
+ {
637
+ Quat<T> v(0, x, y, z);
638
+ T vNorm = v.norm();
639
+ T k = vNorm < CV_QUAT_EPS ? 1 : vNorm;
640
+ return -v / k * acosh();
641
+ }
642
+
643
+ template <typename T>
644
+ inline Quat<T> atan(const Quat<T> &q)
645
+ {
646
+ return q.atan();
647
+ }
648
+
649
+ template <typename T>
650
+ inline Quat<T> Quat<T>::atan() const
651
+ {
652
+ Quat<T> v(0, x, y, z);
653
+ T vNorm = v.norm();
654
+ T k = vNorm < CV_QUAT_EPS ? 1 : vNorm;
655
+ return -v / k * (*this * v / k).atanh();
656
+ }
657
+
658
+ template <typename T>
659
+ inline T Quat<T>::getAngle(QuatAssumeType assumeUnit) const
660
+ {
661
+ if (assumeUnit)
662
+ {
663
+ return 2 * std::acos(w);
664
+ }
665
+ if (norm() < CV_QUAT_EPS)
666
+ {
667
+ CV_Error(Error::StsBadArg, "This quaternion does not represent a rotation");
668
+ }
669
+ return 2 * std::acos(w / norm());
670
+ }
671
+
672
+ template <typename T>
673
+ inline Vec<T, 3> Quat<T>::getAxis(QuatAssumeType assumeUnit) const
674
+ {
675
+ T angle = getAngle(assumeUnit);
676
+ const T sin_v = std::sin(angle * 0.5);
677
+ if (assumeUnit)
678
+ {
679
+ return Vec<T, 3>{x, y, z} / sin_v;
680
+ }
681
+ return Vec<T, 3> {x, y, z} / (norm() * sin_v);
682
+ }
683
+
684
+ template <typename T>
685
+ Matx<T, 4, 4> Quat<T>::toRotMat4x4(QuatAssumeType assumeUnit) const
686
+ {
687
+ T a = w, b = x, c = y, d = z;
688
+ if (!assumeUnit)
689
+ {
690
+ Quat<T> qTemp = normalize();
691
+ a = qTemp.w;
692
+ b = qTemp.x;
693
+ c = qTemp.y;
694
+ d = qTemp.z;
695
+ }
696
+ Matx<T, 4, 4> R{
697
+ 1 - 2 * (c * c + d * d), 2 * (b * c - a * d) , 2 * (b * d + a * c) , 0,
698
+ 2 * (b * c + a * d) , 1 - 2 * (b * b + d * d), 2 * (c * d - a * b) , 0,
699
+ 2 * (b * d - a * c) , 2 * (c * d + a * b) , 1 - 2 * (b * b + c * c), 0,
700
+ 0 , 0 , 0 , 1,
701
+ };
702
+ return R;
703
+ }
704
+
705
+ template <typename T>
706
+ Matx<T, 3, 3> Quat<T>::toRotMat3x3(QuatAssumeType assumeUnit) const
707
+ {
708
+ T a = w, b = x, c = y, d = z;
709
+ if (!assumeUnit)
710
+ {
711
+ Quat<T> qTemp = normalize();
712
+ a = qTemp.w;
713
+ b = qTemp.x;
714
+ c = qTemp.y;
715
+ d = qTemp.z;
716
+ }
717
+ Matx<T, 3, 3> R{
718
+ 1 - 2 * (c * c + d * d), 2 * (b * c - a * d) , 2 * (b * d + a * c),
719
+ 2 * (b * c + a * d) , 1 - 2 * (b * b + d * d), 2 * (c * d - a * b),
720
+ 2 * (b * d - a * c) , 2 * (c * d + a * b) , 1 - 2 * (b * b + c * c)
721
+ };
722
+ return R;
723
+ }
724
+
725
+ template <typename T>
726
+ Vec<T, 3> Quat<T>::toRotVec(QuatAssumeType assumeUnit) const
727
+ {
728
+ T angle = getAngle(assumeUnit);
729
+ Vec<T, 3> axis = getAxis(assumeUnit);
730
+ return angle * axis;
731
+ }
732
+
733
+ template <typename T>
734
+ Vec<T, 4> Quat<T>::toVec() const
735
+ {
736
+ return Vec<T, 4>{w, x, y, z};
737
+ }
738
+
739
+ template <typename T>
740
+ Quat<T> Quat<T>::lerp(const Quat<T> &q0, const Quat<T> &q1, const T t)
741
+ {
742
+ return (1 - t) * q0 + t * q1;
743
+ }
744
+
745
+ template <typename T>
746
+ Quat<T> Quat<T>::slerp(const Quat<T> &q0, const Quat<T> &q1, const T t, QuatAssumeType assumeUnit, bool directChange)
747
+ {
748
+ Quatd v0(q0);
749
+ Quatd v1(q1);
750
+ if (!assumeUnit)
751
+ {
752
+ v0 = v0.normalize();
753
+ v1 = v1.normalize();
754
+ }
755
+ T cosTheta = v0.dot(v1);
756
+ constexpr T DOT_THRESHOLD = 0.995;
757
+ if (cosTheta > DOT_THRESHOLD)
758
+ {
759
+ return nlerp(v0, v1, t, QUAT_ASSUME_UNIT);
760
+ }
761
+
762
+ if (directChange && cosTheta < 0)
763
+ {
764
+ v0 = -v0;
765
+ cosTheta = -cosTheta;
766
+ }
767
+ T sinTheta = std::sqrt(1 - cosTheta * cosTheta);
768
+ T angle = atan2(sinTheta, cosTheta);
769
+ return (std::sin((1 - t) * angle) / (sinTheta) * v0 + std::sin(t * angle) / (sinTheta) * v1).normalize();
770
+ }
771
+
772
+
773
+ template <typename T>
774
+ inline Quat<T> Quat<T>::nlerp(const Quat<T> &q0, const Quat<T> &q1, const T t, QuatAssumeType assumeUnit)
775
+ {
776
+ Quat<T> v0(q0), v1(q1);
777
+ if (v1.dot(v0) < 0)
778
+ {
779
+ v0 = -v0;
780
+ }
781
+ if (assumeUnit)
782
+ {
783
+ return ((1 - t) * v0 + t * v1).normalize();
784
+ }
785
+ v0 = v0.normalize();
786
+ v1 = v1.normalize();
787
+ return ((1 - t) * v0 + t * v1).normalize();
788
+ }
789
+
790
+
791
+ template <typename T>
792
+ inline bool Quat<T>::isNormal(T eps) const
793
+ {
794
+
795
+ double normVar = norm();
796
+ if ((normVar > 1 - eps) && (normVar < 1 + eps))
797
+ return true;
798
+ return false;
799
+ }
800
+
801
+ template <typename T>
802
+ inline void Quat<T>::assertNormal(T eps) const
803
+ {
804
+ if (!isNormal(eps))
805
+ CV_Error(Error::StsBadArg, "Quaternion should be normalized");
806
+ }
807
+
808
+
809
+ template <typename T>
810
+ inline Quat<T> Quat<T>::squad(const Quat<T> &q0, const Quat<T> &q1,
811
+ const Quat<T> &q2, const Quat<T> &q3,
812
+ const T t, QuatAssumeType assumeUnit,
813
+ bool directChange)
814
+ {
815
+ Quat<T> v0(q0), v1(q1), v2(q2), v3(q3);
816
+ if (!assumeUnit)
817
+ {
818
+ v0 = v0.normalize();
819
+ v1 = v1.normalize();
820
+ v2 = v2.normalize();
821
+ v3 = v3.normalize();
822
+ }
823
+
824
+ Quat<T> c0 = slerp(v0, v3, t, assumeUnit, directChange);
825
+ Quat<T> c1 = slerp(v1, v2, t, assumeUnit, directChange);
826
+ return slerp(c0, c1, 2 * t * (1 - t), assumeUnit, directChange);
827
+ }
828
+
829
+ template <typename T>
830
+ Quat<T> Quat<T>::interPoint(const Quat<T> &q0, const Quat<T> &q1,
831
+ const Quat<T> &q2, QuatAssumeType assumeUnit)
832
+ {
833
+ Quat<T> v0(q0), v1(q1), v2(q2);
834
+ if (!assumeUnit)
835
+ {
836
+ v0 = v0.normalize();
837
+ v1 = v1.normalize();
838
+ v2 = v2.normalize();
839
+ }
840
+ return v1 * cv::exp(-(cv::log(v1.conjugate() * v0, assumeUnit) + (cv::log(v1.conjugate() * v2, assumeUnit))) / 4);
841
+ }
842
+
843
+ template <typename T>
844
+ Quat<T> Quat<T>::spline(const Quat<T> &q0, const Quat<T> &q1, const Quat<T> &q2, const Quat<T> &q3, const T t, QuatAssumeType assumeUnit)
845
+ {
846
+ Quatd v0(q0), v1(q1), v2(q2), v3(q3);
847
+ if (!assumeUnit)
848
+ {
849
+ v0 = v0.normalize();
850
+ v1 = v1.normalize();
851
+ v2 = v2.normalize();
852
+ v3 = v3.normalize();
853
+ }
854
+ T cosTheta;
855
+ std::vector<Quat<T>> vec{v0, v1, v2, v3};
856
+ for (size_t i = 0; i < 3; ++i)
857
+ {
858
+ cosTheta = vec[i].dot(vec[i + 1]);
859
+ if (cosTheta < 0)
860
+ {
861
+ vec[i + 1] = -vec[i + 1];
862
+ }
863
+ }
864
+ Quat<T> s1 = interPoint(vec[0], vec[1], vec[2], QUAT_ASSUME_UNIT);
865
+ Quat<T> s2 = interPoint(vec[1], vec[2], vec[3], QUAT_ASSUME_UNIT);
866
+ return squad(vec[1], s1, s2, vec[2], t, assumeUnit, QUAT_ASSUME_NOT_UNIT);
867
+ }
868
+
869
+ namespace detail {
870
+
871
+ template <typename T> static
872
+ Quat<T> createFromAxisRot(int axis, const T theta)
873
+ {
874
+ if (axis == 0)
875
+ return Quat<T>::createFromXRot(theta);
876
+ if (axis == 1)
877
+ return Quat<T>::createFromYRot(theta);
878
+ if (axis == 2)
879
+ return Quat<T>::createFromZRot(theta);
880
+ CV_Assert(0);
881
+ }
882
+
883
+ inline bool isIntAngleType(QuatEnum::EulerAnglesType eulerAnglesType)
884
+ {
885
+ return eulerAnglesType < QuatEnum::EXT_XYZ;
886
+ }
887
+
888
+ inline bool isTaitBryan(QuatEnum::EulerAnglesType eulerAnglesType)
889
+ {
890
+ return eulerAnglesType/6 == 1 || eulerAnglesType/6 == 3;
891
+ }
892
+ } // namespace detail
893
+
894
+ template <typename T>
895
+ Quat<T> Quat<T>::createFromYRot(const T theta)
896
+ {
897
+ return Quat<T>{std::cos(theta * 0.5f), 0, std::sin(theta * 0.5f), 0};
898
+ }
899
+
900
+ template <typename T>
901
+ Quat<T> Quat<T>::createFromXRot(const T theta){
902
+ return Quat<T>{std::cos(theta * 0.5f), std::sin(theta * 0.5f), 0, 0};
903
+ }
904
+
905
+ template <typename T>
906
+ Quat<T> Quat<T>::createFromZRot(const T theta){
907
+ return Quat<T>{std::cos(theta * 0.5f), 0, 0, std::sin(theta * 0.5f)};
908
+ }
909
+
910
+
911
+ template <typename T>
912
+ Quat<T> Quat<T>::createFromEulerAngles(const Vec<T, 3> &angles, QuatEnum::EulerAnglesType eulerAnglesType) {
913
+ CV_Assert(eulerAnglesType < QuatEnum::EulerAnglesType::EULER_ANGLES_MAX_VALUE);
914
+ static const int rotationAxis[24][3] = {
915
+ {0, 1, 2}, ///< Intrinsic rotations with the Euler angles type X-Y-Z
916
+ {0, 2, 1}, ///< Intrinsic rotations with the Euler angles type X-Z-Y
917
+ {1, 0, 2}, ///< Intrinsic rotations with the Euler angles type Y-X-Z
918
+ {1, 2, 0}, ///< Intrinsic rotations with the Euler angles type Y-Z-X
919
+ {2, 0, 1}, ///< Intrinsic rotations with the Euler angles type Z-X-Y
920
+ {2, 1, 0}, ///< Intrinsic rotations with the Euler angles type Z-Y-X
921
+ {0, 1, 0}, ///< Intrinsic rotations with the Euler angles type X-Y-X
922
+ {0, 2, 0}, ///< Intrinsic rotations with the Euler angles type X-Z-X
923
+ {1, 0, 1}, ///< Intrinsic rotations with the Euler angles type Y-X-Y
924
+ {1, 2, 1}, ///< Intrinsic rotations with the Euler angles type Y-Z-Y
925
+ {2, 0, 2}, ///< Intrinsic rotations with the Euler angles type Z-X-Z
926
+ {2, 1, 2}, ///< Intrinsic rotations with the Euler angles type Z-Y-Z
927
+ {0, 1, 2}, ///< Extrinsic rotations with the Euler angles type X-Y-Z
928
+ {0, 2, 1}, ///< Extrinsic rotations with the Euler angles type X-Z-Y
929
+ {1, 0, 2}, ///< Extrinsic rotations with the Euler angles type Y-X-Z
930
+ {1, 2, 0}, ///< Extrinsic rotations with the Euler angles type Y-Z-X
931
+ {2, 0, 1}, ///< Extrinsic rotations with the Euler angles type Z-X-Y
932
+ {2, 1, 0}, ///< Extrinsic rotations with the Euler angles type Z-Y-X
933
+ {0, 1, 0}, ///< Extrinsic rotations with the Euler angles type X-Y-X
934
+ {0, 2, 0}, ///< Extrinsic rotations with the Euler angles type X-Z-X
935
+ {1, 0, 1}, ///< Extrinsic rotations with the Euler angles type Y-X-Y
936
+ {1, 2, 1}, ///< Extrinsic rotations with the Euler angles type Y-Z-Y
937
+ {2, 0, 2}, ///< Extrinsic rotations with the Euler angles type Z-X-Z
938
+ {2, 1, 2} ///< Extrinsic rotations with the Euler angles type Z-Y-Z
939
+ };
940
+ Quat<T> q1 = detail::createFromAxisRot(rotationAxis[eulerAnglesType][0], angles(0));
941
+ Quat<T> q2 = detail::createFromAxisRot(rotationAxis[eulerAnglesType][1], angles(1));
942
+ Quat<T> q3 = detail::createFromAxisRot(rotationAxis[eulerAnglesType][2], angles(2));
943
+ if (detail::isIntAngleType(eulerAnglesType))
944
+ {
945
+ return q1 * q2 * q3;
946
+ }
947
+ else // (!detail::isIntAngleType<T>(eulerAnglesType))
948
+ {
949
+ return q3 * q2 * q1;
950
+ }
951
+ }
952
+
953
+ template <typename T>
954
+ Vec<T, 3> Quat<T>::toEulerAngles(QuatEnum::EulerAnglesType eulerAnglesType){
955
+ CV_Assert(eulerAnglesType < QuatEnum::EulerAnglesType::EULER_ANGLES_MAX_VALUE);
956
+ Matx33d R = toRotMat3x3();
957
+ enum {
958
+ C_ZERO,
959
+ C_PI,
960
+ C_PI_2,
961
+ N_CONSTANTS,
962
+ R_0_0 = N_CONSTANTS, R_0_1, R_0_2,
963
+ R_1_0, R_1_1, R_1_2,
964
+ R_2_0, R_2_1, R_2_2
965
+ };
966
+ static const T constants_[N_CONSTANTS] = {
967
+ 0, // C_ZERO
968
+ (T)CV_PI, // C_PI
969
+ (T)(CV_PI * 0.5) // C_PI_2, -C_PI_2
970
+ };
971
+ static const int rotationR_[24][12] = {
972
+ {+R_0_2, +R_1_0, +R_1_1, C_PI_2, +R_2_1, +R_1_1, -C_PI_2, -R_1_2, +R_2_2, +R_0_2, -R_0_1, +R_0_0}, // INT_XYZ
973
+ {+R_0_1, -R_1_2, +R_2_2, -C_PI_2, +R_2_0, +R_2_2, C_PI_2, +R_2_1, +R_1_1, -R_0_1, +R_0_2, +R_0_0}, // INT_XZY
974
+ {+R_1_2, -R_0_1, +R_0_0, -C_PI_2, +R_0_1, +R_0_0, C_PI_2, +R_0_2, +R_2_2, -R_1_2, +R_1_0, +R_1_1}, // INT_YXZ
975
+ {+R_1_0, +R_0_2, +R_2_2, C_PI_2, +R_0_2, +R_0_1, -C_PI_2, -R_2_0, +R_0_0, +R_1_0, -R_1_2, +R_1_1}, // INT_YZX
976
+ {+R_2_1, +R_1_0, +R_0_0, C_PI_2, +R_1_0, +R_0_0, -C_PI_2, -R_0_1, +R_1_1, +R_2_1, -R_2_0, +R_2_2}, // INT_ZXY
977
+ {+R_2_0, -R_0_1, +R_1_1, -C_PI_2, +R_1_2, +R_1_1, C_PI_2, +R_1_0, +R_0_0, -R_2_0, +R_2_1, +R_2_2}, // INT_ZYX
978
+ {+R_0_0, +R_2_1, +R_2_2, C_ZERO, +R_1_2, +R_1_1, C_PI, +R_1_0, -R_2_0, +R_0_0, +R_0_1, +R_0_2}, // INT_XYX
979
+ {+R_0_0, +R_2_1, +R_2_2, C_ZERO, -R_2_1, +R_2_2, C_PI, +R_2_0, +R_1_0, +R_0_0, +R_0_2, -R_0_1}, // INT_XZX
980
+ {+R_1_1, +R_0_2, +R_0_0, C_ZERO, -R_2_0, +R_0_0, C_PI, +R_0_1, +R_2_1, +R_1_1, +R_1_0, -R_1_2}, // INT_YXY
981
+ {+R_1_1, +R_0_2, +R_0_0, C_ZERO, +R_0_2, -R_0_0, C_PI, +R_2_1, -R_0_1, +R_1_1, +R_1_2, +R_1_0}, // INT_YZY
982
+ {+R_2_2, +R_1_0, +R_1_1, C_ZERO, +R_1_0, +R_0_0, C_PI, +R_0_2, -R_1_2, +R_2_2, +R_2_0, +R_2_1}, // INT_ZXZ
983
+ {+R_2_2, +R_1_0, +R_0_0, C_ZERO, +R_1_0, +R_0_0, C_PI, +R_1_2, +R_0_2, +R_2_2, +R_2_1, -R_2_0}, // INT_ZYZ
984
+
985
+ {+R_2_0, -C_PI_2, -R_0_1, +R_1_1, C_PI_2, +R_1_2, +R_1_1, +R_2_1, +R_2_2, -R_2_0, +R_1_0, +R_0_0}, // EXT_XYZ
986
+ {+R_1_0, C_PI_2, +R_0_2, +R_2_2, -C_PI_2, +R_0_2, +R_0_1, -R_1_2, +R_1_1, +R_1_0, -R_2_0, +R_0_0}, // EXT_XZY
987
+ {+R_2_1, C_PI_2, +R_1_0, +R_0_0, -C_PI_2, +R_1_0, +R_0_0, -R_2_0, +R_2_2, +R_2_1, -R_0_1, +R_1_1}, // EXT_YXZ
988
+ {+R_0_2, -C_PI_2, -R_1_2, +R_2_2, C_PI_2, +R_2_0, +R_2_2, +R_0_2, +R_0_0, -R_0_1, +R_2_1, +R_1_1}, // EXT_YZX
989
+ {+R_1_2, -C_PI_2, -R_0_1, +R_0_0, C_PI_2, +R_0_1, +R_0_0, +R_1_0, +R_1_1, -R_1_2, +R_0_2, +R_2_2}, // EXT_ZXY
990
+ {+R_0_2, C_PI_2, +R_1_0, +R_1_1, -C_PI_2, +R_2_1, +R_1_1, -R_0_1, +R_0_0, +R_0_2, -R_1_2, +R_2_2}, // EXT_ZYX
991
+ {+R_0_0, C_ZERO, +R_2_1, +R_2_2, C_PI, +R_1_2, +R_1_1, +R_0_1, +R_0_2, +R_0_0, +R_1_0, -R_2_0}, // EXT_XYX
992
+ {+R_0_0, C_ZERO, +R_2_1, +R_2_2, C_PI, +R_2_1, +R_2_2, +R_0_2, -R_0_1, +R_0_0, +R_2_0, +R_1_0}, // EXT_XZX
993
+ {+R_1_1, C_ZERO, +R_0_2, +R_0_0, C_PI, -R_2_0, +R_0_0, +R_1_0, -R_1_2, +R_1_1, +R_0_1, +R_2_1}, // EXT_YXY
994
+ {+R_1_1, C_ZERO, +R_0_2, +R_0_0, C_PI, +R_0_2, -R_0_0, +R_1_2, +R_1_0, +R_1_1, +R_2_1, -R_0_1}, // EXT_YZY
995
+ {+R_2_2, C_ZERO, +R_1_0, +R_1_1, C_PI, +R_1_0, +R_0_0, +R_2_0, +R_2_1, +R_2_2, +R_0_2, -R_1_2}, // EXT_ZXZ
996
+ {+R_2_2, C_ZERO, +R_1_0, +R_0_0, C_PI, +R_1_0, +R_0_0, +R_2_1, -R_2_0, +R_2_2, +R_1_2, +R_0_2}, // EXT_ZYZ
997
+ };
998
+ T rotationR[12];
999
+ for (int i = 0; i < 12; i++)
1000
+ {
1001
+ int id = rotationR_[eulerAnglesType][i];
1002
+ unsigned idx = std::abs(id);
1003
+ T value = 0.0f;
1004
+ if (idx < N_CONSTANTS)
1005
+ {
1006
+ value = constants_[idx];
1007
+ }
1008
+ else
1009
+ {
1010
+ unsigned r_idx = idx - N_CONSTANTS;
1011
+ CV_DbgAssert(r_idx < 9);
1012
+ value = R.val[r_idx];
1013
+ }
1014
+ bool isNegative = id < 0;
1015
+ if (isNegative)
1016
+ value = -value;
1017
+ rotationR[i] = value;
1018
+ }
1019
+ Vec<T, 3> angles;
1020
+ if (detail::isIntAngleType(eulerAnglesType))
1021
+ {
1022
+ if (abs(rotationR[0] - 1) < CV_QUAT_CONVERT_THRESHOLD)
1023
+ {
1024
+ CV_LOG_WARNING(NULL,"Gimbal Lock occurs. Euler angles are non-unique, we set the third angle to 0");
1025
+ angles = {std::atan2(rotationR[1], rotationR[2]), rotationR[3], 0};
1026
+ return angles;
1027
+ }
1028
+ else if(abs(rotationR[0] + 1) < CV_QUAT_CONVERT_THRESHOLD)
1029
+ {
1030
+ CV_LOG_WARNING(NULL,"Gimbal Lock occurs. Euler angles are non-unique, we set the third angle to 0");
1031
+ angles = {std::atan2(rotationR[4], rotationR[5]), rotationR[6], 0};
1032
+ return angles;
1033
+ }
1034
+ }
1035
+ else // (!detail::isIntAngleType<T>(eulerAnglesType))
1036
+ {
1037
+ if (abs(rotationR[0] - 1) < CV_QUAT_CONVERT_THRESHOLD)
1038
+ {
1039
+ CV_LOG_WARNING(NULL,"Gimbal Lock occurs. Euler angles are non-unique, we set the first angle to 0");
1040
+ angles = {0, rotationR[1], std::atan2(rotationR[2], rotationR[3])};
1041
+ return angles;
1042
+ }
1043
+ else if (abs(rotationR[0] + 1) < CV_QUAT_CONVERT_THRESHOLD)
1044
+ {
1045
+ CV_LOG_WARNING(NULL,"Gimbal Lock occurs. Euler angles are non-unique, we set the first angle to 0");
1046
+ angles = {0, rotationR[4], std::atan2(rotationR[5], rotationR[6])};
1047
+ return angles;
1048
+ }
1049
+ }
1050
+
1051
+ angles(0) = std::atan2(rotationR[7], rotationR[8]);
1052
+ if (detail::isTaitBryan(eulerAnglesType))
1053
+ angles(1) = std::acos(rotationR[9]);
1054
+ else
1055
+ angles(1) = std::asin(rotationR[9]);
1056
+ angles(2) = std::atan2(rotationR[10], rotationR[11]);
1057
+ return angles;
1058
+ }
1059
+
1060
+ } // namepsace
1061
+ //! @endcond
1062
+
1063
+ #endif /*OPENCV_CORE_QUATERNION_INL_HPP*/