uniapp实现人脸识别(不使用三方插件)
uniapp实现人脸识别
- 内容简介
- 功能实现
- 上传身份证
- 进行人脸比对
- 遇到的问题
内容简介
1.拍摄/相册将身份证照片上传到接口进行图片解析
2.使用live-pusher组件拍摄人脸照片,上传接口与身份证人脸进行比对
功能实现
上传身份证
先看下效果
![]() | ![]() |
---|
点击按钮调用chooseImageAPI进行图片的上传
// 上传按钮的loading以及disabled状态,避免多次上传
const loading = ref(false)
// 上传按钮事件
const chooseIdCard = () => {
uni.chooseImage({
success: (tempFiles) => {
// 获取到当前图片路径并调用上传方法
uploadIdCard(tempFiles.tempFilePaths[0])
}
})
}
// 身份证图片上传
const uploadIdCard = async (stream: (ArrayBuffer | string)) => {
loading.value = true
uni.uploadFile({
url: '/cardInfo/uploads', // 你的上传接口地址
filePath: stream, // 选中的图片
name: 'file', // 与后端协定的key
success: ({data, statusCode }) => {
if(statusCode == 200){
// 这里需要注意下,接口返回的事string,需要解析后才可正常使用
const result = JSON.parse(data)
if(result.code == 200 || result.success == true){
// 这里写上传成功的逻辑
// 我要将数据存在store中 给后面的页面使用
loading.value = false
const memberStore = useMemberStore()
memberStore.setPersonInfo(result.data)
uni.navigateTo({
url:'/pages/face/face',
})
}else{
uni.showToast({
icon: 'error',
title: result.msg
})
}
}
},
fail: (err) => {
console.error(err);
uni.showToast({
icon: 'error',
title: '上传失败fail!'
})
}
});
}
进行人脸比对
live-pusher组件实现摄像头调起以及样式的实现,在之前的文章有记录,点击查看,
这里主要描述该组件截图上传的部分
<template>
<cover-view class="pushContent">
<live-pusher id="pusherFaceId" ref="pusherRef" class="livePusher"
aspect="1:1" :whiteness="1" :beauty="1" device-position="front"
/>
<cover-image class="pusherImg" src="/static/images/faceRadio.png" alt=""></cover-image>
</cover-view>
</template>
<script lang="ts" setup>
const pusherContext = ref()
onMounted(() => {
// 获取当前组件实例
const instance = getCurrentInstance() as ComponentInternalInstance;
// 创建 live-pusher 上下文 livePusherContext 对象。
// 这是要用实例的proxy代理对象
pusherContext.value = uni.createLivePusherContext("pusherFaceId", instance.proxy)
// 开启摄像头预览
pusherContext.value.startPreview({
success: () => {
// 人脸拍摄上传
faceRecognition()
}
});
})
const faceRecognition = () => {
pusherContext.value.snapshot({
success: (res: UniHelper.LivePusherProps) => {
uploadFace(res.message.tempImagePath)
},
})
}
const uploadFace = (stream) => {
uni.uploadFile({
url: '/cardInfo/faceUploads',
filePath: stream,
name: 'file',
// 额外的参数
formData: {
cardToken: memberStore.personInfo.cardToken
},
success: ({data, statusCode }) => {
if(statusCode == 200){
const result = JSON.parse(data)
if(result.code == 200 || result.success == true){
const memberStore = useMemberStore()
memberStore.setProfile(result.data)
uni.navigateTo({
url:'/pages/main/main',
})
}else{
uni.showToast({
icon: 'error',
title: result.msg
})
faceRecognition()
}
}
},
fail: (err) => {
uni.showToast({
icon: 'error',
title: '上传失败fail!'
})
}
});
}
</script>
遇到的问题
- 使用nvue页进行开发
vue页面在调用live-pusher组件的API时,不支持回调
人脸拍摄需要在摄像头调起成功之后进行,并且拍摄快照需要在success回调中获取值
- 创建 live-pusher 上下文 livePusherContext 对象时要用proxy代理对象
之前使用 getCurrentInstance().ctx 去获取实例对象,在本地打包以及自定义基座包的时候都没有问题,但是打正式包就会报错,导致无法 创建 live-pusher对象,摄像头黑屏
ctx 和 proxy 的区别
特性 | ctx | proxy |
---|---|---|
适用版本 | Vue 2.x 和 Vue 3.x | Vue 3.x |
推荐使用 | Vue 2.x | Vue 3.x |
访问方式 | 直接访问组件实例 | 通过代理对象访问组件实例 |
安全性 | 较低,直接操作实例可能带来风险 | 较高,通过代理对象更安全 |
- 流文件上传
刚开始尝试用uni.request尝试上传流文件,没成功 。在这个做个记录
uni实现本地文件转数据流
- 通过h5+的API FileReader读取文件 获得base64地址
- uni中不支持js的FileReader 只支持5+的 API,两者是有区别的,需要注意下
- uni自带的API base64ToArrayBuffer 再将base64转换为buffer
pusherContext.value.snapshot({ success: (res: UniHelper.LivePusherProps) => { // 5+API FileReader读取文件 获得base64地址 const reader = new plus!.io!.FileReader!(); reader.readAsDataURL(res.message.tempImagePath) reader.onload = (readerRes: PlusIoFileEvent) => { var speech = readerRes!.target!.result; imgUrl.value = speech // uni自带的APIbase64ToArrayBuffer 将文件转换为buffer const arrayBuffer = uni.base64ToArrayBuffer(speech) const resFace = await faceRecognitionAPI(arrayBuffer) if(resFace.code == 200){ isfaced.value = true setTimeout(() => { uni.navigateTo({ url: '/pages/main/main' }) }, 1500) }else{ uni.showToast({ icon: 'error', title: '识别失败,请对准摄像头!' }) faceRecognition() } } } })