文章目录
- 前言
- 一、实现步骤
- 1. 获取所需特征点的索引
- 2. 使用opencv.js 计算俯仰角、水平角和翻滚角
- cv.solvePnP介绍
- cv.solvePnP原理
- 运行代码查看效果
- 3.绘制姿态示意直线
- 添加canvas元素
- 计算姿态直线坐标并绘制
- 总结
前言
在计算机视觉领域,估算脸部姿态是一项具有挑战性但又极具应用前景的任务。通过识别脸部特征点,我们可以了解人脸的姿态,包括旋转角度、倾斜程度等信息。本文将介绍如何利用 TensorFlow.js 和 OpenCV.js 结合起来,实现通过面部特征点估算脸部姿态并绘制示意图的功能。
一、实现步骤
本文将基于文章如何使用tensorflow.js实现面部特征点检测中实现的人脸特征点检测继续根据人脸特征点实现人脸姿态的估计和绘制。
1. 获取所需特征点的索引
我们可以从示例项目看到注释的主要特征点索引如下:
2. 使用opencv.js 计算俯仰角、水平角和翻滚角
我们可以从示例项目看到计算的相关代码如下:
var modelPoints = window.cv.matFromArray(6, 3, window.cv.CV_32F, [
0.0,
0.0,
0.0, // Nose tip
0.0,
-330.0,
-65.0, // Chin
-225.0,
170.0,
-135.0, // Left eye left corner
225.0,
170.0,
-135.0, // Right eye right corne
-150.0,
-150.0,
-125.0, // Left Mouth corner
150.0,
-150.0,
-125.0, // Right mouth corner
]);
var imagePoints = window.cv.matFromArray(6, 2, window.cv.CV_32F, [
keyPoints[4].x,
keyPoints[4].y, // Nose tip
keyPoints[152].x,
keyPoints[152].y, // Chin
keyPoints[263].x,
keyPoints[263].y, // Left eye left corner
keyPoints[33].x,
keyPoints[33].y, // Right eye right corne
keyPoints[308].x,
keyPoints[308].y, // Left Mouth corner
keyPoints[78].x,
keyPoints[78].y, // Right mouth corner
]);
var focal_length = inputResolution.width;
var center = [inputResolution.width / 2, inputResolution.height / 2];
var cameraMatrix = window.cv.matFromArray(3, 3, window.cv.CV_64F, [
focal_length,
0,
center[0],
0,
focal_length,
center[1],
0,
0,
1,
]);
// console.log("Camera Matrix", cameraMatrix.data64F);
var distCoeffs = window.cv.matFromArray(
4,
1,
window.cv.CV_64F,
[0, 0, 0, 0]
); // Assuming no lens distortion
var rvec = new window.cv.Mat(3, 1, window.cv.CV_64F);
var tvec = new window.cv.Mat(3, 1, window.cv.CV_64F);
let ret_val = window.cv.solvePnP(
modelPoints,
imagePoints,
cameraMatrix,
distCoeffs,
rvec,
tvec,
false,
window.cv.SOLVEPNP_ITERATIVE // flags
);
// console.log("-------ret_val--------");
// console.log(ret_val);
// console.log("-------rvecs--------");
// console.log("rvecs.data64F", rvec.data64F);
// console.log("tvecs.data64F", tvec.data64F);
var rtn = getEulerAngle(rvec);
var pitch = rtn[0]; // 俯仰角
var yaw = rtn[1]; // 水平角
var roll = rtn[2]; // 翻滚角
// console.log("pitch:", pitch, "yaw:", yaw, "roll:", roll);
cv.solvePnP介绍
在计算机视觉领域,解决摄像头姿态估计(Camera Pose Estimation)问题是一项关键任务。摄像头姿态估计可以用于许多应用,例如增强现实、目标跟踪和三维重建等。OpenCV是一个广泛使用的开源计算机视觉库,其中的cv.solvePnP
方法是用于解决摄像头姿态估计问题的重要工具。
cv.solvePnP
方法是OpenCV库中的一个函数,用于估计摄像头的姿态。该方法可以通过已知的物体三维坐标和对应的图像中的二维坐标来计算摄像头的姿态。姿态包括摄像头的旋转和平移。
cv.solvePnP原理
cv.solvePnP
方法的原理基于解决一种称为PnP问题(Perspective-n-Point Problem)的几何计算。该问题旨在通过已知的三维点和它们在图像中的投影来计算摄像头的姿态。具体来说,该方法利用了摄像头的投影模型和三维-二维点对之间的几何关系。
在解决PnP问题时,cv.solvePnP
方法通常使用一种称为迭代最小化重投影误差(Iterative Minimization of Reprojection Error)的技术。该技术通过最小化实际观测到的图像点和由估计的摄像头姿态计算得到的投影点之间的误差来优化姿态估计。
cv.solvePnP
方法在许多计算机视觉应用中都有广泛的应用,其中包括但不限于:
增强现实(AR):用于将虚拟对象准确地叠加到实际世界中。
目标跟踪:用于追踪目标物体的位置和姿态。
三维重建:用于从多个视角的图像中重建三维场景。
运行代码查看效果
npm i
安装依赖
npm start
运行代码
3.绘制姿态示意直线
添加canvas元素
计算姿态直线坐标并绘制
相关代码内容如下:
var noseEndPoint2D = new window.cv.Mat(1, 2, window.cv.CV_64F);
var jacobian = new window.cv.Mat(
imagePoints.rows * 2,
13,
window.cv.CV_64F
);
window.cv.projectPoints(
window.cv.matFromArray(1, 3, window.cv.CV_64F, [0.0, 0.0, 1000.0]),
rvec,
tvec,
cameraMatrix,
distCoeffs,
noseEndPoint2D,
jacobian
);
// console.log(noseEndPoint2D);
// 绘制线段,连接鼻尖和其它点
var p1 = new window.cv.Point(
Math.round(imagePoints.data32F[0]),
Math.round(imagePoints.data32F[1])
);
var p2 = new window.cv.Point(
Math.round(noseEndPoint2D.data64F[0]),
Math.round(noseEndPoint2D.data64F[1])
);
var zeroMat = window.cv.Mat.zeros(
inputResolution.height,
inputResolution.width,
window.cv.CV_8U
);
// console.log("p1", p1.x, p1.y);
// console.log("p2", p2.x, p2.y);
window.cv.line(zeroMat, p1, p2, new window.cv.Scalar(255, 0, 0), 2);
window.cv.imshow("cv", zeroMat);
最终的效果如下
总结
感谢您看到这里,本文介绍了如何结合tensorflow.js 和 opencv.js通过面部特征点估算脸部姿态并绘制示意图,希望对您有所帮助,如果文章中存在任何问题、疏漏,或者您对文章有任何建议,请在评论区提出。