OpenCV: разница в углах Эйлера между SOLVEPNP_ITERATIVE и SOLVEPNP_EPNP - PullRequest
0 голосов
/ 24 апреля 2020

Я использую 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
...