|
|
@ -55,7 +55,72 @@ namespace cv |
|
|
|
//! @{
|
|
|
|
//! @{
|
|
|
|
|
|
|
|
|
|
|
|
/** @brief Affine transform
|
|
|
|
/** @brief Affine transform
|
|
|
|
@todo document |
|
|
|
* |
|
|
|
|
|
|
|
* It represents a 4x4 homogeneous transformation matrix \f$T\f$ |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* \f[T = |
|
|
|
|
|
|
|
* \begin{bmatrix} |
|
|
|
|
|
|
|
* R & t\\
|
|
|
|
|
|
|
|
* 0 & 1\\
|
|
|
|
|
|
|
|
* \end{bmatrix} |
|
|
|
|
|
|
|
* \f] |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* where \f$R\f$ is a 3x3 rotation matrix and \f$t\f$ is a 3x1 translation vector. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* You can specify \f$R\f$ either by a 3x3 rotation matrix or by a 3x1 rotation vector, |
|
|
|
|
|
|
|
* which is converted to a 3x3 rotation matrix by the Rodrigues formula. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* To construct a matrix \f$T\f$ representing first rotation around the axis \f$r\f$ with rotation |
|
|
|
|
|
|
|
* angle \f$|r|\f$ in radian (right hand rule) and then translation by the vector \f$t\f$, you can use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Vec3f r, t; |
|
|
|
|
|
|
|
* cv::Affine3f T(r, t); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If you already have the rotation matrix \f$R\f$, then you can use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Matx33f R; |
|
|
|
|
|
|
|
* cv::Affine3f T(R, t); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* To extract the rotation matrix \f$R\f$ from \f$T\f$, use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Matx33f R = T.rotation(); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* To extract the translation vector \f$t\f$ from \f$T\f$, use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Vec3f t = T.translation(); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* To extract the rotation vector \f$r\f$ from \f$T\f$, use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Vec3f r = T.rvec(); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Note that since the mapping from rotation vectors to rotation matrices |
|
|
|
|
|
|
|
* is many to one. The returned rotation vector is not necessarily the one |
|
|
|
|
|
|
|
* you used before to set the matrix. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If you have two transformations \f$T = T_1 * T_2\f$, use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Affine3f T, T1, T2; |
|
|
|
|
|
|
|
* T = T2.concatenate(T1); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* To get the inverse transform of \f$T\f$, use |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @code |
|
|
|
|
|
|
|
* cv::Affine3f T, T_inv; |
|
|
|
|
|
|
|
* T_inv = T.inv(); |
|
|
|
|
|
|
|
* @endcode |
|
|
|
|
|
|
|
* |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
template<typename T> |
|
|
|
template<typename T> |
|
|
|
class Affine3 |
|
|
|
class Affine3 |
|
|
@ -66,45 +131,127 @@ namespace cv |
|
|
|
typedef Matx<float_type, 4, 4> Mat4; |
|
|
|
typedef Matx<float_type, 4, 4> Mat4; |
|
|
|
typedef Vec<float_type, 3> Vec3; |
|
|
|
typedef Vec<float_type, 3> Vec3; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Default constructor. It represents a 4x4 identity matrix.
|
|
|
|
Affine3(); |
|
|
|
Affine3(); |
|
|
|
|
|
|
|
|
|
|
|
//! Augmented affine matrix
|
|
|
|
//! Augmented affine matrix
|
|
|
|
Affine3(const Mat4& affine); |
|
|
|
Affine3(const Mat4& affine); |
|
|
|
|
|
|
|
|
|
|
|
//! Rotation matrix
|
|
|
|
/**
|
|
|
|
|
|
|
|
* The resulting 4x4 matrix is |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* \f[ |
|
|
|
|
|
|
|
* \begin{bmatrix} |
|
|
|
|
|
|
|
* R & t\\
|
|
|
|
|
|
|
|
* 0 & 1\\
|
|
|
|
|
|
|
|
* \end{bmatrix} |
|
|
|
|
|
|
|
* \f] |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param R 3x3 rotation matrix. |
|
|
|
|
|
|
|
* @param t 3x1 translation vector. |
|
|
|
|
|
|
|
*/ |
|
|
|
Affine3(const Mat3& R, const Vec3& t = Vec3::all(0)); |
|
|
|
Affine3(const Mat3& R, const Vec3& t = Vec3::all(0)); |
|
|
|
|
|
|
|
|
|
|
|
//! Rodrigues vector
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Rodrigues vector. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The last row of the current matrix is set to [0,0,0,1]. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param rvec 3x1 rotation vector. Its direction indicates the rotation axis and its length |
|
|
|
|
|
|
|
* indicates the rotation angle in radian (using right hand rule). |
|
|
|
|
|
|
|
* @param t 3x1 translation vector. |
|
|
|
|
|
|
|
*/ |
|
|
|
Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); |
|
|
|
Affine3(const Vec3& rvec, const Vec3& t = Vec3::all(0)); |
|
|
|
|
|
|
|
|
|
|
|
//! Combines all contructors above. Supports 4x4, 4x3, 3x3, 1x3, 3x1 sizes of data matrix
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Combines all constructors above. Supports 4x4, 3x4, 3x3, 1x3, 3x1 sizes of data matrix. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* The last row of the current matrix is set to [0,0,0,1] when data is not 4x4. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param data 1-channel matrix. |
|
|
|
|
|
|
|
* when it is 4x4, it is copied to the current matrix and t is not used. |
|
|
|
|
|
|
|
* When it is 3x4, it is copied to the upper part 3x4 of the current matrix and t is not used. |
|
|
|
|
|
|
|
* When it is 3x3, it is copied to the upper left 3x3 part of the current matrix. |
|
|
|
|
|
|
|
* When it is 3x1 or 1x3, it is treated as a rotation vector and the Rodrigues formula is used |
|
|
|
|
|
|
|
* to compute a 3x3 rotation matrix. |
|
|
|
|
|
|
|
* @param t 3x1 translation vector. It is used only when data is neither 4x4 nor 3x4. |
|
|
|
|
|
|
|
*/ |
|
|
|
explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); |
|
|
|
explicit Affine3(const Mat& data, const Vec3& t = Vec3::all(0)); |
|
|
|
|
|
|
|
|
|
|
|
//! From 16th element array
|
|
|
|
//! From 16-element array
|
|
|
|
explicit Affine3(const float_type* vals); |
|
|
|
explicit Affine3(const float_type* vals); |
|
|
|
|
|
|
|
|
|
|
|
//! Create identity transform
|
|
|
|
//! Create an 4x4 identity transform
|
|
|
|
static Affine3 Identity(); |
|
|
|
static Affine3 Identity(); |
|
|
|
|
|
|
|
|
|
|
|
//! Rotation matrix
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Rotation matrix. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Copy the rotation matrix to the upper left 3x3 part of the current matrix. |
|
|
|
|
|
|
|
* The remaining elements of the current matrix are not changed. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param R 3x3 rotation matrix. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
*/ |
|
|
|
void rotation(const Mat3& R); |
|
|
|
void rotation(const Mat3& R); |
|
|
|
|
|
|
|
|
|
|
|
//! Rodrigues vector
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Rodrigues vector. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* It sets the upper left 3x3 part of the matrix. The remaining part is unaffected. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param rvec 3x1 rotation vector. The direction indicates the rotation axis and |
|
|
|
|
|
|
|
* its length indicates the rotation angle in radian (using the right thumb convention). |
|
|
|
|
|
|
|
*/ |
|
|
|
void rotation(const Vec3& rvec); |
|
|
|
void rotation(const Vec3& rvec); |
|
|
|
|
|
|
|
|
|
|
|
//! Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix;
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Combines rotation methods above. Supports 3x3, 1x3, 3x1 sizes of data matrix. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* It sets the upper left 3x3 part of the matrix. The remaining part is unaffected. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param data 1-channel matrix. |
|
|
|
|
|
|
|
* When it is a 3x3 matrix, it sets the upper left 3x3 part of the current matrix. |
|
|
|
|
|
|
|
* When it is a 1x3 or 3x1 matrix, it is used as a rotation vector. The Rodrigues formula |
|
|
|
|
|
|
|
* is used to compute the rotation matrix and sets the upper left 3x3 part of the current matrix. |
|
|
|
|
|
|
|
*/ |
|
|
|
void rotation(const Mat& data); |
|
|
|
void rotation(const Mat& data); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Copy the 3x3 matrix L to the upper left part of the current matrix |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* It sets the upper left 3x3 part of the matrix. The remaining part is unaffected. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param L 3x3 matrix. |
|
|
|
|
|
|
|
*/ |
|
|
|
void linear(const Mat3& L); |
|
|
|
void linear(const Mat3& L); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Copy t to the first three elements of the last column of the current matrix |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* It sets the upper right 3x1 part of the matrix. The remaining part is unaffected. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param t 3x1 translation vector. |
|
|
|
|
|
|
|
*/ |
|
|
|
void translation(const Vec3& t); |
|
|
|
void translation(const Vec3& t); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @return the upper left 3x3 part
|
|
|
|
Mat3 rotation() const; |
|
|
|
Mat3 rotation() const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @return the upper left 3x3 part
|
|
|
|
Mat3 linear() const; |
|
|
|
Mat3 linear() const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @return the upper right 3x1 part
|
|
|
|
Vec3 translation() const; |
|
|
|
Vec3 translation() const; |
|
|
|
|
|
|
|
|
|
|
|
//! Rodrigues vector
|
|
|
|
//! Rodrigues vector.
|
|
|
|
|
|
|
|
//! @return a vector representing the upper left 3x3 rotation matrix of the current matrix.
|
|
|
|
|
|
|
|
//! @warning Since the mapping between rotation vectors and rotation matrices is many to one,
|
|
|
|
|
|
|
|
//! this function returns only one rotation vector that represents the current rotation matrix,
|
|
|
|
|
|
|
|
//! which is not necessarily the same one set by `rotation(const Vec3& rvec)`.
|
|
|
|
Vec3 rvec() const; |
|
|
|
Vec3 rvec() const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! @return the inverse of the current matrix.
|
|
|
|
Affine3 inv(int method = cv::DECOMP_SVD) const; |
|
|
|
Affine3 inv(int method = cv::DECOMP_SVD) const; |
|
|
|
|
|
|
|
|
|
|
|
//! a.rotate(R) is equivalent to Affine(R, 0) * a;
|
|
|
|
//! a.rotate(R) is equivalent to Affine(R, 0) * a;
|
|
|
@ -113,7 +260,7 @@ namespace cv |
|
|
|
//! a.rotate(rvec) is equivalent to Affine(rvec, 0) * a;
|
|
|
|
//! a.rotate(rvec) is equivalent to Affine(rvec, 0) * a;
|
|
|
|
Affine3 rotate(const Vec3& rvec) const; |
|
|
|
Affine3 rotate(const Vec3& rvec) const; |
|
|
|
|
|
|
|
|
|
|
|
//! a.translate(t) is equivalent to Affine(E, t) * a;
|
|
|
|
//! a.translate(t) is equivalent to Affine(E, t) * a, where E is an identity matrix
|
|
|
|
Affine3 translate(const Vec3& t) const; |
|
|
|
Affine3 translate(const Vec3& t) const; |
|
|
|
|
|
|
|
|
|
|
|
//! a.concatenate(affine) is equivalent to affine * a;
|
|
|
|
//! a.concatenate(affine) is equivalent to affine * a;
|
|
|
@ -136,6 +283,7 @@ namespace cv |
|
|
|
template<typename T> static |
|
|
|
template<typename T> static |
|
|
|
Affine3<T> operator*(const Affine3<T>& affine1, const Affine3<T>& affine2); |
|
|
|
Affine3<T> operator*(const Affine3<T>& affine1, const Affine3<T>& affine2); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! V is a 3-element vector with member fields x, y and z
|
|
|
|
template<typename T, typename V> static |
|
|
|
template<typename T, typename V> static |
|
|
|
V operator*(const Affine3<T>& affine, const V& vector); |
|
|
|
V operator*(const Affine3<T>& affine, const V& vector); |
|
|
|
|
|
|
|
|
|
|
@ -178,7 +326,7 @@ namespace cv |
|
|
|
//! @cond IGNORED
|
|
|
|
//! @cond IGNORED
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Implementaiton
|
|
|
|
// Implementation
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T> inline |
|
|
|
template<typename T> inline |
|
|
|
cv::Affine3<T>::Affine3() |
|
|
|
cv::Affine3<T>::Affine3() |
|
|
@ -212,6 +360,7 @@ template<typename T> inline |
|
|
|
cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t) |
|
|
|
cv::Affine3<T>::Affine3(const cv::Mat& data, const Vec3& t) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Assert(data.type() == cv::traits::Type<T>::value); |
|
|
|
CV_Assert(data.type() == cv::traits::Type<T>::value); |
|
|
|
|
|
|
|
CV_Assert(data.channels() == 1); |
|
|
|
|
|
|
|
|
|
|
|
if (data.cols == 4 && data.rows == 4) |
|
|
|
if (data.cols == 4 && data.rows == 4) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -276,11 +425,12 @@ void cv::Affine3<T>::rotation(const Vec3& _rvec) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Combines rotation methods above. Suports 3x3, 1x3, 3x1 sizes of data matrix;
|
|
|
|
//Combines rotation methods above. Supports 3x3, 1x3, 3x1 sizes of data matrix;
|
|
|
|
template<typename T> inline |
|
|
|
template<typename T> inline |
|
|
|
void cv::Affine3<T>::rotation(const cv::Mat& data) |
|
|
|
void cv::Affine3<T>::rotation(const cv::Mat& data) |
|
|
|
{ |
|
|
|
{ |
|
|
|
CV_Assert(data.type() == cv::traits::Type<T>::value); |
|
|
|
CV_Assert(data.type() == cv::traits::Type<T>::value); |
|
|
|
|
|
|
|
CV_Assert(data.channels() == 1); |
|
|
|
|
|
|
|
|
|
|
|
if (data.cols == 3 && data.rows == 3) |
|
|
|
if (data.cols == 3 && data.rows == 3) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -295,7 +445,7 @@ void cv::Affine3<T>::rotation(const cv::Mat& data) |
|
|
|
rotation(_rvec); |
|
|
|
rotation(_rvec); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); |
|
|
|
CV_Assert(!"Input matrix can only be 3x3, 1x3 or 3x1"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
template<typename T> inline |
|
|
|
template<typename T> inline |
|
|
|