小程序人脸识别—检测人脸图片获取图片
2023-12-15 16:34:00
wxml
<view>
<view class="flex white">
<!-- 镜头翻转 -->
<view bindtap="reverse">镜头翻转</view>
<view bindtap="clickScanCode">扫二维码</view>
</view>
<view class="head-image-box w-100 text-center position-relative">
<!-- resolution:获取人脸图片后的清晰度 low:低 -->
<camera device-position="{{devicePosition ?'back': 'front'}}" class="camera" flash="off" resolution='low' />
<view class="title">{{ tipsText }}1</view>
<image src="{{faceImage}}" mode="" />
<cover-view class="cover-box" wx:if="{{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>
<canvas id="myCanvas" canvas-id="myCanvas" :style="'width:'+screenWidth+'px;'+'height:'+screenHeight+'px'"></canvas>
</view>
</view>
js
// pages/face/index.js
Page({
/**
* 页面的初始数据
*/
data() {
return {
isShow: false,
tipsText: '', // 错误文案提示
tempImg: '', // 本地图片路径
cameraEngine: null, // 相机引擎
devicePosition: false, // 摄像头朝向
isAuthCamera: true, // 是否拥有相机权限
isVerify: false,
translateY: -24,
timer: null,
isFlag: true,
origin: null,
base64: "",
personId: "",
isFlag2: true,
screenWidth: 375,
screenHeight: 640,
faceImage: '', //人脸图片
}
},
onShow: function () {
this.setData({
isVerify: false,
tipsText: "",
isFlag: true,
})
this.lineAnimation();
},
onLoad(options) {
this.initData();
},
onUnload() {
this.clearTimer();
},
onHide() {
this.clearTimer();
},
clearTimer() {
if (this.data.timer) {
clearInterval(this.data.timer);
this.setData({
timer: null,
})
}
this.setData({
isFlag: false,
})
},
// 初始化相机引擎
initData() {
// #ifdef MP-WEIXIN
// 1、初始化人脸识别
wx.initFaceDetect();
// 2、创建 camera 上下文 CameraContext 对象
this.setData({
cameraEngine: wx.createCameraContext(),
isShow: true,
})
// 3、获取 Camera 实时帧数据
const listener = this.data.cameraEngine.onCameraFrame((frame) => {
console.log(888888888, frame.data, frame.width, frame.height)
if (this.data.isVerify) return
//动态设置canvas的宽高,不设置会导致部分机型人脸不完整导致不能识别-----很重要!很重要!很重要!
if (this.data.isFlag2) {
this.setData({
isFlag2: false,
screenWidth: frame.width,
screenHeight: frame.height,
})
}
// 4、人脸识别,使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据
wx.faceDetect({
frameBuffer: frame.data,
width: frame.width,
height: frame.height,
enablePoint: true,
enableConf: true,
enableAngle: true,
enableMultiFace: true,
success: async (faceData) => {
console.log(1111, faceData)
let face = faceData.faceInfo[0]
if (face.x == -1 || face.y == -1) {
this.setData({
tipsText: '检测不到人'
})
}
if (faceData.faceInfo.length > 1) {
this.setData({
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.setData({
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.setData({
tipsText: '请勿遮挡五官'
})
} else {
if (this.isVerify) return
//人脸位置校验
var centerWidth = 250;
var centerHeight = 250;
if (face.x > (frame.width - centerWidth) / 2 && face.x < (frame
.width - centerWidth) / 2 + centerWidth && face.y > (frame
.height - centerHeight) / 2 && face.y < (frame.height -
centerHeight) / 2 + centerHeight) {
this.setData({
tipsText: '校验中...',
isVerify: true
})
// 太快获取的人脸可能比较抽象,给用户一个准备时间
setTimeout(async () => {
let img = await this.changeDataToBase64(
frame);
this.setData({
base64: img
})
this.searchUserFace();
}, 300)
} else {
this.setData({
tipsText: '请将人脸对准中心位置'
})
}
}
}
},
fail: (err) => {
console.log(2222, err)
if (this.isVerify) return
if (err.x == -1 || err.y == -1) {
this.setData({
tipsText: '检测不到人'
})
} else {
this.setData({
tipsText: err.errMsg || '网络错误,请退出页面重试'
})
}
},
})
})
// 5、开始监听帧数据
listener.start()
this.setData({
listener: listener
})
// #endif
},
reverse() {
let a = this.data.devicePosition
this.setData({
devicePosition: !a
})
},
clickScanCode() {
// 只允许通过相机扫码
// #ifdef MP-WEIXIN
wx.scanCode({
onlyFromCamera: true,
success: (res) => {
var data = JSON.parse(res.result.replace(/\ufeff/g, ""));
}
});
// #endif
},
changeDataToBase64(frame) {
console.log(4444, frame)
return new Promise((resolve, reject) => {
var data = new Uint8Array(frame.data);
var clamped = new Uint8ClampedArray(data);
let that = this;
var width = this.data.screenWidth;
var height = frame.height * this.data.screenWidth / frame.width;
wx.canvasPutImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: frame.width,
height: frame.height,
data: clamped,
success(res) { // 转换临时文件
console.log(5555, res)
wx.canvasToTempFilePath({
x: 0,
y: 0,
width: width,
height: height,
canvasId: 'myCanvas',
fileType: 'jpg',
destWidth: width,
destHeight: height, // 精度修改
quality: 0.5,
success(res) {
console.log(666, res)
// 临时文件转base64
wx.getFileSystemManager().readFile({
filePath: res.tempFilePath, //选择图片返回的相对路径
encoding: 'base64', //编码格式
success: res => {
console.log(7777, res)
// 保存base64
resolve(res.data);
}
})
},
fail(res) {
console.log(8888, res)
reject(false);
}
});
},
fail(error) {
console.log(error);
}
})
})
},
searchUserFace() {
// 1.人脸识别错误 把isVerify设置为true继续识别
// 2.人脸识别成功,做对应的逻辑
console.log(333, this.data.base64)
this.setData({
faceImage: 'data:image/jpeg;base64,' + this.data.base64,
tipsText: '校验成功'
})
wx.stopFaceDetect(); //关闭人脸识别
this.data.listener.stop(); //关闭camera摄像头监听
return
var params = {
faceImage: this.data.base64,
}
searchFaces(params).then(res => {
console.log(444, res)
if (res.code == 200) {
wx.stopFaceDetect(); //关闭人脸识别
this.data.listener.stop(); //关闭camera摄像头监听
this.clickPushDetail(res.data.personCode);
this.setData({
tipsText: '校验成功'
})
}
}).catch(error => {
setTimeout(() => {
this.setData({
isVerify: 'false'
})
}, 500)
this.setData({
tipsText: '暂未查找到相关人员'
})
})
},
clickPushDetail() {
// 跳转到其他页面
},
lineAnimation() {
if (this.timer) return
this.setData({
timer: setInterval(() => {
this.setData({
translateY: this.data.translateY + 8
})
if (this.data.translateY >= 460) {
this.setData({
translateY: 10
})
}
}, 40)
})
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
css
/* pages/face/index.wxss */
page {
background-color: #000000;
}
.camera-change-image {
width: 52rpx;
margin-left: 40rpx;
}
.scan-image {
width: 48rpx;
}
.update-box {
color: #ffffff;
}
.operation-box {
position: fixed;
width: 100%;
bottom: calc(120rpx + env(safe-area-inset-bottom));
}
.icon-box {
width: 76rpx;
height: 76rpx;
}
first {
width: 72rpx;
height: 72rpx;
}
.head-image-box {
position: absolute;
top: 10vh;
color: white;
}
.camera {
width: 750rpx;
height: 872rpx;
position: relative;
z-index: 10;
}
#myCanvas {
position: absolute;
z-index: 1;
top: -10000px;
}
.title {
font-size: 40rpx;
margin-top: 60rpx;
}
.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;
z-index: 2;
}
文章来源:https://blog.csdn.net/weixin_43848576/article/details/135012779
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!