Я использую OpenCV 4.3.0 и пытаюсь рассчитать позу головы с точки зрения углов Эйлера, используя OpenCV и Dlib API.
Проблема: Когда я переключаюсь на SOLVEPNP_EPNP с SOLVEPNP_ITERATIVE, углы резко меняются. Я что-то здесь упускаю?
Вот мой полный пример кода.
Я что-то упустил? Любые указатели / входные данные по этому поведению были бы действительно хороши.
//Dlib Headers
#include <iostream>
#include <dlib/opencv.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/objdetect.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/plot.hpp"
#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing.h>
#include <time.h>
#include <unistd.h>
#include <opencv2/tracking.hpp>
#include <opencv2/core/ocl.hpp>
using namespace cv;
using namespace std;
using namespace dlib;
int main(int argc, char **argv)
{
cv::Mat im;
VideoCapture cap(0);
dlib::shape_predictor predictor;
dlib::frontal_face_detector detector;
std::vector<dlib::rectangle> faces;
dlib::cv_image<dlib::bgr_pixel> d_frame;
dlib::full_object_detection shape;
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(3, 1, CV_64FC1);
std::vector<Point2f> projected_axes, projected_pts;
std::vector<Point3f> axes;
cv::Mat rotation_mat;
cv::Mat pose_mat;
cv::Mat euler_angle;
dlib::deserialize("./shape_predictor_68_face_landmarks.dat") >> predictor;
detector = dlib::get_frontal_face_detector();
// 3D model points.
std::vector<cv::Point3d> model_points;
model_points.push_back(cv::Point3d(0.0f, 0.0f, 0.0f)); // Nose tip
model_points.push_back(cv::Point3d(0.0f, -330.0f, -65.0f)); // Chin
model_points.push_back(cv::Point3d(-225.0f, 170.0f, -135.0f)); // Left eye left corner
model_points.push_back(cv::Point3d(225.0f, 170.0f, -135.0f)); // Right eye right corner
model_points.push_back(cv::Point3d(-150.0f, -150.0f, -125.0f)); // Left Mouth corner
model_points.push_back(cv::Point3d(150.0f, -150.0f, -125.0f)); // Right mouth corner
while(1) {
cap >> im;
d_frame = im; // OpenCV to dlib conversion
faces = detector(d_frame, 0);
if(!faces.size()) {
cout << "Face not detected..." << endl;
continue;
}
shape = predictor(d_frame, faces[0]);
// 2D image points.
std::vector<cv::Point2d> image_points;
image_points.push_back( cv::Point2d(shape.part(33).x(), shape.part(33).y()) ); // Nose tip
image_points.push_back( cv::Point2d(shape.part(8).x(), shape.part(8).y()) ); // Chin
image_points.push_back( cv::Point2d(shape.part(45).x(), shape.part(45).y()) ); // Left eye left corner
image_points.push_back( cv::Point2d(shape.part(36).x(), shape.part(36).y()) ); // Right eye right corner
image_points.push_back( cv::Point2d(shape.part(54).x(), shape.part(54).y()) ); // Left mouth corner
image_points.push_back( cv::Point2d(shape.part(48).x(), shape.part(48).y()) ); // Right Mouth corner
// Camera internals
double focal_length = im.cols; // Approximate focal length.
Point2d center = cv::Point2d(im.cols/2,im.rows/2);
cv::Mat camera_matrix = (cv::Mat_<double>(3,3) << focal_length, 0, center.x, 0 , focal_length, center.y, 0, 0, 1);
cv::Mat dist_coeffs = cv::Mat::zeros(4,1,cv::DataType<double>::type); // Assuming no lens distortion
// Output rotation and translation
cv::Mat rotation_vector; // Rotation in axis-angle form
cv::Mat translation_vector;
// Solve for pose
//cv::solvePnP(model_points, image_points, camera_matrix, dist_coeffs, rotation_vector, translation_vector, false, cv::SOLVEPNP_ITERATIVE);
cv::solvePnP(model_points, image_points, camera_matrix, dist_coeffs, rotation_vector, translation_vector, false, cv::SOLVEPNP_EPNP);
axes.push_back(Point3d(0, 0, 0));
axes.push_back(Point3d(200, 0, 0));
axes.push_back(Point3d(0, 200, 0));
axes.push_back(Point3d(0, 0, 200));
projectPoints(axes, rotation_vector, translation_vector, camera_matrix, dist_coeffs, projected_axes);
cv::line(im, projected_axes[0], projected_axes[1], Scalar(0,0,255), 2, LINE_AA);
cv::line(im, projected_axes[0], projected_axes[2], Scalar(0,255,0), 2, LINE_AA);
cv::line(im, projected_axes[0], projected_axes[3], Scalar(255,0,0), 2, LINE_AA);
for(int i=0; i < image_points.size(); i++)
{
circle(im, image_points[i], 3, Scalar(0,0,255), -1);
}
cv::Rodrigues(rotation_vector, rotation_mat);
cv::hconcat(rotation_mat, translation_vector, pose_mat);
cv::decomposeProjectionMatrix(pose_mat, out_intrinsics, out_rotation, out_translation, cv::noArray(), cv::noArray(), cv::noArray(), euler_angle);
cout << " Euler Angles = " << euler_angle.at<double>(0) << ", " << euler_angle.at<double>(1) << ", " << euler_angle.at<double>(2) << endl;
// Display image.
cv::imshow("test-oc", im);
if((cv::waitKey(1)) == 27) {
break;
}
}
}
Результат SOLVEPNP_ITERATIVE:
Euler Angles = 6.47259, 5.16644, -2.55706
Euler Angles = 7.50049, -0.980577, -2.5629
Euler Angles = 6.04655, 0.339898, -1.97143
Euler Angles = 8.93439, 1.31261, -2.17082
Euler Angles = 7.89372, -3.46604, -3.12118
Euler Angles = 8.44813, 1.29295, -3.34813
Euler Angles = 6.88552, 0.524957, -3.02001
Euler Angles = 6.30558, -1.64235, -2.58923
Euler Angles = 8.50534, -3.00043, -2.4731
Euler Angles = 9.4099, -2.02561, -2.4283
Euler Angles = 8.16788, -3.64308, -2.61497
Euler Angles = 8.65888, 0.920203, -2.43853
Euler Angles = 8.15495, 1.76792, -3.33953
Euler Angles = 7.61768, -3.51622, -3.28664
Euler Angles = 7.79249, 2.33657, -3.27351
Euler Angles = 6.68948, -2.05756, -3.42978
Euler Angles = 7.30531, -1.31404, -3.60287
Euler Angles = 8.15858, 0.292005, -3.25695
Euler Angles = 7.88462, 0.696455, -3.15758
Euler Angles = 8.00573, 0.425516, -3.58641
Euler Angles = 6.8475, 1.75971, -3.39312
Результат SOLVEPNP_EPNP:
Euler Angles = 14.6544, 26.1875, -178.478
Euler Angles = 17.1788, 27.4086, -176.768
Euler Angles = 18.8691, 23.2976, -177.202
Euler Angles = 16.2182, 26.7816, -177.099
Euler Angles = 16.6824, 24.7938, -177.333
Euler Angles = 17.7303, 24.9154, -176.922
Euler Angles = 7.36889, 26.012, 177.365
Euler Angles = 17.1243, 27.0429, -176.401
Euler Angles = 17.8143, 25.7133, -176.537
Euler Angles = 17.4924, 26.0709, -176.571
Euler Angles = 18.2996, 26.2258, -176.795
Euler Angles = 4.67489, 27.6959, 176.795
Euler Angles = 6.55337, 24.8503, 177.21
Euler Angles = 17.898, 25.2551, -176.566
Euler Angles = 19.6069, 25.1173, -176.056
Euler Angles = 17.8531, 27.1073, -176.783
Euler Angles = 18.6442, 24.573, -176.731
Euler Angles = 16.7624, 26.8984, -176.809
Euler Angles = 18.0749, 26.8476, -176.722
Euler Angles = 17.6393, 25.7551, -176.178
Euler Angles = 16.5079, 26.1617, -177.581
Euler Angles = 17.4239, 27.6137, -176.662
Euler Angles = 17.4765, 25.2052, -176.825
Euler Angles = 17.5855, 23.8312, -176.792
Euler Angles = 16.9895, 28.3646, -176.535