#include #include #include #include "svp_opencv.h" // 预定义的68个3D模型点 (需补全剩余点) const std::vector model_points_68 = { {-73.393523f, -29.801432f, -47.667532f}, {-72.775014f, -10.949766f, -45.909403f}, {-70.533638f, 7.929818f, -44.84258f}, {-66.850058f, 26.07428f, -43.141114f}, {-59.790187f, 42.56439f, -38.635298f}, {-48.368973f, 56.48108f, -30.750622f}, {-34.121101f, 67.246992f, -18.456453f}, {-17.875411f, 75.056892f, -3.609035f}, {0.098749f, 77.061286f, 0.881698f}, {17.477031f, 74.758448f, -5.181201f}, {32.648966f, 66.929021f, -19.176563f}, {46.372358f, 56.311389f, -30.77057f}, {57.34348f, 42.419126f, -37.628629f}, {64.388482f, 25.45588f, -40.886309f}, {68.212038f, 6.990805f, -42.281449f}, {70.486405f, -11.666193f, -44.142567f}, {71.375822f, -30.365191f, -47.140426f}, {-61.119406f, -49.361602f, -14.254422f}, {-51.287588f, -58.769795f, -7.268147f}, {-37.8048f, -61.996155f, -0.442051f}, {-24.022754f, -61.033399f, 6.606501f}, {-11.635713f, -56.686759f, 11.967398f}, {12.056636f, -57.391033f, 12.051204f}, {25.106256f, -61.902186f, 7.315098f}, {38.338588f, -62.777713f, 1.022953f}, {51.191007f, -59.302347f, -5.349435f}, {60.053851f, -50.190255f, -11.615746f}, {0.65394f, -42.19379f, 13.380835f}, {0.804809f, -30.993721f, 21.150853f}, {0.992204f, -19.944596f, 29.284036f}, {1.226783f, -8.414541f, 36.94806f}, {-14.772472f, 2.598255f, 20.132003f}, {-7.180239f, 4.751589f, 23.536684f}, {0.55592f, 6.5629f, 25.944448f}, {8.272499f, 4.661005f, 23.695741f}, {15.214351f, 2.643046f, 20.858157f}, {-46.04729f, -37.471411f, -7.037989f}, {-37.674688f, -42.73051f, -3.021217f}, {-27.883856f, -42.711517f, -1.353629f}, {-19.648268f, -36.754742f, 0.111088f}, {-28.272965f, -35.134493f, 0.147273f}, {-38.082418f, -34.919043f, -1.476612f}, {19.265868f, -37.032306f, 0.665746f}, {27.894191f, -43.342445f, -0.24766f}, {37.437529f, -43.110822f, -1.696435f}, {45.170805f, -38.086515f, -4.894163f}, {38.196454f, -35.532024f, -0.282961f}, {28.764989f, -35.484289f, 1.172675f}, {-28.916267f, 28.612716f, 2.24031f}, {-17.533194f, 22.172187f, 15.934335f}, {-6.68459f, 19.029051f, 22.611355f}, {0.381001f, 20.721118f, 23.748437f}, {8.375443f, 19.03546f, 22.721995f}, {18.876618f, 22.394109f, 15.610679f}, {28.794412f, 28.079924f, 3.217393f}, {19.057574f, 36.298248f, 14.987997f}, {8.956375f, 39.634575f, 22.554245f}, {0.381549f, 40.395647f, 23.591626f}, {-7.428895f, 39.836405f, 22.406106f}, {-18.160634f, 36.677899f, 15.121907f}, {-24.37749f, 28.677771f, 4.785684f}, {-6.897633f, 25.475976f, 20.893742f}, {0.340663f, 26.014269f, 22.220479f}, {8.444722f, 25.326198f, 21.02552f}, {24.474473f, 28.323008f, 5.712776f}, {8.449166f, 30.596216f, 20.671489f}, {0.205322f, 31.408738f, 21.90367f}, {-7.198266f, 30.844876f, 20.328022f} }; xmedia_s32 svp_opencv_face_orientation(const xmedia_svp_keypoint *landmarks, svp_euler_angles *angles) { if (landmarks == XMEDIA_NULL || angles == XMEDIA_NULL) { printf("svp_opencv_face_orientation param is NULL!\n"); return XMEDIA_FAILURE; } // 转换关键点到图像坐标 std::vector image_points; for (xmedia_u8 i = 0; i < MAX_DETECT_KEYPOINT_NUM; i++) { image_points.emplace_back(landmarks[i].x, landmarks[i].y); } // 相机内参矩阵 xmedia_double center_x = 640 / 2; xmedia_double center_y = 360 / 2; xmedia_double focal_length = center_x / tan(30 * CV_PI / 180); cv::Mat camera_matrix = (cv::Mat_(3,3) << focal_length, 0, center_x, 0, focal_length, center_y, 0, 0, 1); // 畸变系数, 后续需要根据不同sensor设置? cv::Mat dist_coeffs = cv::Mat::zeros(4, 1, CV_64F); // 初始化猜测 cv::Mat r_vec = (cv::Mat_(3,1) << 0.01891013, 0.08560084, -3.14392813); cv::Mat t_vec = (cv::Mat_(3,1) << -14.97821226, -10.62040383, -2053.03596872); bool success = cv::solvePnP( model_points_68, image_points, camera_matrix, dist_coeffs, r_vec, t_vec, true, // 使用外部猜测 cv::SOLVEPNP_ITERATIVE ); if (!success) { printf("solvePnP error\n"); return XMEDIA_FAILURE; } // 转换旋转向量为矩阵 cv::Mat rvec_matrix; cv::Rodrigues(r_vec, rvec_matrix); // 构建投影矩阵 cv::Mat proj_matrix(3, 4, CV_64F); cv::hconcat(rvec_matrix, t_vec, proj_matrix); // 分解投影矩阵求欧拉角, 实现旋转矩阵到欧拉角的转换 xmedia_double sy = std::sqrt(rvec_matrix.at(0,0) * rvec_matrix.at(0,0) + rvec_matrix.at(1,0) * rvec_matrix.at(1,0)); xmedia_double x, y, z; if (!(sy < 1e-6)) { x = std::atan2(rvec_matrix.at(2,1), rvec_matrix.at(2,2)); y = std::atan2(-rvec_matrix.at(2,0), sy); z = std::atan2(rvec_matrix.at(1,0), rvec_matrix.at(0,0)); } else { x = std::atan2(-rvec_matrix.at(1,2), rvec_matrix.at(1,1)); y = std::atan2(-rvec_matrix.at(2,0), sy); z = 0; } // 原始弧度转角度 x = x * 180 / CV_PI; y = y * 180 / CV_PI; z = z * 180 / CV_PI; // 角度范围修正 angles->pitch = std::asin(std::sin(x * CV_PI / 180)) * 180 / CV_PI; angles->roll = -std::asin(std::sin(z * CV_PI / 180)) * 180 / CV_PI; angles->yaw = std::asin(std::sin(y * CV_PI / 180)) * 180 / CV_PI; // 确保角度在-90到90度范围内 angles->pitch = std::max(std::min(angles->pitch, 90.0), -90.0); angles->roll = std::max(std::min(angles->roll, 90.0), -90.0); angles->yaw = std::max(std::min(angles->yaw, 90.0), -90.0); return XMEDIA_SUCCESS; }