| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> JavaScript知识库 -> VUE项目如何实现H5端人脸识别功能 -> 正文阅读 |
|
[JavaScript知识库]VUE项目如何实现H5端人脸识别功能 |
需求:安卓原生app端接入腾讯人脸核身sdk,采集人脸信息和账号绑定。用户使用同一账号登录微信公众号h5端,h5采集人脸信息,调用腾讯人脸比对接口,和原生app端采集的人脸信息比对,是否是同一个人,然后再进行下一步操作。 H5实现思路:1.如何调用移动端设备摄像头 2.使用tracking.js捕捉人脸 3.对人脸进行拍照,描绘到canvas画布上面 4.将照片转换成base64格式 5.调用后台接口,后台调用腾讯人脸比对接口进行比对。(由于调用腾讯人脸比对接口需要签名,签名在后台做比较合适) 代码以及注释1.下载tracking.js 网址:https://trackingjs.com? ?将需要的js文件复制到静态资源文件夹 2.使用video标签调用手机摄像头,playsinline、webkit-playsinline属性非常重要,如果不写会掉不起来苹果手机的摄像头。微信开发者文档上面有明确的说明,喜欢钻研的同学可以到微信开发者文档中查看文档。video和canvas的宽高的写法是为了适配手机屏幕的大小。 ``` <template> ? <div id="app"> ? ? <div v-show="showContainer" class="face-capture" id="face-capture"> ? ? ? <p class="tip">请保持人像在取景框内</p> ? ? ? <video ? ? ? ? id="video" ? ? ? ? :width="vwidth" ? ? ? ? :height="vheight" ? ? ? ? playsinline ? ? ? ? webkit-playsinline ? ? ? ></video> ? ? ? <canvas id="refCanvas" :width="cwidth" :height="cheight"></canvas> ? ? ? <img ? ? ? ? class="img-cover" ? ? ? ? src="@/assets/img/face/yuanxingtouming.png" ? ? ? ? alt="" ? ? ? /> ? ? ? <p class="contentp">{{ scanTip }}</p> ? ? </div> ? ? <div v-if="!showContainer" class="img-face"> ? ? ? <img class="imgurl" :src="imgUrl" /> ? ? </div> ? </div> </template> ``` 3.获取媒体设备,video开始播放 ``` import tracking from "@/assets/js/tracking-min.js"; import "@/assets/js/data/face-min.js"; import "@/assets/js/data/eye-min.js"; import "@/assets/js/data/mouth-min.js"; import { faceInfo, conFace } from "@/request/api/my.js"; export default { ? data() { ? ? return { ? ? ? screenSize: { ? ? ? ? width: window.screen.width, ? ? ? ? height: window.screen.height, ? ? ? }, ? ? ? URL: null, ? ? ? streamIns: null, // 视频流 ? ? ? showContainer: true, // 显示 ? ? ? tracker: null, ? ? ? tipFlag: false, // 提示用户已经检测到 ? ? ? flag: false, // 判断是否已经拍照 ? ? ? context: null, // canvas上下文 ? ? ? profile: [], // 轮廓 ? ? ? removePhotoID: null, // 停止转换图片 ? ? ? scanTip: "人脸识别中...", // 提示文字 ? ? ? imgUrl: "", ? ? ? canvas: null, ? ? ? trackertask: null, ? ? ? vwidth: "266", ? ? ? vheight: "266", ? ? ? cwidth: "266", ? ? ? cheight: "266", ? ? ? userInfo: {}, ? ? ? orderData: {}, ? ? }; ? }, mounted() { ? ? //设置video canvas宽高 ? ? const scale = this.screenSize.width / 375; ? ? this.vwidth = 266 * scale; ? ? this.vheight = 266 * scale; ? ? this.cwidth = 266 * scale; ? ? this.cheight = 266 * scale; ? ? this.playVideo(); ? }, methods: { playVideo() { ? ? ? this.getUserMedia( ? ? ? ? { ? ? ? ? ? //摄像头拍摄的区域 ? ? ? ? ? video: { ? ? ? ? ? ? width: 500, ? ? ? ? ? ? height: 500, ? ? ? ? ? ? facingMode: "user", ? ? ? ? ? } /* 前置优先 */, ? ? ? ? }, ? ? ? ? this.success, ? ? ? ? this.error ? ? ? ); ? ? }, ? ? // 访问用户媒体设备 ? ? getUserMedia(constrains, success, error) { ? ? ? if (navigator.mediaDevices.getUserMedia) { ? ? ? ? //最新标准API ? ? ? ? navigator.mediaDevices ? ? ? ? ? .getUserMedia(constrains) ? ? ? ? ? .then(success) ? ? ? ? ? .catch(error); ? ? ? } else if (navigator.webkitGetUserMedia) { ? ? ? ? //webkit内核浏览器 ? ? ? ? navigator.webkitGetUserMedia(constrains).then(success).catch(error); ? ? ? } else if (navigator.mozGetUserMedia) { ? ? ? ? //Firefox浏览器 ? ? ? ? navagator.mozGetUserMedia(constrains).then(success).catch(error); ? ? ? } else if (navigator.getUserMedia) { ? ? ? ? //旧版API ? ? ? ? navigator.getUserMedia(constrains).then(success).catch(error); ? ? ? } else { ? ? ? ? this.scanTip = "你的浏览器不支持访问用户媒体设备"; ? ? ? } ? ? }, } ``` 4.安卓手机在允许调用摄像头之后正常调用和播放,苹果手机第一次允许之后调不出来摄像头,返回到上个页面再次进入人脸识别页面,可以正常调用。这个问题想了很多方向,使用了微信api里面的一些监听方法,依然无效。想了一些策略,在前一个页面获取媒体设备等,都不是完美方案。 可以在调用video.play方法的时候,给它加一个定时器,让它1秒钟之后再执行。? 加上之后,苹果手机上面的问题解决了。自此,我猜想:当我们询问是否可以调用手机摄像头的时候,苹果的系统弹框阻碍了js的执行,在那一刻js代码停止执行,但是当我们点击允许之后,js代码没有继续执行,因为系统没有手段或者说事件去触发代码继续走。我们加上setTimeout函数之后,系统有了可以让代码继续执行的触发手段,所以js代码继续执行,我们就可以进行下一步人脸捕捉了。如果同学们有更好的解释,欢迎留言。 代码 ``` success(stream) { ? ? ? this.streamIns = stream; ? ? ? const video = document.getElementById("video"); ? ? ? // webkit内核浏览器 ? ? ? this.URL = window.URL || window.webkitURL; ? ? ? if ("srcObject" in video) { ? ? ? ? video.srcObject = stream; ? ? ? } else { ? ? ? ? video.src = this.URL.createObjectURL(stream); ? ? ? } ? ? ? // 苹果手机的系统弹框会阻止js的线程的继续执行 手动0.1秒之后自动执行代码 ? ? ? setTimeout(() => { ? ? ? ? video.play(); ? ? ? ? this.initTracker();// 人脸捕捉 ? ? ? }, 100); ? ? }, ? ? error(e) { ? ? ? this.scanTip = "访问用户媒体失败"; ? ? }, ``` 5.设置各种参数 实例化人脸捕捉实例对象 ``` // 人脸捕捉 设置各种参数 实例化人脸捕捉实例对象,注意canvas上面的动画效果。 ? ? initTracker() { ? ? ? this.context = document.getElementById("refCanvas").getContext("2d"); // 画布 ? ? ? this.canvas = document.getElementById("refCanvas"); ? ? ? this.tracker = new window.tracking.ObjectTracker("face"); // tracker实例 ? ? ? this.tracker.setInitialScale(4); ? ? ? this.tracker.setStepSize(2); // 设置步长 ? ? ? this.tracker.setEdgesDensity(0.1); ? ? ? try { ? ? ? ? this.trackertask = window.tracking.track("#video", this.tracker); // 开始追踪 ? ? ? } catch (e) { ? ? ? ? this.scanTip = "访问用户媒体失败,请重试"; ? ? ? } ? ? ? //开始捕捉方法 一直不停的检测人脸直到检测到人脸 ? ? ? this.tracker.on("track", (e) => { ? ? ? ? //画布描绘之前清空画布 ? ? ? ? this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); ? ? ? ? if (e.data.length === 0) { ? ? ? ? ? this.scanTip = "未检测到人脸"; ? ? ? ? } else { ? ? ? ? ? e.data.forEach((rect) => { ? ? ? ? ? ? //设置canvas 方框的颜色大小 ? ? ? ? ? ? this.context.strokeStyle = "#42e365"; ? ? ? ? ? ? this.context.lineWidth = 2; ? ? ? ? ? ? this.context.strokeRect(rect.x, rect.y, rect.width, rect.height); ? ? ? ? ? }); ? ? ? ? ? if (!this.tipFlag) { ? ? ? ? ? ? this.scanTip = "检测成功,正在拍照,请保持不动2秒"; ? ? ? ? ? } ? ? ? ? ? // 1.5秒后拍照,仅拍一次 给用户一个准备时间 ? ? ? ? ? // falg 限制一直捕捉人脸,只要拍照之后就停止检测 ? ? ? ? ? if (!this.flag) { ? ? ? ? ? ? this.scanTip = "拍照中..."; ? ? ? ? ? ? this.flag = true; ? ? ? ? ? ? this.removePhotoID = setTimeout(() => { ? ? ? ? ? ? ? this.tackPhoto(); ? ? ? ? ? ? ? document.getElementById("video").pause(); ? ? ? ? ? ? ? this.tipFlag = true; ? ? ? ? ? ? }, 1500); ? ? ? ? ? } ? ? ? ? } ? ? ? }); ? ? }, ``` 6.拍照 绘制照片,计算照片大小,腾讯人脸比对接口对照片大小和格式有要求。 ``` // 拍照 ? ? tackPhoto() { ? ? ? // 在画布上面绘制拍到的照片 ? ? ? this.context.drawImage( ? ? ? ? document.getElementById("video"), ? ? ? ? 0, ? ? ? ? 0, ? ? ? ? this.vwidth, ? ? ? ? this.vwidth ? ? ? ); ? ? ? // 保存为base64格式 ? ? ? this.imgUrl = this.saveAsPNG(document.getElementById("refCanvas")); ? ? ? /** 拿到base64格式图片之后就可以在this.compare方法中去调用后端接口比较了,也可以调用getBlobBydataURI方法转化成文件再去比较 ? ? ? ?* 我们项目里有一个设置个人头像的地方,先保存一下用户的图片,然后去拿这个图片的地址和当前拍照图片给后端接口去比较。 ? ? ? ?* */ ? ? ? // this.compare(imgUrl) ? ? ? //判断图片大小 ? ? ? this.imgSize(); ? ? ? this.faceToTengXun(); // 人脸比对 ? ? ? this.close(); ? ? }, ? ? imgSize() { ? ? ? if (this.imgUrl) { ? ? ? ? // 获取base64图片byte大小 ? ? ? ? const equalIndex = this.imgUrl.indexOf("="); // 获取=号下标 ? ? ? ? let size; ? ? ? ? if (equalIndex > 0) { ? ? ? ? ? const str = this.imgUrl.substring(0, equalIndex); // 去除=号 ? ? ? ? ? const strLength = str.length; ? ? ? ? ? const fileLength = strLength - (strLength / 8) * 2; // 真实的图片byte大小 ? ? ? ? ? size = Math.floor(fileLength / 1024); // 向下取整 ? ? ? ? ? console.log("size", size + "KB"); ? ? ? ? } else { ? ? ? ? ? const strLength = this.imgUrl.length; ? ? ? ? ? const fileLength = strLength - (strLength / 8) * 2; ? ? ? ? ? size = Math.floor(fileLength / 1024); // 向下取整 ? ? ? ? ? console.log("size", size + "KB"); ? ? ? ? } ? ? ? ? if (size > 1024) { ? ? ? ? ? // 图片超过1M 按比例压缩 ? ? ? ? ? this.imgUrl = document ? ? ? ? ? ? .getElementById("refCanvas") ? ? ? ? ? ? .toDataURL("image/png", 1024 / size); ? ? ? ? } ? ? ? } ? ? }, ? ? // Base64转文件 ? ? getBlobBydataURI(dataURI, type) { ? ? ? var binary = window.atob(dataURI.split(",")[1]); ? ? ? var array = []; ? ? ? for (var i = 0; i < binary.length; i++) { ? ? ? ? array.push(binary.charCodeAt(i)); ? ? ? } ? ? ? return new Blob([new Uint8Array(array)], { ? ? ? ? type: type, ? ? ? }); ? ? }, ? ? // compare(url) { ? ? // ? ? let blob = this.getBlobBydataURI(url, 'image/png') ? ? // ? ? let formData = new FormData() ? ? // ? ? formData.append("file", blob, "file_" + Date.parse(new Date()) + ".png") ? ? // ? ? // TODO 得到文件后进行人脸识别 ? ? // }, ? ? // 保存为png,base64格式图片 ? ? saveAsPNG(c) { ? ? ? return c.toDataURL("image/png", 0.4); ? ? }, ``` 7. 人脸采集之后,移除实例化对象,初始化参数和css样式部分代码 ``` close() { ? ? ? this.flag = false; ? ? ? this.tipFlag = false; ? ? ? this.showContainer = false; ? ? ? this.context = null; ? ? ? this.scanTip = "人脸识别中..."; ? ? ? clearTimeout(this.removePhotoID); ? ? ? if (this.streamIns) { ? ? ? ? this.streamIns.enabled = false; ? ? ? ? this.streamIns.getTracks()[0].stop(); ? ? ? ? this.streamIns.getVideoTracks()[0].stop(); ? ? ? } ? ? ? this.streamIns = null; ? ? ? this.trackertask.stop(); ? ? ? this.tracker = null; ? ? } <style> .face-capture { ? display: flex; ? flex-direction: column; ? align-items: center; ? justify-content: center; } .tip { ? position: fixed; ? top: 48px; ? z-index: 5; ? font-size: 18px; ? font-family: PingFangSC-Medium, PingFang SC; ? font-weight: 500; ? color: #333333; ? line-height: 25px; } .face-capture video, .face-capture canvas { ? position: fixed; ? top: 117.5px; ? object-fit: cover; ? z-index: 2; ? background-repeat: no-repeat; ? background-size: 100% 100%; } .face-capture .img-cover { ? position: fixed; ? top: 63px; ? width: 375px; ? height: 375px; ? object-fit: cover; ? z-index: 3; ? background-repeat: no-repeat; ? background-size: 100% 100%; } .face-capture .contentp { ? position: fixed; ? top: 438px; ? font-size: 18px; ? font-weight: 500; ? color: #333333; } .face-capture .rect { ? border: 2px solid #0aeb08; ? position: fixed; ? z-index: 4; } .img-face { ? display: flex; ? flex-direction: column; ? align-items: center; ? justify-content: center; } .img-face .imgurl { ? position: fixed; ? top: 117.5px; ? width: 266px; ? height: 266px; ? border-radius: 133px; } </style> ``` 总结:1.人脸捕捉技术使用的tracking.js,关键是要理解它的运作原理和一下参数配置。 2.因为要调用手机媒体设备,兼容性问题是大问题,特别是苹果手机的问题,往往不知道如何下手,需要有丰富的开发经验和各种曲线救国的开发思想。 |
|
JavaScript知识库 最新文章 |
ES6的相关知识点 |
react 函数式组件 & react其他一些总结 |
Vue基础超详细 |
前端JS也可以连点成线(Vue中运用 AntVG6) |
Vue事件处理的基本使用 |
Vue后台项目的记录 (一) |
前后端分离vue跨域,devServer配置proxy代理 |
TypeScript |
初识vuex |
vue项目安装包指令收集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 10:34:31- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |