diff --git a/modules/core/include/opencv2/core.hpp b/modules/core/include/opencv2/core.hpp index fe3af39365..a6fa49c7eb 100644 --- a/modules/core/include/opencv2/core.hpp +++ b/modules/core/include/opencv2/core.hpp @@ -2629,7 +2629,7 @@ public: /** @overload initializes an empty SVD structure and then calls SVD::operator() - @param src decomposed matrix. + @param src decomposed matrix. The depth has to be CV_32F or CV_64F. @param flags operation flags (SVD::Flags) */ SVD( InputArray src, int flags = 0 ); @@ -2642,7 +2642,7 @@ public: different matrices. Each time, if needed, the previous u,`vt` , and w are reclaimed and the new matrices are created, which is all handled by Mat::create. - @param src decomposed matrix. + @param src decomposed matrix. The depth has to be CV_32F or CV_64F. @param flags operation flags (SVD::Flags) */ SVD& operator ()( InputArray src, int flags = 0 ); @@ -2658,18 +2658,18 @@ public: SVD::compute(A, w, u, vt); @endcode - @param src decomposed matrix + @param src decomposed matrix. The depth has to be CV_32F or CV_64F. @param w calculated singular values @param u calculated left singular vectors - @param vt transposed matrix of right singular values - @param flags operation flags - see SVD::SVD. + @param vt transposed matrix of right singular vectors + @param flags operation flags - see SVD::Flags. */ static void compute( InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags = 0 ); /** @overload computes singular values of a matrix - @param src decomposed matrix + @param src decomposed matrix. The depth has to be CV_32F or CV_64F. @param w calculated singular values @param flags operation flags - see SVD::Flags. */ diff --git a/modules/core/include/opencv2/core/affine.hpp b/modules/core/include/opencv2/core/affine.hpp index 443097a52c..66853a7163 100644 --- a/modules/core/include/opencv2/core/affine.hpp +++ b/modules/core/include/opencv2/core/affine.hpp @@ -55,7 +55,72 @@ namespace cv //! @{ /** @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 class Affine3 @@ -66,45 +131,127 @@ namespace cv typedef Matx Mat4; typedef Vec Vec3; + //! Default constructor. It represents a 4x4 identity matrix. Affine3(); //! Augmented affine matrix 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)); - //! 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)); - //! 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)); - //! From 16th element array + //! From 16-element array explicit Affine3(const float_type* vals); - //! Create identity transform + //! Create an 4x4 identity transform 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); - //! 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); - //! 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); + /** + * 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); + + /** + * 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); + //! @return the upper left 3x3 part Mat3 rotation() const; + + //! @return the upper left 3x3 part Mat3 linear() const; + + //! @return the upper right 3x1 part 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; + //! @return the inverse of the current matrix. Affine3 inv(int method = cv::DECOMP_SVD) const; //! 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; 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; //! a.concatenate(affine) is equivalent to affine * a; @@ -136,6 +283,7 @@ namespace cv template static Affine3 operator*(const Affine3& affine1, const Affine3& affine2); + //! V is a 3-element vector with member fields x, y and z template static V operator*(const Affine3& affine, const V& vector); @@ -178,7 +326,7 @@ namespace cv //! @cond IGNORED /////////////////////////////////////////////////////////////////////////////////// -// Implementaiton +// Implementation template inline cv::Affine3::Affine3() @@ -212,6 +360,7 @@ template inline cv::Affine3::Affine3(const cv::Mat& data, const Vec3& t) { CV_Assert(data.type() == cv::traits::Type::value); + CV_Assert(data.channels() == 1); if (data.cols == 4 && data.rows == 4) { @@ -276,11 +425,12 @@ void cv::Affine3::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 inline void cv::Affine3::rotation(const cv::Mat& data) { CV_Assert(data.type() == cv::traits::Type::value); + CV_Assert(data.channels() == 1); if (data.cols == 3 && data.rows == 3) { @@ -295,7 +445,7 @@ void cv::Affine3::rotation(const cv::Mat& data) rotation(_rvec); } else - CV_Assert(!"Input marix can be 3x3, 1x3 or 3x1"); + CV_Assert(!"Input matrix can only be 3x3, 1x3 or 3x1"); } template inline diff --git a/modules/core/include/opencv2/core/matx.hpp b/modules/core/include/opencv2/core/matx.hpp index 1d1ab4a43c..048bf3b2c4 100644 --- a/modules/core/include/opencv2/core/matx.hpp +++ b/modules/core/include/opencv2/core/matx.hpp @@ -92,7 +92,7 @@ Except of the plain constructor which takes a list of elements, Matx can be init float values[] = { 1, 2, 3}; Matx31f m(values); @endcode -In case if C++11 features are avaliable, std::initializer_list can be also used to initizlize Matx: +In case if C++11 features are avaliable, std::initializer_list can be also used to initialize Matx: @code{.cpp} Matx31f m = { 1, 2, 3}; @endcode