Added Affine3<T>::rvec()
authorAnatoly Baksheev <no@email>
Thu, 21 Nov 2013 17:20:20 +0000 (21:20 +0400)
committerAnatoly Baksheev <no@email>
Sat, 7 Dec 2013 14:50:45 +0000 (18:50 +0400)
modules/core/include/opencv2/core/affine.hpp

index cadc7ee..fa7eed8 100644 (file)
@@ -97,6 +97,9 @@ namespace cv
         Mat3 linear() const;
         Vec3 translation() const;
 
+        //Rodrigues vector
+        Vec3 rvec() const;
+
         Affine3 inv(int method = cv::DECOMP_SVD) const;
 
         // a.rotate(R) is equivalent to Affine(R, 0) * a;
@@ -301,6 +304,55 @@ typename cv::Affine3<T>::Vec3 cv::Affine3<T>::translation() const
 }
 
 template<typename T> inline
+typename cv::Affine3<T>::Vec3 cv::Affine3<T>::rvec() const
+{
+    cv::Vec3d w;
+    cv::Matx33d u, vt, R = rotation();
+    cv::SVD::compute(R, w, u, vt, cv::SVD::FULL_UV + cv::SVD::MODIFY_A);
+    R = u * vt;
+
+    double rx = R.val[7] - R.val[5];
+    double ry = R.val[2] - R.val[6];
+    double rz = R.val[3] - R.val[1];
+
+    double s = std::sqrt((rx*rx + ry*ry + rz*rz)*0.25);
+    double c = (R.val[0] + R.val[4] + R.val[8] - 1) * 0.5;
+    c = c > 1.0 ? 1.0 : c < -1.0 ? -1.0 : c;
+    double theta = acos(c);
+
+    if( s < 1e-5 )
+    {
+        if( c > 0 )
+            rx = ry = rz = 0;
+        else
+        {
+            double t;
+            t = (R.val[0] + 1) * 0.5;
+            rx = std::sqrt(std::max(t, 0.0));
+            t = (R.val[4] + 1) * 0.5;
+            ry = std::sqrt(std::max(t, 0.0)) * (R.val[1] < 0 ? -1.0 : 1.0);
+            t = (R.val[8] + 1) * 0.5;
+            rz = std::sqrt(std::max(t, 0.0)) * (R.val[2] < 0 ? -1.0 : 1.0);
+
+            if( fabs(rx) < fabs(ry) && fabs(rx) < fabs(rz) && (R.val[5] > 0) != (ry*rz > 0) )
+                rz = -rz;
+            theta /= std::sqrt(rx*rx + ry*ry + rz*rz);
+            rx *= theta;
+            ry *= theta;
+            rz *= theta;
+        }
+    }
+    else
+    {
+        double vth = 1/(2*s);
+        vth *= theta;
+        rx *= vth; ry *= vth; rz *= vth;
+    }
+
+    return cv::Vec3d(rx, ry, rz);
+}
+
+template<typename T> inline
 cv::Affine3<T> cv::Affine3<T>::inv(int method) const
 {
     return matrix.inv(method);