Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: RZ_A2M_Mbed_samples
affine.hpp
00001 /*M/////////////////////////////////////////////////////////////////////////////////////// 00002 // 00003 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 00004 // 00005 // By downloading, copying, installing or using the software you agree to this license. 00006 // If you do not agree to this license, do not download, install, 00007 // copy or use the software. 00008 // 00009 // 00010 // License Agreement 00011 // For Open Source Computer Vision Library 00012 // 00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 00015 // Copyright (C) 2013, OpenCV Foundation, all rights reserved. 00016 // Third party copyrights are property of their respective owners. 00017 // 00018 // Redistribution and use in source and binary forms, with or without modification, 00019 // are permitted provided that the following conditions are met: 00020 // 00021 // * Redistribution's of source code must retain the above copyright notice, 00022 // this list of conditions and the following disclaimer. 00023 // 00024 // * Redistribution's in binary form must reproduce the above copyright notice, 00025 // this list of conditions and the following disclaimer in the documentation 00026 // and/or other materials provided with the distribution. 00027 // 00028 // * The name of the copyright holders may not be used to endorse or promote products 00029 // derived from this software without specific prior written permission. 00030 // 00031 // This software is provided by the copyright holders and contributors "as is" and 00032 // any express or implied warranties, including, but not limited to, the implied 00033 // warranties of merchantability and fitness for a particular purpose are disclaimed. 00034 // In no event shall the Intel Corporation or contributors be liable for any direct, 00035 // indirect, incidental, special, exemplary, or consequential damages 00036 // (including, but not limited to, procurement of substitute goods or services; 00037 // loss of use, data, or profits; or business interruption) however caused 00038 // and on any theory of liability, whether in contract, strict liability, 00039 // or tort (including negligence or otherwise) arising in any way out of 00040 // the use of this software, even if advised of the possibility of such damage. 00041 // 00042 //M*/ 00043 00044 #ifndef OPENCV_CORE_AFFINE3_HPP 00045 #define OPENCV_CORE_AFFINE3_HPP 00046 00047 #ifdef __cplusplus 00048 00049 #include <opencv2/core.hpp> 00050 00051 namespace cv 00052 { 00053 00054 //! @addtogroup core 00055 //! @{ 00056 00057 /** @brief Affine transform 00058 @todo document 00059 */ 00060 template<typename T> 00061 class Affine3 00062 { 00063 public: 00064 typedef T float_type; 00065 typedef Matx<float_type, 3, 3> Mat3; 00066 typedef Matx<float_type, 4, 4> Mat4 ; 00067 typedef Vec<float_type, 3> Vec3; 00068 00069 Affine3(); 00070 00071 //! Augmented affine matrix 00072 Affine3(const Mat4 & affine); 00073 00074 //! Rotation matrix 00075 Affine3(const Mat3& R, const Vec3& t = Vec3::all(0)); 00076 00077 //! Rodrigues vector 00078 Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); 00079 00080 //! Combines all contructors above. Supports 4x4, 4x3, 3x3, 1x3, 3x1 sizes of data matrix 00081 explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); 00082 00083 //! From 16th element array 00084 explicit Affine3(const float_type* vals); 00085 00086 //! Create identity transform 00087 static Affine3 Identity(); 00088 00089 //! Rotation matrix 00090 void rotation(const Mat3& R); 00091 00092 //! Rodrigues vector 00093 void rotation(const Vec3& rvec); 00094 00095 //! Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; 00096 void rotation(const Mat& data); 00097 00098 void linear(const Mat3& L); 00099 void translation(const Vec3& t); 00100 00101 Mat3 rotation() const; 00102 Mat3 linear() const; 00103 Vec3 translation() const; 00104 00105 //! Rodrigues vector 00106 Vec3 rvec() const; 00107 00108 Affine3 inv(int method = cv::DECOMP_SVD) const; 00109 00110 //! a.rotate(R) is equivalent to Affine(R, 0) * a; 00111 Affine3 rotate(const Mat3& R) const; 00112 00113 //! a.rotate(rvec) is equivalent to Affine(rvec, 0) * a; 00114 Affine3 rotate(const Vec3& rvec) const; 00115 00116 //! a.translate(t) is equivalent to Affine(E, t) * a; 00117 Affine3 translate(const Vec3& t) const; 00118 00119 //! a.concatenate(affine) is equivalent to affine * a; 00120 Affine3 concatenate(const Affine3& affine) const; 00121 00122 template <typename Y> operator Affine3<Y>() const; 00123 00124 template <typename Y> Affine3<Y> cast() const; 00125 00126 Mat4 matrix; 00127 00128 #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H 00129 Affine3(const Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>& affine); 00130 Affine3(const Eigen::Transform<T, 3, Eigen::Affine>& affine); 00131 operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>() const; 00132 operator Eigen::Transform<T, 3, Eigen::Affine>() const; 00133 #endif 00134 }; 00135 00136 template<typename T> static 00137 Affine3<T> operator*(const Affine3<T>& affine1, const Affine3<T>& affine2); 00138 00139 template<typename T, typename V> static 00140 V operator*(const Affine3<T>& affine, const V& vector); 00141 00142 typedef Affine3<float> Affine3f; 00143 typedef Affine3<double> Affine3d; 00144 00145 static Vec3f operator*(const Affine3f& affine, const Vec3f& vector); 00146 static Vec3d operator*(const Affine3d& affine, const Vec3d& vector); 00147 00148 template<typename _Tp> class DataType< Affine3<_Tp> > 00149 { 00150 public: 00151 typedef Affine3<_Tp> value_type; 00152 typedef Affine3<typename DataType<_Tp>::work_type> work_type; 00153 typedef _Tp channel_type; 00154 00155 enum { generic_type = 0, 00156 depth = DataType<channel_type>::depth, 00157 channels = 16, 00158 fmt = DataType<channel_type>::fmt + ((channels - 1) << 8), 00159 type = CV_MAKETYPE(depth, channels) 00160 }; 00161 00162 typedef Vec<channel_type, channels> vec_type; 00163 }; 00164 00165 //! @} core 00166 00167 } 00168 00169 //! @cond IGNORED 00170 00171 /////////////////////////////////////////////////////////////////////////////////// 00172 // Implementaiton 00173 00174 template<typename T> inline 00175 cv::Affine3<T>::Affine3() 00176 : matrix(Mat4::eye()) 00177 {} 00178 00179 template<typename T> inline 00180 cv::Affine3<T>::Affine3(const Mat4& affine) 00181 : matrix(affine) 00182 {} 00183 00184 template<typename T> inline 00185 cv::Affine3<T>::Affine3(const Mat3& R, const Vec3& t) 00186 { 00187 rotation(R); 00188 translation(t); 00189 matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; 00190 matrix.val[15] = 1; 00191 } 00192 00193 template<typename T> inline 00194 cv::Affine3<T>::Affine3(const Vec3& _rvec, const Vec3& t) 00195 { 00196 rotation(_rvec); 00197 translation(t); 00198 matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; 00199 matrix.val[15] = 1; 00200 } 00201 00202 template<typename T> inline 00203 cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t) 00204 { 00205 CV_Assert(data.type() == cv::DataType<T>::type); 00206 00207 if (data.cols == 4 && data.rows == 4) 00208 { 00209 data.copyTo(matrix); 00210 return; 00211 } 00212 else if (data.cols == 4 && data.rows == 3) 00213 { 00214 rotation(data(Rect(0, 0, 3, 3))); 00215 translation(data(Rect(3, 0, 1, 3))); 00216 return; 00217 } 00218 00219 rotation(data); 00220 translation(t); 00221 matrix.val[12] = matrix.val[13] = matrix.val[14] = 0; 00222 matrix.val[15] = 1; 00223 } 00224 00225 template<typename T> inline 00226 cv::Affine3<T>::Affine3(const float_type* vals) : matrix(vals) 00227 {} 00228 00229 template<typename T> inline 00230 cv::Affine3<T> cv::Affine3<T>::Identity() 00231 { 00232 return Affine3<T>(cv::Affine3<T>::Mat4::eye()); 00233 } 00234 00235 template<typename T> inline 00236 void cv::Affine3<T>::rotation(const Mat3& R) 00237 { 00238 linear(R); 00239 } 00240 00241 template<typename T> inline 00242 void cv::Affine3<T>::rotation(const Vec3& _rvec) 00243 { 00244 double theta = norm(_rvec); 00245 00246 if (theta < DBL_EPSILON) 00247 rotation(Mat3::eye()); 00248 else 00249 { 00250 double c = std::cos(theta); 00251 double s = std::sin(theta); 00252 double c1 = 1. - c; 00253 double itheta = (theta != 0) ? 1./theta : 0.; 00254 00255 Point3_<T> r = _rvec*itheta; 00256 00257 Mat3 rrt( r.x*r.x, r.x*r.y, r.x*r.z, r.x*r.y, r.y*r.y, r.y*r.z, r.x*r.z, r.y*r.z, r.z*r.z ); 00258 Mat3 r_x( 0, -r.z, r.y, r.z, 0, -r.x, -r.y, r.x, 0 ); 00259 00260 // R = cos(theta)*I + (1 - cos(theta))*r*rT + sin(theta)*[r_x] 00261 // where [r_x] is [0 -rz ry; rz 0 -rx; -ry rx 0] 00262 Mat3 R = c*Mat3::eye() + c1*rrt + s*r_x; 00263 00264 rotation(R); 00265 } 00266 } 00267 00268 //Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix; 00269 template<typename T> inline 00270 void cv::Affine3<T>::rotation(const cv::Mat& data) 00271 { 00272 CV_Assert(data.type() == cv::DataType<T>::type); 00273 00274 if (data.cols == 3 && data.rows == 3) 00275 { 00276 Mat3 R; 00277 data.copyTo(R); 00278 rotation(R); 00279 } 00280 else if ((data.cols == 3 && data.rows == 1) || (data.cols == 1 && data.rows == 3)) 00281 { 00282 Vec3 _rvec; 00283 data.reshape(1, 3).copyTo(_rvec); 00284 rotation(_rvec); 00285 } 00286 else 00287 CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); 00288 } 00289 00290 template<typename T> inline 00291 void cv::Affine3<T>::linear(const Mat3& L) 00292 { 00293 matrix.val[0] = L.val[0]; matrix.val[1] = L.val[1]; matrix.val[ 2] = L.val[2]; 00294 matrix.val[4] = L.val[3]; matrix.val[5] = L.val[4]; matrix.val[ 6] = L.val[5]; 00295 matrix.val[8] = L.val[6]; matrix.val[9] = L.val[7]; matrix.val[10] = L.val[8]; 00296 } 00297 00298 template<typename T> inline 00299 void cv::Affine3<T>::translation(const Vec3& t) 00300 { 00301 matrix.val[3] = t[0]; matrix.val[7] = t[1]; matrix.val[11] = t[2]; 00302 } 00303 00304 template<typename T> inline 00305 typename cv::Affine3<T>::Mat3 cv::Affine3<T>::rotation() const 00306 { 00307 return linear(); 00308 } 00309 00310 template<typename T> inline 00311 typename cv::Affine3<T>::Mat3 cv::Affine3<T>::linear() const 00312 { 00313 typename cv::Affine3<T>::Mat3 R; 00314 R.val[0] = matrix.val[0]; R.val[1] = matrix.val[1]; R.val[2] = matrix.val[ 2]; 00315 R.val[3] = matrix.val[4]; R.val[4] = matrix.val[5]; R.val[5] = matrix.val[ 6]; 00316 R.val[6] = matrix.val[8]; R.val[7] = matrix.val[9]; R.val[8] = matrix.val[10]; 00317 return R; 00318 } 00319 00320 template<typename T> inline 00321 typename cv::Affine3<T>::Vec3 cv::Affine3<T>::translation() const 00322 { 00323 return Vec3(matrix.val[3], matrix.val[7], matrix.val[11]); 00324 } 00325 00326 template<typename T> inline 00327 typename cv::Affine3<T>::Vec3 cv::Affine3<T>::rvec() const 00328 { 00329 cv::Vec3d w; 00330 cv::Matx33d u, vt, R = rotation(); 00331 cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A); 00332 R = u * vt; 00333 00334 double rx = R.val[7] - R.val[5]; 00335 double ry = R.val[2] - R.val[6]; 00336 double rz = R.val[3] - R.val[1]; 00337 00338 double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25); 00339 double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5; 00340 c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c; 00341 double theta = acos(c); 00342 00343 if( s < 1e-5 ) 00344 { 00345 if( c > 0 ) 00346 rx = ry = rz = 0; 00347 else 00348 { 00349 double t; 00350 t = (R.val[0] + 1) * 0.5; 00351 rx = std::sqrt(std::max(t, 0.0)); 00352 t = (R.val[4] + 1) * 0.5; 00353 ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0); 00354 t = (R.val[8] + 1) * 0.5; 00355 rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0); 00356 00357 if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) ) 00358 rz = -rz; 00359 theta /= std::sqrt(rx*rx + ry*ry + rz*rz); 00360 rx *= theta; 00361 ry *= theta; 00362 rz *= theta; 00363 } 00364 } 00365 else 00366 { 00367 double vth = 1/(2*s); 00368 vth *= theta; 00369 rx *= vth; ry *= vth; rz *= vth; 00370 } 00371 00372 return cv::Vec3d(rx, ry, rz); 00373 } 00374 00375 template<typename T> inline 00376 cv::Affine3<T> cv::Affine3<T>::inv(int method) const 00377 { 00378 return matrix.inv(method); 00379 } 00380 00381 template<typename T> inline 00382 cv::Affine3<T> cv::Affine3<T>::rotate(const Mat3& R) const 00383 { 00384 Mat3 Lc = linear(); 00385 Vec3 tc = translation(); 00386 Mat4 result; 00387 result.val[12] = result.val[13] = result.val[14] = 0; 00388 result.val[15] = 1; 00389 00390 for(int j = 0; j < 3; ++j) 00391 { 00392 for(int i = 0; i < 3; ++i) 00393 { 00394 float_type value = 0; 00395 for(int k = 0; k < 3; ++k) 00396 value += R(j, k) * Lc(k, i); 00397 result(j, i) = value; 00398 } 00399 00400 result(j, 3) = R.row(j).dot(tc.t()); 00401 } 00402 return result; 00403 } 00404 00405 template<typename T> inline 00406 cv::Affine3<T> cv::Affine3<T>::rotate(const Vec3& _rvec) const 00407 { 00408 return rotate(Affine3f(_rvec).rotation()); 00409 } 00410 00411 template<typename T> inline 00412 cv::Affine3<T> cv::Affine3<T>::translate(const Vec3& t) const 00413 { 00414 Mat4 m = matrix; 00415 m.val[ 3] += t[0]; 00416 m.val[ 7] += t[1]; 00417 m.val[11] += t[2]; 00418 return m; 00419 } 00420 00421 template<typename T> inline 00422 cv::Affine3<T> cv::Affine3<T>::concatenate(const Affine3<T>& affine) const 00423 { 00424 return (*this).rotate(affine.rotation()).translate(affine.translation()); 00425 } 00426 00427 template<typename T> template <typename Y> inline 00428 cv::Affine3<T>::operator Affine3<Y>() const 00429 { 00430 return Affine3<Y>(matrix); 00431 } 00432 00433 template<typename T> template <typename Y> inline 00434 cv::Affine3<Y> cv::Affine3<T>::cast() const 00435 { 00436 return Affine3<Y>(matrix); 00437 } 00438 00439 template<typename T> inline 00440 cv::Affine3<T> cv::operator*(const cv::Affine3<T>& affine1, const cv::Affine3<T>& affine2) 00441 { 00442 return affine2.concatenate(affine1); 00443 } 00444 00445 template<typename T, typename V> inline 00446 V cv::operator*(const cv::Affine3<T>& affine, const V& v) 00447 { 00448 const typename Affine3<T>::Mat4& m = affine.matrix; 00449 00450 V r; 00451 r.x = m.val[0] * v.x + m.val[1] * v.y + m.val[ 2] * v.z + m.val[ 3]; 00452 r.y = m.val[4] * v.x + m.val[5] * v.y + m.val[ 6] * v.z + m.val[ 7]; 00453 r.z = m.val[8] * v.x + m.val[9] * v.y + m.val[10] * v.z + m.val[11]; 00454 return r; 00455 } 00456 00457 static inline 00458 cv::Vec3f cv::operator*(const cv::Affine3f& affine, const cv::Vec3f& v) 00459 { 00460 const cv::Matx44f& m = affine.matrix; 00461 cv::Vec3f r; 00462 r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; 00463 r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; 00464 r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; 00465 return r; 00466 } 00467 00468 static inline 00469 cv::Vec3d cv::operator*(const cv::Affine3d& affine, const cv::Vec3d& v) 00470 { 00471 const cv::Matx44d& m = affine.matrix; 00472 cv::Vec3d r; 00473 r.val[0] = m.val[0] * v[0] + m.val[1] * v[1] + m.val[ 2] * v[2] + m.val[ 3]; 00474 r.val[1] = m.val[4] * v[0] + m.val[5] * v[1] + m.val[ 6] * v[2] + m.val[ 7]; 00475 r.val[2] = m.val[8] * v[0] + m.val[9] * v[1] + m.val[10] * v[2] + m.val[11]; 00476 return r; 00477 } 00478 00479 00480 00481 #if defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H 00482 00483 template<typename T> inline 00484 cv::Affine3<T>::Affine3(const Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>& affine) 00485 { 00486 cv::Mat(4, 4, cv::DataType<T>::type, affine.matrix().data()).copyTo(matrix); 00487 } 00488 00489 template<typename T> inline 00490 cv::Affine3<T>::Affine3(const Eigen::Transform<T, 3, Eigen::Affine>& affine) 00491 { 00492 Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)> a = affine; 00493 cv::Mat(4, 4, cv::DataType<T>::type, a.matrix().data()).copyTo(matrix); 00494 } 00495 00496 template<typename T> inline 00497 cv::Affine3<T>::operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>() const 00498 { 00499 Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)> r; 00500 cv::Mat hdr(4, 4, cv::DataType<T>::type, r.matrix().data()); 00501 cv::Mat(matrix, false).copyTo(hdr); 00502 return r; 00503 } 00504 00505 template<typename T> inline 00506 cv::Affine3<T>::operator Eigen::Transform<T, 3, Eigen::Affine>() const 00507 { 00508 return this->operator Eigen::Transform<T, 3, Eigen::Affine, (Eigen::RowMajor)>(); 00509 } 00510 00511 #endif /* defined EIGEN_WORLD_VERSION && defined EIGEN_GEOMETRY_MODULE_H */ 00512 00513 //! @endcond 00514 00515 #endif /* __cplusplus */ 00516 00517 #endif /* OPENCV_CORE_AFFINE3_HPP */
Generated on Tue Jul 12 2022 18:20:16 by
1.7.2