目录
1660033284021056
1. 微信小程序人脸识别
方案已废弃: 用到的第三方框架: upng.js及pako.js(速度太慢,容易卡顿)
推荐使用:微信小程序人脸识别改进版
1. 初始化人脸识别
wx.initFaceDetect()
2. 创建 camera 上下文 CameraContext 对象
this.cameraEngine = wx.createCameraContext();
3.获取 Camera 实时帧数据
const listener = this.cameraEngine.onCameraFrame()
4.人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据
wx.faceDetect()
5.完整代码
<template>
<view>
<view class="d-flex justify-content-between align-items-center update-box mt-40 mr-32">
<!-- 可用iconfont -->
<image @click="devicePosition=!devicePosition" class="camera-change-image" mode="widthFix"
src="@/static/images/camera_change.png"></image>
</view>
<view class="head-image-box w-100 text-center position-relative">
<!-- resolution:获取人脸图片后的清晰度 low:低 -->
<camera v-if='isAuthCamera' :device-position="devicePosition ?'back': 'front'" class="camera" flash="off"
resolution='low' />
<view class="title mt-40" v-show="!tempImg && tipsText">{{ tipsText }}</view>
<cover-view class="cover-box" v-show="isShow">
<cover-image class="image-box" src="@/static/images/camera_verify.png"></cover-image>
<!-- cover-view 不支持动画所以只能变通的形式实现 -->
<cover-image :style="'transform: translateY('+translateY+'rpx);'" class="line"
src="@/static/images/bg_line.png"></cover-image>
<!-- <cover-view class="line"></cover-view> -->
</cover-view>
</view>
</view>
</template>
<script>
import upng from "@/common/js/upng.js"
export default {
name: 'index',
data() {
return {
isShow: false,
tipsText: '', // 错误文案提示
tempImg: '', // 本地图片路径
cameraEngine: null, // 相机引擎
devicePosition: true, // 摄像头朝向
isAuthCamera: true, // 是否拥有相机权限
isVerify: false,
translateY: -24,
timer: null,
isFlag: true,
origin: null
}
},
onShow: function() {
this.isVerify = false;
this.tipsText = "";
this.isFlag = true;
},
onLoad(options) {
this.origin = options.origin;
this.initData();
this.lineAnimation()
},
onUnload: function() {
clearInterval(this.timer);
this.timer = null;
this.isFlag = false;
},
methods: {
// 初始化相机引擎
initData() {
// #ifdef MP-WEIXIN
// 1、初始化人脸识别
wx.initFaceDetect()
// 2、创建 camera 上下文 CameraContext 对象
this.cameraEngine = wx.createCameraContext();
this.isShow = true;
// 3、获取 Camera 实时帧数据
const listener = this.cameraEngine.onCameraFrame((frame) => {
if (this.tempImg) {
return;
}
// 4、人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据
wx.faceDetect({
frameBuffer: frame.data,
width: frame.width,
height: frame.height,
enablePoint: true,
enableConf: true,
enableAngle: true,
enableMultiFace: true,
success: (faceData) => {
if (this.isVerify) return
let face = faceData.faceInfo[0]
if (face.x == -1 || face.y == -1) {
this.tipsText = '检测不到人'
}
if (faceData.faceInfo.length > 1) {
this.tipsText = '请保证只有一个人'
} else {
const {
pitch,
roll,
yaw
} = face.angleArray;
const standard = 0.5
if (Math.abs(pitch) >= standard || Math.abs(roll) >= standard ||
Math.abs(yaw) >= standard) {
this.tipsText = '请平视摄像头'
} else if (face.confArray.global <= 0.8 || face.confArray.leftEye <=
0.8 || face.confArray.mouth <= 0.8 || face.confArray.nose <= 0.8 ||
face.confArray.rightEye <= 0.8) {
this.tipsText = '请勿遮挡五官'
} else {
this.tipsText = '校验中...'
this.isVerify = true;
// 太快获取的人脸可能比较抽象,给用户一个准备时间
setTimeout(() => {
//借助upng把流转为二进制数据
let pngData = upng.encode([frame.data], frame.width,
frame.height),
base64 = arrayBufferToBase64(pngData);
// 获取到base64后可以已上传,展示,或保存到本地
var imageType = getImageType();
function getImageType() {
let type = "center"
if (face.y / frame.height < 0.3333) {
type = "top"
} else if (face.y / frame.height > 0.6666) {
type = "bottom"
}
return type;
}
//二进制转base64
function arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
// unicode编码还原
binary += String.fromCharCode(bytes[i]);
}
return "data:image/png;base64," + btoa(binary);
}
// 小程序没有window对象,需手动实现btoa()方法
// 作用: 字符转base64
function btoa(string) {
const b64 =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
string = String(string);
var bitmap, a, b, c,
result = "",
i = 0,
rest = string.length %
3; // To determine the final padding
for (; i < string.length;) {
if ((a = string.charCodeAt(i++)) > 255 ||
(b = string.charCodeAt(i++)) > 255 ||
(c = string.charCodeAt(i++)) > 255)
throw new TypeError(
"Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."
);
bitmap = (a << 16) | (b << 8) | c;
result += b64.charAt(bitmap >> 18 & 63) + b64
.charAt(bitmap >> 12 & 63) +
b64.charAt(bitmap >> 6 & 63) + b64.charAt(
bitmap & 63);
}
return rest ? result.slice(0, rest - 3) + "==="
.substring(rest) : result;
};
this.tipsText = '校验成功'
setTimeout(() => {
this.clickPushDetail(imageType);
}, 50)
}, 300)
}
}
},
fail: (err) => {
if (this.isVerify) return
if (err.x == -1 || err.y == -1) {
this.tipsText = '检测不到人'
} else {
this.tipsText = err.errMsg || '网络错误,请退出页面重试'
}
},
})
})
// 5、开始监听帧数据
listener.start()
// #endif
},
clickPushDetail(imageType) {
if (!this.isFlag) return
// 可以跳转到详情页面
},
lineAnimation() {
if (this.timer) return
this.timer = setInterval(() => {
this.translateY += 3;
if (this.translateY >= 460) {
this.translateY = 10;
}
}, 12)
},
}
}
</script>
<style>
page {
background-color: #000000;
}
</style>
<style lang="scss" scoped>
.d-flex {
display: flex;
}
.justify-content-center {
justify-content: center;
}
.align-items-center {
align-items: center;
}
.camera-change-image {
width: 48rpx;
margin-left: 40rpx;
}
.mr-32{
margin-right: 32rpx;
}
.mt-40 {
margin-top: 40rpx;
}
.text-center {
text-align: center;
}
.position-relative{
position: relative;
}
.w-100{
width: 100%;
}
.update-box {
color: #ffffff;
}
.head-image-box {
position: absolute;
top: 10vh;
color: white;
.camera {
width: 100%;
height: 872rpx;
}
.title {
font-size: 48rpx;
font-weight: bold;
}
.cover-box {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
width: 500rpx;
height: 500rpx;
}
.image-box {
width: 100%;
height: 100%;
}
.line {
position: absolute;
top: 0rpx;
left: 8rpx;
right: 8rpx;
width: auto;
height: 30rpx;
// transform: translateY(-24rpx);
// animation: radar-beam 1.5s infinite;
// background: linear-gradient(180deg, rgba(13, 110, 217, 0) 0%, rgba(13, 110, 217, 0.4000) 100%);
z-index: 2;
}
// @keyframes radar-beam {
// 0% {
// transform: translateY(24rpx);
// }
// 100% {
// transform: translateY(450rpx);
// }
// }
}
</style>
附带绝对定位的圆角图片真机展示问题
父元素添加:-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
.image-box {
overflow: hidden;
border-radius: 50%;
-webkit-backface-visibility: hidden;
-webkit-transform: translate3d(0, 0, 0);
z-index: 1;
.face-image {
width: 100%;
height: 100%;
position: absolute;
left: 0;
&.top {
top: 0;
}
&.bottom {
bottom: 0;
}
&.center {
top: 50%;
transform: translateY(-50%);
}
}
}
借鉴于:ZegTsai
2. H5人脸识别
详见:h5人脸识别