tensorflow.js 如何使用opencv.js通过面部特征点估算脸部姿态并绘制示意图

系列文章目录

  1. 如何在前端项目中使用opencv.js | opencv.js入门
  2. 如何使用tensorflow.js实现面部特征点检测
  3. tensorflow.js 如何从 public 路径加载人脸特征点检测模型
  4. tensorflow.js 如何使用opencv.js通过面部特征点估算脸部姿态并绘制示意图
  5. tensorflow.js 使用 opencv.js 将人脸特征点网格绘制与姿态估计线绘制结合起来,以获得更高的帧数
  6. 结合 tensorflow.js 、opencv.js 与 Ant Design 创建美观且高性能的人脸动捕组件并发布到InsCode

项目地址(github):https://github.com/couchette/simple-react-face-fandmark-detection
项目地址(gitcode):https://gitcode.com/qq_41456316/simple-react-face-fandmark-detection


前言

在计算机视觉领域,估算脸部姿态是一项具有挑战性但又极具应用前景的任务。通过识别脸部特征点,我们可以了解人脸的姿态,包括旋转角度、倾斜程度等信息。本文将介绍如何利用 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通过面部特征点估算脸部姿态并绘制示意图,希望对您有所帮助,如果文章中存在任何问题、疏漏,或者您对文章有任何建议,请在评论区提出。


  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

买药弟弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值