前言

对于前端来说,需要后端提供一个人脸识别接口,前端传入图片,接口识别并返回结果,如此看来,其实前端只需实现图片传入即可,但是其实不然,在传入图片时,需要进行以下几点操作:

  1. 判断图片格式,市场上比较常见的是.jpg.jpeg.png
  2. 计算文件大小,一般要求不超过5MB
  3. 对图片进行base64加密

其实前2点具体要看接口要求,但是第3点,是实现人脸识别必备步骤,下文重点讲述一下移动端实现人脸识别的base64加密方法

问题

项目主要使用的技术栈是uniapp,uniapp的优点是上手快,基于vue开发,但缺点也很明显,多环境兼容导致兼容性较差,真机调试和运行较慢。比如h5端可以轻松实现base64加密,但是安卓环境完全不行,因为本地上传图片时,会返回一个blob流,但是uniapp的blob流是以http://localhost…(安卓环境无法识别localhost) 开始,导致无法进行base64加密

解决办法

经过多方实现后,借用html5+ api的多个结合方法(plus.zip.compressImageplus.io.resolveLocalFileSystemURLplus.io.FileReader)实现加密,主要代码如下:

//app压缩图片  用for循环 来处理图片压缩 的问题,原因是 plus.zip.compressImage 方法 是异步执行的,for循环很快, 同时手机可执行的压缩方法有限制:应该是3个吧。超出直接就不执行了。所以 原理就是 在图片压缩成功后 继续 回调 压缩函数。 以到达循环压缩图片的功能。
app_img(num, rem) {let that = this;let index = rem.tempFiles[num].path.lastIndexOf('.'); //获取图片地址最后一个点的位置let img_type = rem.tempFiles[num].path.substring(index + 1, rem.tempFiles[num].path.length); //截取图片类型如png jpglet img_yuanshi = rem.tempFiles[num].path.substring(0, index); //截取图片原始路径let d2 = new Date().getTime(); //时间戳//压缩图片plus.zip.compressImage({src: rem.tempFiles[num].path, //你要压缩的图片地址dst: img_yuanshi + d2 + '.' + img_type, //压缩之后的图片地址(注意压缩之后的路径最好和原生路径的位置一样,不然真机上报code-5)quality: 70 //[10-100]},function (e) {//压缩之后路径转base64位的//通过URL参数获取目录对象或文件对象plus.io.resolveLocalFileSystemURL(e.target, function (entry) {// 可通过entry对象操作test.html文件entry.file(function (file) {//获取文件数据对象var fileReader = new plus.io.FileReader(); // 文件系统中的读取文件对象,用于获取文件的内容//alert("getFile:" + JSON.stringify(file));fileReader.readAsDataURL(file); //以URL编码格式读取文件数据内容fileReader.onloadend = function (evt) {//读取文件成功完成的回调函数that.base64Img = evt.target.result.split(',')[1]; //拿到‘data:image/jpeg;base64,‘后面的console.log('that.base64Img', that.base64Img);// rem.tempFiles[num].Base64_Path = evt.target.result.split(',')[1];};});});// that.base64Img = that.base64Img.concat(rem.tempFiles[num]);// 【注意】在此人脸认证中,只会传一张图片,故不考虑多张图片情况//利用递归循环来实现多张图片压缩// if (num == rem.tempFiles.length - 1) {//     return;// } else {//    that.app_img(num + 1, rem);// }},function (error) {console.log('Compress error!');console.log(JSON.stringify(error));uni.showToast({title: '编码失败' + error});});
},

详细实现思路

其实对于uniapp实现人脸识别功能来讲,大概要经过这么几个步骤

  1. onImage():打开手机相册上传图片,获取blob流(本地临时地址)
  2. #ifdef APP-PLUS/#ifndef APP-PLUS:判断系统环境,是h5还是安卓环境,然后在进行图片压缩和加密,具体实现代码如下:
//#ifdef APP-PLUS
//图片压缩
that.app_img(0, res);
//#endif// #ifndef APP-PLUS
that.blobTobase64(res.tempFilePaths[0]);
// #endif
  1. app_img()/blobTobase64():对要识别的图片进行base64加密
  2. onSave()—>upImage():附件上传,并处理识别信息

具体代码

<!-- 人脸认证 -->
<template><view><view class="u-margin-30 text-center"><u-avatar size="600" :src="data:imageSrc"></u-avatar></view><view class="u-margin-60"><u-button type="primary" class="u-margin-top-60" @click="onImage">{{ !imageSrc ? '拍照' : '重拍' }}</u-button><!-- <u-button type="primary" class="u-margin-top-30">重拍</u-button> --><u-button type="primary" class="u-margin-top-50" @click="onSave">保存</u-button></view><u-toast ref="uToast" /></view>
</template><script>
import { registerOrUpdateFaceInfo, UpdateLaborPersonnel } from '@/api/mww/labor.js';
import { UploadByProject } from '@/api/sys/upload.js';
import { sysConfig } from '@/config/config.js';
import storage from 'store';
import { ACCESS_TOKEN } from '@/store/mutation-types';
export default {name: 'face-authentication',data() {return {imageSrc: '',lastData: {},base64Img: '',base64: ''};},onLoad(option) {this.lastData = JSON.parse(decodeURIComponent(option.lastData));console.log('前一个页面数据', this.lastData);uni.setNavigationBarTitle({title: this.lastData.CnName + '-人脸认证 '});},methods: {onSave() {if (!this.imageSrc) {this.$refs.uToast.show({title: '请先拍照',type: 'error'});}// 人脸上传,附件上传,劳务人员信息修改this.upImage();},// h5压缩图片的方式,url为图片流blobTobase64(url) {console.log('进来了2', url);let imgFile = url;let _this = this;uni.request({url: url,method: 'GET',responseType: 'arraybuffer',success: res => {let base64 = uni.arrayBufferToBase64(res.data); //把arraybuffer转成base64_this.base64Img = 'data:image/jpeg;base64,' + base64; //不加上这串字符,在页面无法显示}});},//app压缩图片  用for循环 来处理图片压缩 的问题,原因是 plus.zip.compressImage 方法 是异步执行的,for循环很快, 同时手机可执行的压缩方法有限制:应该是3个吧。超出直接就不执行了。所以 原理就是 在图片压缩成功后 继续 回调 压缩函数。 以到达循环压缩图片的功能。app_img(num, rem) {let that = this;let index = rem.tempFiles[num].path.lastIndexOf('.'); //获取图片地址最后一个点的位置let img_type = rem.tempFiles[num].path.substring(index + 1, rem.tempFiles[num].path.length); //截取图片类型如png jpglet img_yuanshi = rem.tempFiles[num].path.substring(0, index); //截取图片原始路径let d2 = new Date().getTime(); //时间戳//压缩图片plus.zip.compressImage({src: rem.tempFiles[num].path, //你要压缩的图片地址dst: img_yuanshi + d2 + '.' + img_type, //压缩之后的图片地址(注意压缩之后的路径最好和原生路径的位置一样,不然真机上报code-5)quality: 70 //[10-100]},function(e) {//压缩之后路径转base64位的//通过URL参数获取目录对象或文件对象plus.io.resolveLocalFileSystemURL(e.target, function(entry) {// 可通过entry对象操作test.html文件entry.file(function(file) {//获取文件数据对象var fileReader = new plus.io.FileReader(); // 文件系统中的读取文件对象,用于获取文件的内容//alert("getFile:" + JSON.stringify(file));fileReader.readAsDataURL(file); //以URL编码格式读取文件数据内容fileReader.onloadend = function(evt) {//读取文件成功完成的回调函数that.base64Img = evt.target.result.split(',')[1]; //拿到‘data:image/jpeg;base64,‘后面的console.log('that.base64Img', that.base64Img);// rem.tempFiles[num].Base64_Path = evt.target.result.split(',')[1];};});});// that.base64Img = that.base64Img.concat(rem.tempFiles[num]);// 【注意】在此人脸认证中,只会传一张图片,故不考虑多张图片情况//利用递归循环来实现多张图片压缩// if (num == rem.tempFiles.length - 1) {//  return;// } else {//    that.app_img(num + 1, rem);// }},function(error) {console.log('Compress error!');console.log(JSON.stringify(error));uni.showToast({title: '编码失败' + error});});},// 打开手机相机相册功能onImage() {const that = this;// 安卓系统无法默认打开前置摄像头,具体请看下面app-plus原因,uni.chooseImage({count: 1, //默认9sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有sourceType: ['camera'], // 打开摄像头-'camera',从相册选择-'album'success: function(res) {console.log('文件结果', res);if (res.tempFilePaths.length > 0) {// Blob流地址that.imageSrc = res.tempFilePaths[0];//#ifdef APP-PLUS//图片压缩that.app_img(0, res);//#endif// #ifndef APP-PLUSthat.blobTobase64(res.tempFilePaths[0]);// #endif} else {that.$refs.uToast.show({title: '无文件信息',type: 'error'});}},fail: function(res) {console.log('失败了', res.errMsg);that.$refs.uToast.show({title: res.errMsg,type: 'error'});}});// #ifdef APP-PLUS// console.log('app环境了');// 指定要获取摄像头的索引值,1表示主摄像头,2表示辅摄像头。如果没有设置则使用系统默认主摄像头。// 平台支持【注意注意注意】// Android - 2.2+ (不支持) :// 暂不支持设置默认使用的摄像头,忽略此属性值。打开拍摄界面后可操作切换。// iOS - 4.3+ (支持)// var cmr = plus.camera.getCamera(1);// var res = cmr.supportedImageResolutions[0];// var fmt = cmr.supportedImageFormats[0];// console.log('Resolution: ' + res + ', Format: ' + fmt);// cmr.captureImage(//  function(path) {//      alert('Capture image success: ' + path);//   },//    function(error) {//         alert('Capture image failed: ' + error.message);//   },//    { resolution: res, format: fmt }// );// #endif},// 上传附件至[人脸认证]服务器upImage() {if (!this.base64Img) {this.$refs.uToast.show({title: '无图片信息',type: 'error'});return;}const params = {identityId: this.lastData.IdCard, //身份证号码imgInfo: this.base64Img, //头像采用base64编码userId: this.lastData.Id, //劳务人员IduserName: this.lastData.CnName //劳务姓名};uni.showLoading();registerOrUpdateFaceInfo(params).then(res => {if (res.success) {this.$refs.uToast.show({title: '认证成功',type: 'success'});// 上传至附件服务器+修改劳务人员信息this.uploadFile();} else {this.$refs.uToast.show({title: '认证失败,' + res.message,type: 'error'});uni.hideLoading();}}).catch(err => {uni.hideLoading();uni.showModal({title: '提示',content: err});});},// 上传附件至附件服务器uploadFile() {const obj = {project: this.lastData.OrgCode || this.$store.getters.projectCode.value,module: 'mww.personnelCertification',segment: this.lastData.OrgCode,businessID: this.lastData.Id,storageType: 1};let str = `project=${obj.project}&module=${obj.module}&segment=${obj.segment}&businessID=${obj.businessID}&storageType=${obj.storageType}`;console.log('str', str);// const url = '';// console.log('url', url);// const formData = new FormData();// formData.append('file', this.imageSrc, '.png');// UploadByProject(str, formData).then(res => {//     if (res.success) {//        this.$refs.uToast.show({//          title: '上传成功',//          type: 'success'//         });//   } else {//      this.$refs.uToast.show({//          title: res.message,//           type: 'error'//       });//   }// });const token = uni.getStorageSync(ACCESS_TOKEN);const that = this;// 需要使用uniapp提供的api,因为that.imageSrc的blob流为地址头为localhost(本地临时文件)uni.uploadFile({url: `${sysConfig().fileServer}/UploadFile/UploadByProject?${str}`,filePath: that.imageSrc,formData: {...obj},header: {// 必须传token,不然会报[系统标识不能为空]authorization: `Bearer ${token}`},name: 'file',success: res => {that.$refs.uToast.show({title: '上传成功',type: 'success'});that.lastData.CertificationUrl = res.data[0].virtualPath;that.lastData.Certification = 1;that.updateLaborPersonnel();},fail: err => {console.log('上传失败了', err);that.$refs.uToast.show({title: '上传失败,' + err,type: 'error'});uni.hideLoading();}});},// 修改劳务人员信息updateLaborPersonnel() {UpdateLaborPersonnel(this.lastData).then(res => {if (res.success) {this.$refs.uToast.show({title: '修改成功',type: 'success'});// uni.showToast({//     title: '成功了'// });setTimeout(() => {uni.navigateBack({delta: 1});}, 800);} else {this.$refs.uToast.show({title: '修改失败,' + res.message,type: 'error'});}}).finally(() => {uni.hideLoading();});}}
};
</script><style scoped lang="less"></style>

uniapp 实现人脸认证相关推荐

  1. 人脸认证源码faceIdentify

    人脸认证: using AForge.Video.DirectShow; using face; using Newtonsoft.Json; using Newtonsoft.Json.Linq; ...

  2. 互联网晚报 | 2月17日 星期四 | 小鹏汽车回应总裁年薪超4亿;B站将上线开播前人脸认证功能;星巴克再次涨价...

    今日看点 ✦ Redmi K50电竞版正式发布:搭载高通骁龙8Gen1,售价3299元起 ✦ 小鹏汽车回应"总裁年薪超4亿":系误解,实为多年累积的股权激励 ✦ B站直播新规:开播 ...

  3. 【思考】人脸认证真的准确吗?通过身份证的人脸对比有哪些问题?

    本人已经开发了一套人脸识别人证对比的接口,应用场景主要在招聘时作为一个身份认证的功能, 通过后台的观察,我思考了几个问题. 1.深度学习比较受光线影响 我们现在的人脸识别模型都已经由传统的模式识别方式 ...

  4. 手把手教你实现一个人脸认证登录系统

    ​先看下效果图吧,满足你们的好奇心,哈哈哈 人脸登录成功 人脸登录失败 注册人脸 人脸库 一.创作动机 早在很久之前,公司同事已经实现了在网站的登陆模块加上人脸识别认证登陆功能,自己也就萌生了动手在自 ...

  5. 百度人脸对比,人脸认证Demo

    1.注册百度账号,创建应用获取相关授权 #百度人脸认证 BAIDU_APPID BAIDU_APIKEY BAIDU_SECRETKEY 2.pom文件引入jar包 <!-- 百度人脸对比 -- ...

  6. 浅谈一下我对Android实现人脸认证登录的认识

    1.什么是人脸认证登录? (简称TRFA:Tencent Research Face Authentication)是由腾讯研究院研制的. 从功能上来看,人脸认证登录系统是基于终端摄像头的一种身份加密 ...

  7. 支付宝人脸认证(安卓)

    支付宝人脸认证 支付宝人脸认证后端接入前端的实现 /*** 启动支付宝进行认证* @param url 开放平台返回的URL*/private void doVerify(String url) {i ...

  8. 人脸核身--第二篇--启用 H5人脸认证

    腾讯云接口文档 https://cloud.tencent.com/document/product/1007/35894 项目代码实战 @ApiOperation(value = " 启用 ...

  9. 身份证人脸认证接口是如何识别网络诈骗?

    日常新闻里大家总能或多或少地看到类似这样的信息:不法分子利用盗取或者非法买卖的他人身份证件进行诈骗,比如利用他人身份信息注册社交.游戏.交易等网络平台,通过平台伺机寻找容易下手的目标,不仅给受害者带来 ...

最新文章

  1. 替代TabActivity,底部菜单主框架搭建
  2. html5 游戏学习
  3. 集合嵌套存储和遍历元素的示例
  4. JProfiler9安装 监控Tomcat
  5. 使用Spring Roo进行快速云开发–第2部分:VMware Cloud Foundry
  6. 表单提交中的input、button、submit的区别
  7. Cloudera-Manager-agent 误删恢复
  8. Html input 标签
  9. mysql查询锁表及解锁
  10. AD19 add pins to nets错误_NGINX 502 Bad Gateway错误疑难解答
  11. 【ManageEngine】局域网监控软件是什么,有什么作用
  12. VBA-批量删除文本框内容(用类实现)
  13. 基于量化交易回测的金融股票案例基础知识
  14. 基于android的智慧停车app
  15. 黄金票据的制作与使用
  16. 基础知识 | es6的知识点
  17. LINUX 测试resnet18时,找不到模型 no checkpoint fount
  18. CSS clip:rect矩形剪裁功能及一些应用介绍
  19. 光猫 高级NAT配置
  20. 【艾思软件】微信小程序开发报价方案模版

热门文章

  1. OpenStack和Open Source MANO:NFV部署两大支柱
  2. 亚马逊、OZON、敦煌、MANO等跨境电商平台测评养号需要注意什么?
  3. 国外服务器解决域名备案问题
  4. 氢化溶血卵磷脂行业研究分析
  5. 面试问题:发一个随机红包,100块钱给10个人。每个人最多12块钱,最少6块钱。怎么分?
  6. 【图的存储】邻接多重表
  7. kali linux查看版本,kali linux 系统版本的查看方法
  8. 任务调度 cron使用
  9. 新绝代双骄3终极全攻略6
  10. 服务器做RAID,各个RAID特点