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

文章目录

  • 前言
  • 一、实现步骤
    • 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 tip0.0,-330.0,-65.0, // Chin-225.0,170.0,-135.0, // Left eye left corner225.0,170.0,-135.0, // Right eye right corne-150.0,-150.0,-125.0, // Left Mouth corner150.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 tipkeyPoints[152].x,keyPoints[152].y, // ChinkeyPoints[263].x,keyPoints[263].y, // Left eye left cornerkeyPoints[33].x,keyPoints[33].y, // Right eye right cornekeyPoints[308].x,keyPoints[308].y, // Left Mouth cornerkeyPoints[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 distortionvar 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通过面部特征点估算脸部姿态并绘制示意图,希望对您有所帮助,如果文章中存在任何问题、疏漏,或者您对文章有任何建议,请在评论区提出。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/801289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

注入类型(二)

一、二次注入 原理 在第一次进行数据库插入数据的时候,使用了addslashes等函数对其中的特殊字符进行了转义,但是addslashes有一个特点就是虽然参数在过滤后会添加 "\" 进行转义,但是 "\" 并不会插入到数据库中&#xff…

Dubbo 负载均衡

Dubbo 负载均衡 1、什么是负载均衡? 负载均衡是在支持应用程序的资源池中平均分配网络流量的一种方法。 现代应用程序必须同时处理数百万用户,并以快速、可靠的方式将正确的文本、视频、图像和其他数据返回给每个用户。 为了处理如此高的流量&#x…

(虚拟DOM)前端八股文修炼Day10

一 虚拟 DOM 是什么 虚拟 DOM (Virtual DOM) 本质上是真实 DOM 的一个轻量级的 JavaScript 表示形式。它是一个在内存中的抽象,用于描述真实 DOM 的结构和内容。虚拟 DOM 提供了一种机制,允许开发者通过操作 JavaScript 对象来间接更新页面,…

GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程)

🐯 GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图文教程) 📁 文章目录 🐯 GitHub教程:最新如何从GitHub上下载文件(下载单个文件或者下载整个项目文件)之详细步骤讲解(图…

【Leetcode】【240406】1249. Minimum Remove to Make Valid Parentheses

其实大部分是东京时间第二天凌晨才做的- -但国际服刷新比较晚 BGM:刀剑如梦 Decsripition Given a string s of ‘(’ , ‘)’ and lowercase English characters. Your task is to remove the minimum number of parentheses ( ‘(’ or ‘)’, in any position…

0104练习与思考题-算法基础-算法导论第三版

2.3-1 归并示意图 问题:使用图2-4作为模型,说明归并排序再数组 A ( 3 , 41 , 52 , 26 , 38 , 57 , 9 , 49 ) A(3,41,52,26,38,57,9,49) A(3,41,52,26,38,57,9,49)上的操作。图示: tips::有不少在线算法可视化工具(软…

鸿蒙内核源码分析 (内存管理篇) | 虚拟内存全景图是怎样的

初始化整个内存 OsSysMemInitOsMainmain从 main() 跟踪可看内存部分初始化是在 OsSysMemInit() 中完成的。 UINT32 OsSysMemInit(VOID) {STATUS_T ret;OsKSpaceInit();//内核空间初始化ret OsKHeapInit(OS_KHEAP_BLOCK_SIZE);// 内核动态内存初始化 512K if (ret ! LOS_OK…

【LeetCode】454. 四数相加 II

目录 题目 思路 代码 题目 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少个元组 (i, j, k, l) 能满足&#xff1a; 0 < i, j, k, l < nnums1…

一款轻量、干净的 Laravel 后台管理框架

系统简介 ModStart 是一个基于 Laravel 的模块化快速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 系统特性 …

做过的题-最大字段和的一个模板题

题目链接&#xff1a;StarryCoding | 奕歌科技 #include <bits/stdc.h> using ll long long; using namespace std; const int N 1e5 9; int a[N]; //对应动物的类型 int w[N]; //对应动物的体重 ll s[N]; //偏移量前缀和(释放魔法后) int main() {ios::sync_with_s…

蓝桥杯每日一题(博弈论)

4005 取石子游戏 巴什博弈: 取石子儿&#xff0c;石子儿一共n个&#xff0c;如果只能取1-m个&#xff0c;两个人轮流取。 (m1)|n 先手取x个&#xff0c;后手就可以取&#xff08;m1-x&#xff09;个。最后一定是后手全部取完。 若不能整除n的话。若先手先把余数全部取完…

【R语言基础】如何提取矩阵的上三角矩阵

如何提取矩阵的上三角矩阵&#xff1a; 例如&#xff1a;已知矩阵&#xff0c;如何求除对角线值以外均值。 问题描述 提示&#xff1a;求矩阵最大值、最小值、均值&#xff1b;可以值提取上/下三角形矩阵&#xff1b;借助R包 实现方法 借助R包gdata,函数upper.tri 与函数 l…

第三、四章 if语句 + 循环

第三章 if语句 bool类型 两种&#xff1a;True和False bool_1 True bool_2 False print(f"bool_1变量的内容是&#xff1a;{bool_1}," f"类型是&#xff1a;{type(bool_1)}") print(f"bool_2变量的内容是&#xff1a;{bool_2}," f"类…

解决Selenium元素拖拽不生效Bug

前几天在使用Selenium进行元素拖拽操作时&#xff0c;发现Selenium自带的元素拖拽方法&#xff08;dragAndDrop()&#xff09;不生效&#xff0c;网上的回答也是五花八门&#xff0c;比较混乱&#xff0c;尝试了以下几种方法均无法解决。 方案1&#xff1a;通过dragAndDrop()方…

外部模块介绍(七) 蓝牙HC05

HC05原理图 2. 蓝牙模块的调试 2.1 两种工作模式: HC-05蓝牙串口通讯模块具有两种工作模式:命令响应工作模式和自动连接工作模式。在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。 当模块处于自动连接工作模式时,将自动根据事…

二叉树练习day.3

104.二叉树的最大深度 链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root…

pygame旋转直线,计算角色到墙距离

pygame怎么计算距离 在Pygame中&#xff0c;计算两点之间的距离可以使用几何公式。给定两点P1(x1, y1)和P2(x2, y2)&#xff0c;距离D可以用以下公式计算&#xff1a; D √((x2 - x1) (y2 - y1)) 在Python中&#xff0c;你可以使用math库中的sqrt函数来计算平方根。以下是一…

34-5 CSRF漏洞 - CSRF分类

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 1)GET 类型 传参: 参数连接在URL后面 POC构造及执行流程: 构造URL,诱导受害者访问点击利用利用标签进行攻击: 构造虚假URL,在链接上添加payload抓包获取数据包,通过CSRF POC…

java中的set集合及其子类

Set系列集合&#xff1a;添加的元素是无序&#xff08;添加的数据的顺序和获取出数据顺序不一样&#xff09;&#xff0c;不重复&#xff0c;无索引 如&#xff1a;HashSet:无序&#xff0c;不可重复&#xff0c;无索引 LinkedHashSet:有序&#xff0c;不重复&#xff0c;无索…

excel散点图怎么每个点添加名称

最终效果图&#xff1a; 添加图标元素->数据标签->其他数据标签选项 选择单元格中的值 手动拖动数据标签&#xff0c;调整到合适的位置。