算法一:直接法
bool isRotationMatrix(cv::Mat &R)
{
cv::Mat R_t;
cv::transpose(R,R_t);
cv::Mat shouldBeIdentity=R_t*R;
cv::Mat I = cv::Mat::eye(3,3,shouldBeIdentity.type());
return norm(I,shouldBeIdentity)< 1e-6;
}
void getEulerAngles(cv::Mat matrix)
{
assert(isRotationMatrix(matrix));
float sy=sqrt(matrix.at(0,0)*matrix.at(0,0)+matrix.at(1,0)*matrix.at(1,0));
bool singular = sy<1e-6;
if(!singular)
{
theta_x=atan2(matrix.at(2,1),matrix.at(2,2));
//theta_x= theta_x*180.0/3.1416 ;
theta_y=atan2(-matrix.at(2,0), sy);
//theta_y= theta_y*180.0/3.1416 ;
theta_z=atan2(matrix.at(1,0), matrix.at(0,0));
//theta_z= theta_z*180.0/3.1416 ;
}
else
{
theta_x=atan2(-matrix.at(1,2), matrix.at(1,1));
//theta_x= theta_x*180.0/3.1416 ;
theta_y=atan2(-matrix.at(2,0), sy);
//theta_y= theta_y*180.0/3.1416 ;
theta_z=0;
//theta_z= theta_z*180.0/3.1416 ;
}
Debug("theta_x");
Debug(theta_x);
Debug("theta_y");
Debug(theta_y);
Debug("theta_z");
Debug(theta_z);
}
NOTE:需要判断奇异性(singularity)!
算法二:拆分法
void getEulerAngles(cv::Mat &R,cv::Mat &t,cv::Mat &euler_angles)
{
cv::Mat camMatrix,rotMatrix,transVect,theta_x,theta_y,theta_z;
cv::Mat rotation_vec;
cv::Mat projMatrix = cv::Mat(3,4,CV_64FC1);
//cv::Mat euler_angles = cv::Mat(3,1,CV_64FC1);
cv::Mat out_intrinsics = cv::Mat(3,3,CV_64FC1);
cv::Mat out_rotation = cv::Mat(3,3,CV_64FC1);
cv::Mat out_translation = cv::Mat(4,1,CV_64FC1);
cv::hconcat(R,t,projMatrix);//将R、t拼接维投影矩阵
cv::decomposeProjectionMatrix(projMatrix,out_intrinsics,out_rotation,out_translation,
cv::noArray(),cv::noArray(),cv::noArray(),euler_angles);
//将投影矩阵分解为旋转矩阵和相机(内参)矩阵
Debug("Euler Angle");
Debug(euler_angles);
}
无需判断奇异性,直接调用库函数,相对简单