C# 人脸姿态估计(HeadPoseEstimation)

##  先上结果

 

 

 红色的是用网上普遍的方法,参照是以旷视人脸检测的api。用六个关键点来评估误差太大,没啥用。

 

##  环境:

说是C# 写的,实际都是调用opencv跟dlib的封装包。

 

## code:

主要代码opencv的Cv2.SolvePnP

输入为六个人脸关键点,图像宽和高,获取关键点还是最下面项目github看吧。

        public Angles GetAnglesAndPoints(Mat<Point2d> points, int width, int height)
        {
            var cameraMatrix = new Mat<double>(3, 3,
               new double[] {
                    width, 0,     width / 2,
                    0,     width, height / 2,
                    0,     0,     1
               });

            var dist = new Mat<double> { 0, 0, 0, 0, 0 };
            var rvec = new Mat<double>();
            var tvec = new Mat();
            var Model_points = new Mat<Point3f>
             {
                        new Point3f(0.0f, 0.0f, 0.0f),             // Nose tip
                        new Point3f(0.0f, -330.0f, -65.0f),        // Chin
                        new Point3f(-225.0f, 170.0f, -135.0f),     // Left eye left corner
                        new Point3f(225.0f, 170.0f, -135.0f),      // Right eye right corne
                        new Point3f(-150.0f, -150.0f, -125.0f),    // Left Mouth corner
                        new Point3f(150.0f, -150.0f, -125.0f)      // Right mouth corner
             };
            Cv2.SolvePnP(Model_points, points, cameraMatrix, dist, rvec, tvec, flags: SolvePnPFlags.Iterative);

            return GetEulerAngle(rvec);
        }

 

 

旋转向量转化为欧拉角

       
        public Angles GetEulerAngle(Mat<double> rotation_vector)
        {
            var rotArray = rotation_vector.ToArray();

            Mat mat = new Mat(3, 1, MatType.CV_64FC1, rotArray);
            var theta = Cv2.Norm(mat, NormTypes.L2);
            var w = Math.Cos(theta / 2);
            var x = Math.Sin(theta / 2) * rotArray[0] / theta;
            var y = Math.Sin(theta / 2) * rotArray[1] / theta;
            var z = Math.Sin(theta / 2) * rotArray[2] / theta;

            var ysqr = y * y;

            // pitch (x-axis rotation)
            var t0 = 2.0 * (w * x + y * z);
            var t1 = 1.0 - 2.0 * (x * x + ysqr);
            var pitch = Math.Atan2(t0, t1);//反正切(给坐标轴,x,y)

            // yaw (y-axis rotation)
            var t2 = 2.0 * (w * y - z * x);
            if (t2 > 1.0) t2 = 1.0;
            if (t2 < -1.0) t2 = -1.0;
            var yaw = Math.Asin(t2); //反正弦函数

            // roll (z-axis rotation)
            var t3 = 2.0 * (w * z + x * y);
            var t4 = 1.0 - 2.0 * (ysqr + z * z);
            var roll = Math.Atan2(t3, t4);

            // 单位转换:将弧度转换为度
            var Y = (pitch / Math.PI) * 180;
            Y = Math.Sign(Y) * 180 - Y;

            var X = (yaw / Math.PI) * 180;
            var Z = (roll / Math.PI) * 180;
            Angles angles = new Angles() { Pitch = Y, Roll = Z, Yaw = X };
            return angles;
        }

 

Angles就三个属性
    public class Angles
    {
        public double Roll { get; set; }
        public double Pitch { get; set; }
        public double Yaw { get; set; }
    } 

 

效果图:(图源网络,侵删)

 

 

 

 

 

 

 

 

 

 

##  引用:

 

C++实现       https://blog.csdn.net/u013512448/article/details/77804161

python实现   https://blog.csdn.net/loveliuzz/article/details/102716290

 

旷视api调用  https://www.faceplusplus.com.cn/face-detection/

 

人脸识别    https://github.com/takuya-takeuchi/FaceRecognitionDotNet

 

C# 实现        https://github.com/TrojanOlx/AI

           https://github.com/cheat13/FaceDetect

           https://github.com/Zhaofan-Su/FaceRig-Scripts(这个项目太旧,可以运行,但升级最新的opencv没成功)

 

 结尾:

网上基于6个关键点评估方法并不靠谱,误差太大,完全没有实用价值。

文章代码:https://github.com/zlyxm/HeadPoseSharp

FaceRecognitionDotNet 最新版(1.3.0.2)已经支持关键点评估,比6个关键点强不知道多少,不过模型要自己训练就是,试下看。渣渣电脑训练了1天15个钟才45.43%....

 

 

posted @ 2020-08-22 10:50  zlyxm  阅读(1155)  评论(0编辑  收藏  举报