位置: IT常识 - 正文

微信小程序 |基于百度AI从零实现人脸识别小程序(微信小程序开发一个多少钱)

编辑:rootadmin
原力计划微信小程序 |基于百度AI从零实现人脸识别小程序

推荐整理分享微信小程序 |基于百度AI从零实现人脸识别小程序(微信小程序开发一个多少钱),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:微信小程序游戏手游排行榜,微信小程序开发公司,微信小程序怎么制作自己的小程序,微信小程序开发一个多少钱,微信小程序怎么制作自己的小程序,微信小程序开发一个多少钱,微信小程序开发一个多少钱,微信小程序开发一个多少钱,内容如对您有帮助,希望把文章链接给更多的朋友!

写在前面

针对互联网上已有的人脸识别小程序项目,很多只是基于手动拍照,然后上传到SDK进行识别。这一过程完全脱离实际场景!无法直接使用! 本文项目是基于微信摄像头中的实时视频帧数据,通过实时动态识别小程序端所获取的照片帧,从而自动触发人脸识别和登录!完全贴合实际,真正的拿来即用!

一、需求背景

人脸识别是一个老生常谈的问题了,再继小程序的逐步普及化后,人脸识别的功能也变为了各大业务的家常菜。目前市面上已有的解决方案,一方面除了自研以外,对于本来就是小成本进行创业或者开发的个人以及初创型公司来说,接入一些专业的第三方的人脸识别接口不妨是一个优秀的解决方案。目前市面上常用的第三方支持技术有哪些,可以阅读本专栏的文章: 微信小程序 | 人脸识别的最终解决方案 – 里面做了详细的介绍和解读,相信能带你弄请这个方向的技术行情。

为此,这一次我们自己动手来实现一次全流程的人脸识别小程序。 没有基础不用担心,本文就是带领大家从零到一开始搭建,细致到每个网页功能如何选择、代码如何编写,前后端的逻辑如何编写。只会前端或者后端的小伙伴也不用担心,本文提供全流程的操作指引,让零基础的前/后端小白都能轻松上手。 废话不多说相信看到上面酷炫的效果大家应该都按捺不住了,那就让我们开整把。

二、系统架构2.1 系统技术栈前端后端- 语言:vue 2.0 | - 框架 : uni-app | - UI组件: uview- 语言:python | - 框架: Flask2.2 系统架构图

2.3 系统请求时序图

2.4 详细接口请求时序图

三、项目实现

要使用百度智能云的api接口,就需要在控制台创建你的项目应用,通过项目应用去获取API Key``Secret Key ``Access_token,这三个参数是后续调用api接口的必填参数,缺一不可!

3.1 开通百度智能云API登录到百度智能云人脸识别控制台选择相应的API接口并进行购买操作即可(其中我们选择的是人脸比对),其实为了方便我们可以一次性将所有的人脸识别相关的产品全部都进行一次购买,反正都是按量计费,不进行调用也就不用收钱了。3.2 并获取API Key微信小程序 |基于百度AI从零实现人脸识别小程序(微信小程序开发一个多少钱)

-在开通了服务的基础上,由于要获取三大认证参数,再调用接口之前我们仍需要进行应用的创建。

由此即可获取到三大参数 3.3 搭建项目调试环境

本项目是继续uniapp框架进行开发(采用uniapp框架开发的好处在于:在面对众多的小程序平台,我们只需要编写这一套代码就可以实现多平台的运行,极大程度的降低了开发成本!可以说是只要会一套小程序开发的流程,基本每个平台你都能拿下。)

详细的开发环境搭建过程,可以参考:从零开始搭建uni-app框架的小程序开发环境3.4 参考百度云SDK文档人脸识别接口Pthon SDK文档:人脸接口文档地址3.5 人脸对比接口详解

接口能力

两张人脸图片相似度对比:比对两张图片中人脸的相似度,并返回相似度分值;多种图片类型:支持生活照、证件照、身份证芯片照、带网纹照四种类型的人脸对比;活体检测:基于图片中的破绽分析,判断其中的人脸是否为二次翻拍(举例:如用户A用手机拍摄了一张包含人脸的图片一,用户B翻拍了图片一得到了图片二,并用图片二伪造成用户A去进行识别操作,这种情况普遍发生在金融开户、实名认证等环节。);质量检测:返回模糊、光照等质量检测信息,用于辅助判断图片是否符合识别要求;

业务应用

用于比对多张图片中的人脸相似度并返回两两比对的得分,可用于判断两张脸是否是同一人的可能性大小。

典型应用场景:如人证合一验证,用户认证等,可与您现有的人脸库进行比对验证。

result = client.match([ { 'image': base64.b64encode(open('1.jpg', 'rb').read()).decode(), 'image_type': 'BASE64', }, { 'image': base64.b64encode(open('2.jpg', 'rb').read()).decode(), 'image_type': 'BASE64', }])

请求参数

参数必选类型说明image是string图片信息(总数据大小应小于10M),图片上传方式根据image_type来判断。 两张图片通过json格式上传,格式参考表格下方示例image_type是string图片类型 BASE64:图片的base64值,base64编码后的图片数据,编码后的图片大小不超过2M;URL:图片的 URL地址( 可能由于网络等原因导致下载图片时间过长);FACE_TOKEN: 人脸图片的唯一标识,调用人脸检测接口时,会为每个人脸图片赋予一个唯一的FACE_TOKEN,同一张图片多次检测得到的FACE_TOKEN是同一个。face_type否string人脸的类型LIVE表示生活照:通常为手机、相机拍摄的人像图片、或从网络获取的人像图片等,IDCARD表示身份证芯片照:二代身份证内置芯片中的人像照片, WATERMARK表示带水印证件照:一般为带水印的小图,如公安网小图 CERT表示证件照片:如拍摄的身份证、工卡、护照、学生证等证件图片 默认LIVEquality_control否string图片质量控制 NONE: 不进行控制 LOW:较低的质量要求 NORMAL: 一般的质量要求 HIGH: 较高的质量要求 默认 NONEliveness_control否string活体检测控制 NONE: 不进行控制 LOW:较低的活体要求(高通过率 低攻击拒绝率) NORMAL: 一般的活体要求(平衡的攻击拒绝率, 通过率) HIGH: 较高的活体要求(高攻击拒绝率 低通过率) 默认NONE

返回参数

参数名必选类型说明score是float人脸相似度得分face_list是array人脸信息列表+face_token是string人脸的唯一标志

返回示例

{ "score": 44.3, "face_list": [ //返回的顺序与传入的顺序保持一致 { "face_token": "fid1" }, { "face_token": "fid2" } ]}3.6 人脸注册到人脸库功能实现

为了实现保存用户的人脸信息,用于验证人脸请求。一般都是有两种方案:

其一,是我们在自己的后台服务维护一套用户人脸信息库,然后在每次前端请求登入时进行读库操作,同时再调用client.match()方法对用户的登录信息进行比对。这样的做法可以实现高度自定义化,但是维护成本相对较高,主要包括数据的存储和可视化的展示其二,百度SDK平台给我们提供了一套完整的用于维护用户人脸信息库API,而且还以Group分组的形式进行用户数据管理,这就使得对于用户的所归宿的不同组的权限进行区分。同样地,借助组的字段概念可以与业务系统打通,进而更为方便的管理用户。3.6.1 前端代码实现

微信摄像头实时帧的获取与数据处理

要实现小程序端自动采集人脸数据并进行接口验证,就必须使用微信摄像头图像帧数据的采集与监听功能。

官方接口说明如下:

获取 Camera 实时帧数据文档地址

程序中实现思路如下:

1、调用onCameraFrame接口,生成帧数据监听器,然后使用listener.start()启动监听服务。 2、在listen接口中设置一个 setInterVal()时间循环任务,从而实现一个循环获取帧数据并循环上报并处理接口返回数据的任务,保证人脸登录的实时性! 3、特别地,对于获取到的帧数据,仍需要进行处理:将其转为Base64格式数据从而进行数据传输。

代码如下:startFaceCapture(){console.log('=====show==facelogin=====')var that = thisthis.isAuthCamera = truevar i = 1;const context = wx.createCameraContext()console.log('=====load===')const listener = context.onCameraFrame((frame) => {// console.log('==获取帧动画===',that.flag)if (frame && that.flag) {i++;that.frameQueue.push(frame)// console.log('==push任务',that.frameQueue.length)that.flag = false// console.log(i++, frame.data, frame.width, frame.height)}})listener.start({success: function(res) {console.log("开始监听");let task = setInterval(function() {var timeStart = Date.now();//在此处处理store[0](图像的数据);// store.shift();var frame = that.frameQueue.shift()console.log("开始运行===",frame,that.flag);that.flag = true;if(frame != undefined){let pngData = UPNG.encode([frame.data], frame.width, frame.height), base64 = Base64Util.arrayBufferToBase64(pngData)uni.request({url: 'http://127.0.0.1:8099/faceAuth' ,method: 'post',data: {openId:uni.getStorageSync("openId"),base64Img:base64} ,dataType:'json',header: { 'content-type':'application/json'//自定义请求头信息},success:(res)=>{console.log('===result===',res)clearInterval(task)this.$refs.uToast.show({...failTips,complete() {}})},fail:(err)=>{console.log("====执行失败===",err)clearInterval(task)that.isAuthCamera = falseuni.navigateTo({url:'./login'})}})}// if(i==2){// clearInterval(task)// that.isAuthCamera = false// }}, 2000);}})},3.6.1.1 首页登录界面源代码<template><view><view class="content cover" :animation="animationBack"><!-- <view class="bg"></view><view class="bg2"></view><view class="tips"><text class="title">登录</text><text class="subtitle">欢迎再次回来~</text></view><view class="form-box"><view class="btn"style="margin-top:10px;" @click='rotateFn(2)'>密码登录</view><view class="other"><text>找回密码</text><text style="color:#00c6fc;">录入人脸</text></view></view> --><capture ref="faceLogin" @changeLoginMode="rotateFn(2)"></capture></view><view class="content cover" :animation="animationMain"><view class="bg"></view><view class="bg2"></view><view class="tips"><text class="title">登录</text><text class="subtitle">欢迎再次回来~</text></view><view class="form-box"><view class="input-box"><image class="left"src="https://6e69-niew6-1302638010.tcb.qcloud.la/%E7%99%BB%E5%BD%95%E6%A0%B7%E5%BC%8F/%E7%99%BB%E5%BD%959/%E8%B4%A6%E5%8F%B7.png"></image><input placeholder="请输入账号" /><image class="right"src=""></image></view><view class="input-box"><image class="left"src=""></image><input placeholder="请输入密码" /><image class="right"src=""></image></view><view class="btn">登录</view><view class="btn" style="margin-top:10px;" @click='login()'>刷脸登录</view><view class="other"><text>找回密码</text><text style="color:#00c6fc;">快速注册</text></view></view></view></view></template><script>import capture from './capture.vue'export default {components: {capture},data() {return {animationMain: null, //正animationBack: null, //反}},methods: {rotateFn(e) {this.animation_main = uni.createAnimation({duration: 400,timingFunction: 'linear'})this.animation_back = uni.createAnimation({duration: 400,timingFunction: 'linear'})// 点击正面if (e == 1) {this.animation_main.rotateY(180).step()this.animation_back.rotateY(0).step()this.animationMain = this.animation_main.export()this.animationBack = this.animation_back.export()this.$refs.faceLogin.startFaceCapture()} else {this.animation_main.rotateY(0).step()this.animation_back.rotateY(-180).step()this.animationMain = this.animation_main.export()this.animationBack = this.animation_back.export()}},login() {var that = this;if (uni.getStorageSync("openId") == undefined) {wx.login({success(res) {console.log('===触发登录====', res)if (res.code) {uni.request({url: 'http://127.0.0.1:8000/miniapp/faceEngine/login/' + res.code,method: 'get',dataType: 'json',success: (res) => {console.log("====执行成功===", res)that.rotateFn(1)uni.setStorageSync("authed", true)uni.setStorageSync("openId", res.data.openid)},fail: (err) => {console.log("====执行失败===", err)}})} else {console.log('登录失败!')}}})} else {that.rotateFn(1)}},}}</script><style lang="scss">page {margin: 0;padding: 0;min-height: 100vh;position: relative;background-color: rgb(118, 218, 255);overflow: hidden;}page::before,page::after {content: '';position: absolute;top: 90vh;min-width: 300vw;min-height: 300vw;background-color: #76daff;animation: rote 10s linear infinite;}page::before {left: -95%;border-radius: 45%;opacity: .5;}page::after {left: -95%;border-radius: 46%;}@keyframes rote {from {transform: rotateZ(0);}to {transform: rotateZ(360deg);}}.cover {position: absolute;top: 0;left: 0;}.content {width: 100vw;height: 100vh;background-color: #ffffff;transition: all 1s;backface-visibility: hidden;.tips {padding-top: 200rpx;padding-left: 80rpx;display: flex;flex-direction: column;.title {line-height: 70rpx;font-weight: bold;font-size: 50rpx;}.subtitle {line-height: 70rpx;font-size: 35rpx;font-weight: bold;color: #b0b0b1;}}.bg {position: fixed;top: -250rpx;right: -250rpx;width: 600rpx;height: 600rpx;border-radius: 100%;background-color: #00baef;z-index: 2}.bg2 {position: fixed;top: -150rpx;right: -300rpx;width: 600rpx;height: 600rpx;border-radius: 100%;background-color: #ade8f9;z-index: 1;}.form-box {padding-top: 180rpx;padding-left: 70rpx;width: 610rpx;.input-box {margin: 40rpx 0;display: flex;justify-content: flex-start;align-items: center;height: 100rpx;background-color: #f5f5f5;border-radius: 100rpx;width: 100%;input {flex: 1;height: 100%;font-size: 30rpx;}.left {padding: 0 30rpx;width: 35rpx;height: 35rpx;}.right {padding: 0 30rpx;width: 40rpx;height: 40rpx;}}.btn {display: flex;justify-content: center;align-items: center;width: 100%;height: 100rpx;border-radius: 100rpx;color: #FFFFFF;background: linear-gradient(to right, #00c6fc, #9adcf1);}.other {display: flex;justify-content: space-between;text {line-height: 80rpx;font-size: 28rpx;}}}}</style>3.6.1.2人脸采集界面代码<template><view class="page-content"><view class="containerV"><!-- 标题 --><view class="headerV"><view class="top-tips1"><view>{{tipsText}}</view></view></view><u-toast ref="uToast"></u-toast><!-- 拍摄区域 --><view class="contentV"><view class="mark"></view><image class="image" v-if="tempImg" mode="widthFix" :src="tempImg" /><camera v-if='isAuthCamera' device-position="front" class="camera" flash="off" resolution='high' /></view><!-- 操作区域 --><view class="footerV"><view style="width: 100%;"><view v-if="!tempImg" style="width: 100%;"><view class="take-photo-bgV"><!-- 图片上传 --><view v-show="true" class="btn-change-upload" @click="handleChooseImage" /><!--拍照--><view class="btn-take-photo" @click="handleTakePhotoClick" /><!-- 切换镜头 --><view class="btn-change-camera" @click="handleChangeCameraClick" /></view></view><view class="confirmV" v-else><view class="btn-cancel" @click="handleCancelClick">取消</view><view class="btn-ok" @click="handleOkClick">确定</view></view></view></view></view></view></template><script>// import crudFace from '@/api/face.js'import Base64Util from '@/util/Base64Util.js'import UPNG from '@/util/UPNG.js'export default {components: {},data() {return {frameQueue: [],flag: false,tipsText: '请将脸部移入框内', // 错误文案提示tempImg: '', // 本地图片路径cameraEngine: null, // 相机引擎devicePosition: true, // 摄像头朝向isAuthCamera: false, // 是否拥有相机权限cameraListen: '',failTips: {type: 'error',message: "请勿遮挡人脸!",iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/error.png'},successTips: {type: 'success',message: "识别成功!",iconUrl: 'https://www.yuucn.com/wp-content/uploads/2023/04/1681863493-92ddda8be70d273.png'}};},created() {},onLoad() {// this.init();const context = wx.createCameraContext()console.log('=====load===')const listener = context.onCameraFrame((frame) => {console.log(frame.data instanceof ArrayBuffer, frame.width, frame.height)})this.cameraListen = listener// listener.start()},onShow() {console.log('=====show===', )},methods: {startFaceCapture(){console.log('=====show==facelogin=====')var that = thisthis.isAuthCamera = truevar i = 1;const context = wx.createCameraContext()console.log('=====load===')const listener = context.onCameraFrame((frame) => {// console.log('==获取帧动画===',that.flag)if (frame && that.flag) {i++;that.frameQueue.push(frame)// console.log('==push任务',that.frameQueue.length)that.flag = false// console.log(i++, frame.data, frame.width, frame.height)}})listener.start({success: function(res) {console.log("开始监听");let task = setInterval(function() {var timeStart = Date.now();//在此处处理store[0](图像的数据);// store.shift();var frame = that.frameQueue.shift()console.log("开始运行===",frame,that.flag);that.flag = true;if(frame != undefined){let pngData = UPNG.encode([frame.data], frame.width, frame.height), base64 = Base64Util.arrayBufferToBase64(pngData)// that.$refs.uToast.show({// ...that.successTips,// complete() {// }// })// clearInterval(task)// setTimeout(function(){//  uni.navigateTo({// url:'./home' // })// },1000)uni.request({url: 'http://127.0.0.1:8099/faceAuth' ,method: 'post',data: {openId:uni.getStorageSync("openId"),base64Img:base64} ,dataType:'json',header: { 'content-type':'application/json'//自定义请求头信息},success:(res)=>{console.log('===result===',res)clearInterval(task)this.$refs.uToast.show({...failTips,complete() {}})},fail:(err)=>{console.log("====执行失败===",err)clearInterval(task)that.isAuthCamera = falseuni.navigateTo({url:'./login'})}})}// if(i==2){// clearInterval(task)// that.isAuthCamera = false// }}, 2000);}})},handleChangeCameraClick() { // 切换设备镜头this.devicePosition = !this.devicePosition;this.$emit('changeLoginMode')},handleChooseImage() { // 图片上传uni.chooseImage({count: 1,sizeType: ['original', 'compressed'],sourceType: ['album'],success: (res) => {if (res.errMsg === 'chooseImage:ok') {this.handleOkClick(res.tempFilePaths[0])}},fail: (res) => {},});},handleTakePhotoClick() { // 拍照点击listener.stop()console.log('===to TaskPhoto====')if (this.tipsText != "" && this.tipsText != "请拍照") {return;}uni.getSetting({success: (res) => {if (!res.authSetting['scope.camera']) {this.isAuthCamera = falseuni.openSetting({success: (res) => {if (res.authSetting['scope.camera']) {this.isAuthCamera = true;}}})}}})this.cameraEngine.takePhoto({quality: "high",success: ({tempImagePath}) => {this.handleOkClick(tempImagePath)}})},async handleOkClick(filePath) { // 点击确定上传uni.showLoading({title: '上传中...',mask: true})let img = await this.$util.uploadopt.image(filePath, 2)uni.$emit('onface', img);uni.navigateBack();},handleCancelClick() { // 点击 - 取消上传this.tempImg = ''},}}</script><style lang="scss">page {height: 100%;width: 100%;}.page-content {width: 100%;height: 100%;.containerV {width: 100%;height: 100%;display: flex;flex-direction: column;/* 标题 */.headerV {padding: 163rpx 0 56rpx;text-align: center;.top-tips1 {color: #333333;font-size: 42rpx;}}/* 拍摄区域 */.contentV {position: relative;display: flex;flex-direction: column;align-items: center;justify-content: center;width: 564rpx;height: 564rpx;border-radius: 50%;margin: 0 auto;border: 10rpx solid #1568E0;background-color: #d8d8d8;.camera {width: 100%;height: 100%;border-radius: 50%;}.mark {position: absolute;left: 0;top: 0;z-index: 1;width: 100%;height: 100%;border-radius: 50%;}.image {position: absolute;width: 100%;height: 100%;z-index: 3;border-radius: 50%;}}/* 操作按钮 */.footerV {width: 100%;flex-grow: 1;display: flex;flex-direction: row;align-items: center;justify-content: center;.privacyV {padding-top: 30rpx;display: flex;flex-direction: row;align-items: center;justify-content: center;.text {font-size: 30rpx;color: #1C1C1C;text-align: center;line-height: 42rpx;margin-left: 15rpx;text {font-size: 30rpx;color: #00AAFF;text-align: center;line-height: 42rpx;}}}.bottom-tips-2 {margin-top: 20rpx;color: #999999;text-align: center;font-size: 26rpx;}.take-photo-bgV {width: 100%;margin-top: 30rpx;display: flex;flex-direction: row;align-items: center;justify-content: center;// 由于左边没有按钮,所以左边要便宜更大,以便是拍照按钮居中.btn-take-photo {margin: 0rpx 80rpx 0rpx 80rpx;width: 196rpx;height: 196rpx;background: url("https://www.hujinqiang.com/anjiantong/face/photo.png") no-repeat;background-size: 100% auto;}.btn-change-upload {left: 130rpx;width: 80rpx;height: 80rpx;background: url("https://www.yuucn.com/wp-content/uploads/2023/04/1681863499-92ddda8be70d273.png") no-repeat;background-size: 100% auto;}.btn-change-camera {right: 130rpx;width: 80rpx;height: 80rpx;background: url("https://www.yuucn.com/wp-content/uploads/2023/04/1681863505-92ddda8be70d273.png") no-repeat;background-size: 100% auto;}}.confirmV {margin: 200rpx 100rpx 0rpx 100rpx;display: flex;flex-direction: row;align-items: center;justify-content: space-between;.btn-cancel {font-size: 32rpx;color: #1C1C1C;}.btn-ok {font-size: 32rpx;color: #00AAFF;}}}}}</style>3.6.1.3 个人中心界面代码<template><view><!-- #ifndef H5 --><view class="ns">我的账户</view><!-- #endif --><view class="flexView"><view class="scrollView"><view class="head-read"><view class="flex"><image class="read-img" :src="userData.headimgurl" mode="aspectFill" /><view class="flex-box"><view class="flex-box-text">姓名:{{ userData.name }}({{ userData.id }})</view><view class="flex-box-text">手机号:{{ userData.phone }}</view></view><view class="arrow arrow-one" @click="showModal = true"><span>名词解释</span></view></view></view><view class="white-box"><view class="tx"><view class="tx-grid"><view class="tx-grid-text"><view class="title">可提现余额</view><view class="money"><text>{{ userData.withdrawable }}</text><text class="money-b">元</text></view></view></view><view class="tx-grid" @click="navTo('/pages/withdraw/index')"><span class="tx-grid-comm-sign">立即提现</span></view></view><view class="palace palace-one"><view class="palace-grid"><view class="palace-grid-text"><view class="palace-grid-text-data"><text>{{ userData.coming }}</text><text class="palace-grid-text-data-b">元</text></view><view class="palace-grid-text-name">即将到账</view></view></view><view class="palace-grid"><view class="palace-grid-text"><view class="palace-grid-text-data"><text>{{ userData.came }}</text><text class="palace-grid-text-data-b">元</text></view><view class="palace-grid-text-name">累计到账</view></view></view><view class="palace-grid"><view class="palace-grid-text"><view class="palace-grid-text-data"><text>{{ userData.withdrawed }}</text><text class="palace-grid-text-data-b">元</text></view><view class="palace-grid-text-name">累计提现</view></view></view></view></view><view class="top"><tui-tabs:tabs="tabs":height="88":currentTab="currentTab":sliderWidth="150":sliderHeight="60"bottom="50%"color="#888"selectedColor="#fff"sliderBgColor="#ff8a4a"@change="changeTab"></tui-tabs></view><view class="list-view"><view class="list-item" v-for="(item, index) in list" :key="index" hover-class="hover" :hover-stay-time="150" bindtap="detail"><view class="content-box"><view class="des-box"><view class="tit">{{ currentTab == 3 ? '流水号:' + item.extract_no : '订单号:' + item.order_no }}</view><view v-if="currentTab == 3" class="source" :style="{ color: item.status == 1 ? '#4caf50' : item.status == 2 ? '#ff1e0f' : '#00b7ff' }">提现{{ item.status == 1 ? '成功' : item.status == 2 ? '失败' : '处理中' }}</view><view class="time">{{ item.create_time }}</view></view></view><view class="money" :class="{ less: is_withdraw }">{{ is_withdraw ? '-' : '+' }}{{ currentTab == 3 ? item.real_money : item.money }}</view></view></view><view class="tip">仅显示近半年内的收支记录</view></view><view class="cu-modal" :class="showModal ? 'show' : ''"><view class="cu-dialog"><view class="cu-bar bg-white justify-end"><view class="content">名词解释</view><view class="action" @tap="showModal = false"><text class="cuIcon-close text-red"></text></view></view><view class="padding-xl" style="text-align: left;"><view><text class="text-red">可提现余额:</text><text>当前您可以提现的金额</text></view><view class="margin-top-sm"><text class="text-red">即将到账:</text><text>交易中的金额,交易成功后可提现</text></view><view class="margin-top-sm"><text class="text-red">累计到账:</text><text>累计交易成功的金额</text></view><view class="margin-top-sm"><text class="text-red">累计提现:</text><text>累计提现成功的金额</text></view><view class="margin-top-sm"><text class="text-red">*注:所有金额币种均为人民币,单位为元,符号¥</text></view></view><view class="cu-bar bg-white justify-end"><view class="action"><button class="cu-btn bg-green margin-left" @tap="showModal = false">我已知晓</button></view></view></view></view></view></view></template><script>import tuiTabs from '@/components/tui-tabs/tui-tabs';export default {components: {tuiTabs},data() {return {is_withdraw: false,list: [],userData: {name:'陶人',id:12,phone:18648759961,withdrawable:98989,coming:288,came:770,withdrawed:8888289},showModal: false,date: 'incomeMonth',currentTab: 0,tabs: [{name: '本月收入'},{name: '今日收入'},{name: '昨日收入'},{name: '提现记录'}]};},onLoad() {this.$api.loading(true);this.loadData();setTimeout(() => {this.$api.loading(false);}, 500);},methods: {async loadData() {this.userData = await this.$api.json('userData');this.list = await this.$api.json('incomeMonth');},async getFundList() {if (this.currentTab == 3) {this.list = await this.$api.json('extractList');} else {this.list = await this.$api.json(this.date);}},changeTab(e) {this.currentTab = e.index;this.list = [];if (this.currentTab == 3) {this.is_withdraw = true;} else if (this.currentTab == 0) {this.date = 'incomeMonth';this.is_withdraw = false;} else if (this.currentTab == 1) {this.date = 'incomeToday';this.is_withdraw = false;} else if (this.currentTab == 2) {this.date = 'incomeYesterday';this.is_withdraw = false;}this.$api.loading(true);this.getFundList();setTimeout(() => {this.$api.loading(false);}, 500);},navTo(url) {uni.navigateTo({url});}},onPullDownRefresh() {this.loadData();setTimeout(function() {uni.stopPullDownRefresh();}, 500);}};</script><style lang="scss" scoped>page {background-color: #fff;}.ns {width: 100%;height: 60px;text-align: center;line-height: 200rpx;color: white;font-size: 34rpx;font-weight: bold;// background: linear-gradient(to right, #ff8440, #ff1e0f);background: linear-gradient(to right, #7CF7FF , #4B73FF );}.top {margin-top: 20rpx;}.flexView {width: 100%;height: 100%;margin: 0 auto;display: flex;flex-direction: column;.scrollView {width: 100%;height: 100%;flex: 1;overflow-y: auto;overflow-x: hidden;position: relative;padding-bottom: 116rpx;.head-read {// background: linear-gradient(to right, #ff8440, #ff1e0f);background: linear-gradient(to right, #7CF7FF , #4B73FF );background-color: #4B73FF;padding-bottom: 100rpx;.flex {display: flex;align-items: center;padding: 50rpx;position: relative;.read-img {width: 120rpx;height: 120rpx;border-radius: 100%;overflow: hidden;margin-right: 20rpx;border: 4rpx solid rgba(255, 255, 255, 0.3);}.flex-box {flex: 1;min-width: 0;font-size: 26rpx;color: #333;&-text {margin: 10rpx 0;color: #f5f5f5;font-weight: normal;}}.arrow {position: relative;padding-right: 30rpx;span {font-size: 28rpx;color: white;}&:after {content: ' ';display: inline-block;height: 12rpx;width: 12rpx;border-width: 4rpx 4rpx 0 0;border-color: #848484;border-style: solid;transform: matrix(0.71, 0.71, -0.71, 0.71, 0, 0);position: relative;top: -4rpx;position: absolute;top: 50%;margin-top: -8rpx;right: 4rpx;border-radius: 2rpx;}}.arrow-one:after {border-color: white;margin-top: -6rpx;}}}.white-box {width: 94%;background: white;border-radius: 10rpx;margin: -120rpx auto 20rpx;box-shadow: 0 6rpx 20rpx #e7e7e7;.tx {padding-top: 26rpx;overflow: hidden;display: flex;justify-content: space-between;align-content: center;&-grid {box-sizing: border-box;&:first-child {margin-left: 40rpx;}&-comm-sign {display: block;border-radius: 40rpx 0 0 40rpx;font-size: 26rpx;padding: 16rpx 44rpx;background: linear-gradient(to right, #fef082, #ffc551);background-color: #fef082;color: #4B73FF;}&-text {display: block;color: #333;font-size: 26rpx;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;.title {font-size: 26rpx;font-weight: normal;color: #ff6423;}.money {font-size: 60rpx;color: #ff6423;letter-spacing: 2rpx;margin-bottom: 10rpx;&-b {font-size: 28rpx;}}}}}.palace {padding-bottom: 20rpx;overflow: hidden;display: flex;justify-content: center;&-grid {flex: 1;position: relative;box-sizing: border-box;&:not(:last-child) {&:after {width: 1rpx;height: 80rpx;background: #fddece;content: ' ';display: inline-block;position: absolute;top: 0;right: 0;}}&-text {display: block;text-align: center;color: #333;font-size: 32rpx;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;&-name {font-size: 26rpx;font-weight: normal;color: #ff8a4a;}&-data {font-size: 32rpx;color: #ff8a4a;letter-spacing: 2rpx;margin-bottom: 5rpx;&-b {font-size: 20rpx;}}}}}}}}.list-view {position: relative;width: 100%;overflow: hidden;}.list-item {width: 100%;padding: 30rpx 28rpx;box-sizing: border-box;background: #fff;display: flex;align-items: flex-start;justify-content: space-between;border-bottom: 1rpx solid #eaeef1;}.item-last::after {left: 0 !important;}.content-box {display: flex;align-items: flex-start;justify-content: space-between;}.des-box {min-height: 80rpx;padding-left: 28rpx;box-sizing: border-box;vertical-align: top;color: #333;font-size: 24rpx;display: flex;flex-direction: column;justify-content: space-between;}.tit {font-size: 32rpx;max-width: 420rpx;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}.source {margin: 12rpx 0;}.time {color: #888;}.money {font-size: 38rpx;font-weight: 500;color: #ff1e0f;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding-left: 20rpx;}.less {color: #4caf50 !important;}.tip {margin-top: 50rpx;display: flex;justify-content: center;align-content: center;font-size: 24rpx;color: #888;}</style>3.6.2 后端代码实现from flask import Flask, jsonify, requestimport re,osfrom aip import AipFacebasedir = os.path.abspath(os.path.dirname(__file__)) # 定义一个根目录 用于保存图片用import base64from io import BytesIOfrom PIL import ImageimageType = "BASE64"""" 你的 APPID AK SK """APP_ID = '***'API_KEY = '***'SECRET_KEY = '***'client = AipFace(APP_ID, API_KEY, SECRET_KEY)app = Flask(__name__)@app.route('/faceRegister', methods=['GET', 'POST'])def faceRegister(): # 获取图片文件 name = upload user_data = request.get_json() print('==user--data==',user_data['base64Img']) image = user_data['base64Img'].split(',')[1] userId = user_data['openId'] # 将base64字符串转换为图像对象 img_data = base64.b64decode(user_data['base64Img'].split(',')[1]) img = Image.open(BytesIO(img_data)) # 将图像对象保存为文件 img.save('face.png') """ 调用人脸检测 : 校验摄像头中是否检测到人脸 """ detect_res = client.detect(image, imageType) print(detect_res) if detect_res['error_code'] == 222203 : return jsonify({"code": 101, "data": "无法解析人脸", "msg": "验证失败"}) if detect_res['face_num'] != 0 : return jsonify({"code": 101, "data": "解析人脸失败!", "msg": "验证失败"}) groupId = "vip" """ 调用人脸注册 : 将人脸数据注册到人脸库中 """ client.addUser(image, imageType, groupId, userId); """ 调用人脸搜索 """ client.search(image, imageType, groupId); print(detect_res['face_list'][0]['quality']['occlusion']) return detect_res@app.route('/faceAuth', methods=['GET', 'POST'])def faceAuth(): user_data = request.get_json() groupId = "vip" image = user_data['base64Img'].split(',')[1] userId = user_data['openId'] options = {} options["user_id"] = userId """ 调用人脸搜索 """ auth_result = client.search(image, imageType, groupId,options) # { # "face_token": "fid", # "user_list": [ # { # "group_id": "test1", # "user_id": "u333333", # "user_info": "Test User", # "score": 99.3 # } # ] # } if len(auth_result['user_list'])>0: return jsonify({"code": 200, "msg": "登录成功!"}) else: return jsonify({"code": 102, "msg": "用户尚未注册!"})if __name__ == '__main__': app.run(host="0.0.0.0", port=int("8099"), debug=True)四、推荐阅读

🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :

《小程序开发必备功能的吐血整理【个人中心界面样式大全】》《微信小程序 | 动手实现双十一红包雨》《微信小程序 | 人脸识别的最终解决方案》《来接私活吧?小程序接私活必备功能-婚恋交友【附完整代码】》《吐血整理的几十款小程序登陆界面【附完整代码】》
本文链接地址:https://www.jiuchutong.com/zhishi/297537.html 转载请保留说明!

上一篇:个人简历html网页代码(使用chatgpt完成web开发课的实验)(个人简历html网页代码含效果图)

下一篇:uniapp中使用mock(uniapp中使用amap-vue,设置安全密钥)

  • 浅析企业品牌推广的方法(企业品牌推广方式有哪些)

    浅析企业品牌推广的方法(企业品牌推广方式有哪些)

  • ppa-al20是华为什么型号(ppaal20是华为什么型号手机多少钱)

    ppa-al20是华为什么型号(ppaal20是华为什么型号手机多少钱)

  • 戴尔笔记本无线开关怎么打开(戴尔笔记本无线鼠标怎么连接)

    戴尔笔记本无线开关怎么打开(戴尔笔记本无线鼠标怎么连接)

  • word翻译功能用不了(word中翻译工具怎么使用)

    word翻译功能用不了(word中翻译工具怎么使用)

  • 充电宝充到80就不进电(充电宝充到80就不充了)

    充电宝充到80就不进电(充电宝充到80就不充了)

  • 苹果手机闪烁灯怎么关闭(苹果手机闪烁灯关闭)

    苹果手机闪烁灯怎么关闭(苹果手机闪烁灯关闭)

  • 错误代码1001是什么意思(错误代码1001是什么)

    错误代码1001是什么意思(错误代码1001是什么)

  • 微信怎么申请健康二维码(微信怎么申请健康吗?)

    微信怎么申请健康二维码(微信怎么申请健康吗?)

  • 华为artal00x是什么型号

    华为artal00x是什么型号

  • 手机视频源格式错误怎么解决(手机视频源格式错误怎么办)

    手机视频源格式错误怎么解决(手机视频源格式错误怎么办)

  • 苹果为什么不能打开旁白(苹果为什么不能下载软件了)

    苹果为什么不能打开旁白(苹果为什么不能下载软件了)

  • 如何共享手机流量(如何共享手机流量给电脑)

    如何共享手机流量(如何共享手机流量给电脑)

  • iphone6充电插上没反应(苹果6splus插上充电器不充电)

    iphone6充电插上没反应(苹果6splus插上充电器不充电)

  • 美团会员买一赠一什么意思(美团外卖会员赠送)

    美团会员买一赠一什么意思(美团外卖会员赠送)

  • 拼多多复活卡作用(拼多多印钞机复活卡)

    拼多多复活卡作用(拼多多印钞机复活卡)

  • 手机怎么做推文(手机怎么写推文)

    手机怎么做推文(手机怎么写推文)

  • 华为手机时钟怎么设置24小时制(华为手机时钟怎么调到桌面)

    华为手机时钟怎么设置24小时制(华为手机时钟怎么调到桌面)

  • linux最早是由计算机爱好者谁开发的(linux最早是由计算机爱好者( )开发的英语)

    linux最早是由计算机爱好者谁开发的(linux最早是由计算机爱好者( )开发的英语)

  • 12reads购买的是纸质书吗(12reads没有免费资源吗)

    12reads购买的是纸质书吗(12reads没有免费资源吗)

  • 拼多多砍价怎么面对面砍(拼多多砍价怎么没有了)

    拼多多砍价怎么面对面砍(拼多多砍价怎么没有了)

  • 微信测试版是怎么回事(微信测试版怎么弄)

    微信测试版是怎么回事(微信测试版怎么弄)

  • word如何删除分节符(word如何删除分页符(下一页))

    word如何删除分节符(word如何删除分页符(下一页))

  • 小米6拍照如何开启虚化(小米拍照如何显示地理位置)

    小米6拍照如何开启虚化(小米拍照如何显示地理位置)

  • 琥珀山国家公园里的豹变色龙,马达加斯加 (© Christian Ziegler/Minden Pictures)(琥珀山庄位于我国哪个省)

    琥珀山国家公园里的豹变色龙,马达加斯加 (© Christian Ziegler/Minden Pictures)(琥珀山庄位于我国哪个省)

  • Vue实现生成二维码(vue生成二维码分享)

    Vue实现生成二维码(vue生成二维码分享)

  • Python中的进程池是什么(python 进程管理)

    Python中的进程池是什么(python 进程管理)

  • 领用库存商品用于固定资产
  • 银行本票与银行本票存款的区别
  • 服装类发票可以做账吗
  • 报销用专票
  • 个人所得税如果两份工作怎么扣
  • 购买方怎么写分录
  • 小规模申请自开专票
  • 房地产企业会计制度
  • 土地使用税怎么征收标准
  • 吸收合并控股合并新设合并的区别
  • 负数发票跨月怎么重开
  • 政府电费补贴文件
  • 房地产预缴增值税是含税还是不含税
  • 企业如何申请定增资金
  • 公司奖励旅游算休年假吗
  • 餐饮外卖的经营范围是什么项目
  • 应交增值税下面有几个科目
  • 应付票据属于什么类账户
  • 高速公路通行费抵扣最新规定
  • 公司公章丢失登报后又找到了
  • 什么情况下要交增值税
  • 出差补贴怎么算
  • 用户登录系统后首先进入什么
  • window如何打开控制台
  • 苹果电脑mac设备在哪里
  • 事业单位非税收入怎么做账
  • 资产负债表中资产等于什么
  • vue实战项目教程
  • elementui能做什么
  • 2022年苹果iphone14视频配音乐
  • 交接目录excel
  • 安卓车机系统开发
  • slee401.exe - slee401是什么进程 有什么用
  • 补缴的土地出让金需要计提吗
  • 一个非常有用的工具用英语怎么说
  • 出差有补贴
  • 带着崽崽宠老公免费阅读
  • 申请专利费用计入哪个科目
  • vue3.0中的ref
  • node实战
  • 新设立的企业如何办理开业税务登记
  • mysql的文件格式有哪些
  • SqlServer与MongoDB结合使用NHibernate
  • 紫白择日法实例详解
  • 产权转移数据印花税纳税期限
  • 公司能经营烟草公司吗
  • 产业增加值是增长量吗
  • 综合所得减除费用标准
  • 什么叫金税四期呢?
  • 设备维修三种形式
  • 支付境外货款需要缴纳哪些税费
  • 个体工商户怎么注册
  • 增值税明细账怎么结账
  • 扣非净利润占比多少合理
  • 保险赔偿收入如何减税额
  • 外地预缴需要缴纳印花税吗
  • 实收资本实际缴纳要去税务局备案吗
  • 开发票时如何添加商品编码?
  • 住宿费报账怎么写
  • mysql exists与not exists实例详解
  • bitronix 连接 MySQL 出现MySQLSyntaxErrorException 的解决方法
  • winxp系统如何设置禁用磁盘检测功能
  • 进程管理界面
  • windows8禁用uac
  • centos7如何设置中文
  • win10系统小娜不见了
  • macbook调节音量怎么没反应
  • linux sl
  • rdesktop命令
  • vim如何复制粘贴
  • linux rsyslogd
  • cocos2dx-js
  • 创业要看的书
  • jquery用什么编写
  • arraylist100扩充几次
  • js实现组件功能
  • python仿站软件官网
  • 国家税务总局2012年20号公告
  • 应缴财政专户款属于资产类吗
  • 国企残疾职工安置
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设