微信小程序人脸识别功能(wx.faceDetect),含扫脸动画、人脸图片采集(upng.js)和位置显示-1。微信小程序人脸识别
最编程
2024-03-30 22:29:49
...
方案已废弃: 用到的第三方框架: 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
上一篇: 人体分析
下一篇: 找不到间隔落差的照片?
推荐阅读
-
微信 "扫一扫 "物联网,全面揭秘 "扫一扫 "背后的扫盲技术!-1.1 扫一扫感知物体是做什么的? 1.1 微信扫一扫是做什么的? 扫一扫识物是指以图片或视频(商品图片:鞋/包/美妆/服饰/家电/玩具/图书/食品/珠宝/家具/其他商品)为输入媒介,挖掘微信内容生态中的有价值信息(电商+百科+资讯,如图1所示),并展示给用户。这里的电商基本涵盖了微信小程序覆盖上亿SKU的全量优质电商,可以支持用户货比N家并直接下单购买,百科和资讯则聚合了微信内的头部自媒体如搜狗、搜搜、百度等,向用户展示和分享拍摄商品相关的内容资讯。 图 1 扫一扫识别功能示意图 欢迎大家更新iOS新版微信→扫一扫→识货,亲自体验,也欢迎大家通过识货界面的反馈按钮向我们提交反馈意见。 扫一扫识物实景图展示 1.2 扫一扫识物有哪些使用场景? 扫一扫识物的目的是为用户访问微信内部生态内容开辟一个新窗口,以用户扫图片为输入形式,为用户提供微信生态内容中的百科、资讯、电商等作为展示页面。除了用户熟悉的扫一扫操作外,我们还将进一步拓展长按操作,让用户更方便地进行扫一扫操作。"扫一扫知事 "的落地场景主要涵盖三大部分: a. 科普知识: a.科普知识。用户通过扫一扫,可以在微信生态圈中获取该对象的百科、资讯等常识或趣闻,帮助用户更好地了解该对象; b.购物场景。同样的搜索功能支持用户看到喜欢的商品立即检索到微信小程序电商中的同款商品,支持用户即扫即购; c.广告场景。扫一扫识别物体可以辅助公众号文章、视频更好地理解其中蕴含的图片信息,从而更好地投放匹配广告,提高点击率。 1.3 Sweep Sense 为 Sweep 家族带来了哪些新技术? 对于扫一扫来说,大家耳熟能详的应该就是扫一扫二维码、扫一扫小程序码、扫一扫条形码、扫一扫翻译了。无论是各种形式的编码还是文字字符,都可以看作是图片的一种特定编码形式,而物的识别则是对自然场景图片的识别,这对于扫一扫家族来说是一个质的飞跃,我们希望从物的识别入手,进一步拓展扫一扫对自然场景图片的理解能力,比如扫酒、扫车、扫植物、扫人脸等服务,如下图3所示。 图 3 Sweep 家族
-
微信小程序人脸识别功能(wx.faceDetect),含扫脸动画、人脸图片采集(upng.js)和位置显示-1。微信小程序人脸识别