## 先上結果

紅色的是用網上普遍的方法,參照是以曠視人臉檢測的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%....

