IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-24 20:47:38  更:2022-09-24 20:48:50 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码