uni-app项目+云函数+百度AI(人脸识别签到)

云函数方面 

打开uniclould控制台数据库为项目建表

        face_config 百度AI人脸识别配置表 

        userInfo 用户信息配置表 (人脸注册时需要唯一的用户id索引,所以建个表来自动生成注册用户的id)

face_config表结构

userInfo表结构

在项目创建的云函数列表内新建名为 face 的云函数

在face文件夹处鼠标右键使用命令窗口打开所在目录输入以下命令安装依赖

npm i request -save
npm i request-promise -save

face/index.js

'use strict';
//链接数据库
const db = uniCloud.database()
//引入request模块
const rq = require("request-promise")
//声明百度AI配置表
const Bai_Ai = db.collection('face_config')
//用户列表
const user_info = db.collection('userInfo')
exports.main = async (event, context) => {
	//查询数据库中 百度AI配置信息
	let Bai_Ai_data =( await Bai_Ai.get()).data[0]
	//启动参数  type  get 获取人脸信息供录入  signin 人脸注册
	let type=event.type
	//判断百度AI前面是否存在
	if(Bai_Ai_data.face_Access_Token.length>0){
		//人脸检测
		if(event.type=='get'){
			return new Promise((resolve,reject)=>{
				var options = {
				        'method': 'POST',
				        'url': 'https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=' + Bai_Ai_data.face_Access_Token ,
				        'headers': {
				                'Content-Type': 'application/json'
				        },
				        body: JSON.stringify({
				                "image": event.face_image.substring(23),
				                "image_type": "BASE64",
				                "face_field": "quality",
				        })
				};
				rq(options).then(res=>{
					//是否检测到人脸
					if(JSON.parse(res).error_msg=='SUCCESS'){
						//人脸是否完整
						if(JSON.parse(res).result.face_list[0].quality.completeness){
							//阈值判断+提示
							//左眼
							let left_eye=JSON.parse(res).result.face_list[0].quality.occlusion.left_eye
							//右眼
							let right_eye=JSON.parse(res).result.face_list[0].quality.occlusion.right_eye
							//鼻子
							let nose=JSON.parse(res).result.face_list[0].quality.occlusion.nose
							//嘴巴
							let mouth=JSON.parse(res).result.face_list[0].quality.occlusion.mouth
							//左脸
							let left_cheek=JSON.parse(res).result.face_list[0].quality.occlusion.left_cheek
							//右脸
							let right_cheek=JSON.parse(res).result.face_list[0].quality.occlusion.right_cheek
							//下巴
							let chin_contour=JSON.parse(res).result.face_list[0].quality.occlusion.chin_contour
							//图片质量可以
							if(left_eye<=0.6&&right_eye<=0.6&&nose<=0.7&&mouth<=0.7&&left_cheek<=0.8&&right_cheek<=0.8&&chin_contour<=0.6){
								resolve(
									{	
										code:'200',
										image:event.face_image
									}
								)
							}else{
								if(left_eye>0.6){
									resolve(
										{
											code:'400',
											message:'左眼被遮挡'
										}
									)
								}else if(right_eye>0.6){
									resolve(
										{
											code:'400',
											message:'右眼被遮挡'
										}
									)
								}else if(nose>0.7){
									resolve(
										{
											code:'400',
											message:'鼻子被遮挡'
										}
									)
								}else if(mouth>0.7){
									resolve(
										{
											code:'400',
											message:'嘴巴被遮挡'
										}
									)
								}else if(left_cheek>0.8){
									resolve(
										{
											code:'400',
											message:'左脸被遮挡'
										}
									)
								}else if(right_cheek>0.8){
									resolve(
										{
											code:'400',
											message:'右脸被遮挡'
										}
									)
								}else if(chin_contour>0.6){
									resolve(
										{
											code:'400',
											message:'下巴被遮挡'
										}
									)
								}
							}
						}else{
							resolve(
								{
									code:'400',
									message:'未检测到人脸'
								}
							)
						}
					}else{
						//未检出人脸  反馈前端
						resolve( 
							{
								code:'400',
								message:'未检测到人脸q',
							}
						)
					} 
				})
			})
		}
		//人脸注册
		if(event.type=='signin'){
			//加入人脸库
			//数据库注册用户信息 获取id
			return new Promise((resolve,reject)=>{
				//判断是否存在此人
				user_info.where({name:event.name}).get().then(res=>{
					if(res.data.length==0){
						user_info.add({name:event.name}).then(res=>{
							var _user_info_={
								name:event.name
							}
							 var options = {
									'method': 'POST',
									'uri': 'https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=' + Bai_Ai_data.face_Access_Token,
									'headers': {
											'Content-Type': 'application/json'
									},
									body: JSON.stringify({
											"group_id": "yj_face_arr",
											"image": event.face_image.substring(23),
											"image_type": "BASE64",
											"user_id": res.id,//必填
											"user_info":JSON.stringify(_user_info_)
									})
								};
								rq(options).then(res=>{
									resolve(
										{
											code:'200',
											message:'人脸注册成功'
										}
									) 
								})
						})	
						
					}else{
						resolve(
							{
								code:'400',
								message:'此用户已存在'
							}
						)
					}
				})
				
				
			})
				
			
		}
		//人脸 1:N 搜索
		if(event.type=='comparison'){
			return new Promise((resolve)=>{
				var options = {
				        'method': 'POST',
				        'url': 'https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=' + Bai_Ai_data.face_Access_Token,
				        'headers': {
				                'Content-Type': 'application/json'
				        },
				        body: JSON.stringify({
				                "group_id_list": "yj_face_arr",
								"image": event.face_image.substring(23),
				                "image_type": "BASE64"
				        })
				}
				rq(options).then(res=>{
					
					resolve(
						{
							code:'200',
							message:'人脸匹配成功',
							user_info:JSON.parse( JSON.parse(res).result.user_list[0].user_info )
						}
					) 
				})
				
			})
		}	
		
	}else{
		//不存在  生成签名
		console.log('签名不存在')
		var options = {
		        'method': 'POST',
		        'url': 'https://aip.baidubce.com/oauth/2.0/token?client_id='+Bai_Ai_data.face_API_Key+'&client_secret='+Bai_Ai_data.face_Secret_Key+'&grant_type=client_credentials',
		        'headers': {
		                'Content-Type': 'application/json',
		                'Accept': 'application/json'
		        }
		};
		rq(options).then(res=>{
			console.log(JSON.parse(res).access_token)
			//签名存入数据表
			Bai_Ai.doc('657bbf51652341901ba0e89b').update({
				'face_Access_Token':JSON.parse(res).access_token
			})
		})
	}
	
};

百度AI方面

开通人脸识别服务---应用列表--创建应用

可视化人脸库---新建用户组yj_face_arr

将应用的信息填入第一步创建好的数据表中  Access_token 为云函数内部生成并填入 

前端方面

pages文件下创建文件夹

face/new_file.nvue    

<template>
	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
	        <view class="preview" :style="{ width: windowWidth, height: windowHeight-80}">
	            <live-pusher id="livePusher" ref="livePusher" class="livePusher" mode="FHD" beauty="1" whiteness="0"
	                min-bitrate="1000" audio-quality="16KHz" :auto-focus="true" :muted="true"
	                :enable-camera="true" :enable-mic="false" :zoom="false" orientation="horizontal" @statechange="statechange"
	                :style="{ width: cameraWidth, height: cameraHeight }"></live-pusher>
	
	            <!--提示语-->
	            <cover-view class="remind">
	                <text class="remind-text" style="">{{ message }}</text>
	            </cover-view>
	
	            <!--辅助线-->
	            <cover-view class="outline-box" >
	                <cover-image class="outline-img" :style="{width: windowWidth+20, height: windowHeight+150}" src="../../static/face2.png"></cover-image>
	            </cover-view>
	    </view>
	</view>
</template>

<script>
	import { pathToBase64, base64ToPath } from 'image-tools'
    export default {
        data() {
            return {
				//启动参数
				type:'',
                //提示
                message: '',
                //相机画面宽度
                cameraWidth: '',
                //相机画面宽度
                cameraHeight: '',
                //屏幕可用宽度
                windowWidth: '',
                //屏幕可用高度
                windowHeight: '',
                //流视频对象
                livePusher: null,
                //照片
                snapshotsrc: null,
                ifPhoto: false,
            };
        },
        onLoad(e) {
            //获取屏幕高度
            this.initCamera();
			this.type=e.type
        },
        onReady() {
          this.livePusher = uni.createLivePusherContext('livePusher', this);
        },
        onShow() {
            //开启预览并设置摄像头
            this.startPreview();
        },
        methods: {
            //获取屏幕高度
            initCamera() {
                let that = this
                uni.getSystemInfo({
                    success: function(res) {
                        that.windowWidth = res.windowWidth;
                        that.windowHeight = res.windowHeight;
                        that.cameraWidth = res.windowWidth;
                        that.cameraHeight = res.windowWidth * 1.5;
                    }
                });
            },
            //启动相机
            startPreview() {
				var that=this
				setTimeout(()=>{
					console.log(that.livePusher)
					that.livePusher.startPreview({
					    success(res) {
					        console.log('启动相机', res)
					    }
					});
				},300)
               
            },
            //停止相机
            stopPreview() {
                let that = this
                this.livePusher.stopPreview({
                    success(res) {
						that.statechange()
                        console.log('停止相机', res)
                    }
                });
            },
            //摄像头 状态
            statechange(e) {
                 //拍照
                this.snapshot()
            },
            //抓拍
            snapshot() {
                let that = this
				console.log('拍照')
				that.message=''
                this.livePusher.snapshot({
                    success(res) {
                        that.snapshotsrc = res.message.tempImagePath;
                        that.uploadingImg(res.message.tempImagePath)
                    }
                });
            },
            // 图片上传
            uploadingImg(e) { 
                let url = e
                let that = this 
				//图片转base64
				pathToBase64(e).then(base64 => {
					//上传云端进行分析
					uniCloud.callFunction({
						name:'face',
						data:{
							type:that.type,
							face_image:base64
						}
					}).then(res=>{
						if(res.result.code=='200'){
							//如果是注册 则须保存人脸图片进行渲染
							if(that.type=='signin'){
								uni.setStorageSync('user_face',res.result.image)
							}
							//人脸 1:N 匹配 结果
							if(that.type=='comparison'){
								console.log(res)
							}
							uni.navigateBack()
						}else{
							that.message=res.result.message
							console.log('错误',res.result.message)
							//重新启动拍照
							setTimeout(()=>{
								that.snapshot()
							},100)
						}
					})
				})
            },
	
            //验证请求
            request(url) {
                let data = {
                    token: this.userInfo.token,
                    photo: url
                }
            },
            // 认证失败,重新认证
            anew(msg) {
                let that = this
                uni.showModal({
                    content: msg,
                    confirmText: '重新审核',
                    success(res) {
                        if (res.confirm) {
                            // console.log('用户点击确定');
                            that.getCount()
                        } else if (res.cancel) {
                            // console.log('用户点击取消');
                            uni.navigateBack({
                                delta: 1
                            })
                        }
                    }
                })
            },
        }
    };
</script>
<style lang="scss">
	  .live-camera {
	        .preview {
	            justify-content: center;
	            align-items: center;
	            .outline-box {
	                position: absolute;
	                top: 0;
	                left: 0;
	                bottom: 0;
	                z-index: 99;
	                align-items: center;
	                justify-content: center;
	            }
	
	            .remind {
	                position: absolute;
	                bottom: 10px;
	                width: 750rpx;
	                z-index: 100;
	                align-items: center;
	                justify-content: center;
	                .remind-text {
	                    color: #dddddd;
	                    font-weight: bold;
	                }
	            }
	        }
	    }
</style>

face_sign_in/face_sign_in.vue

<template>
	<view class="content">
		<view class="face-box" @click="getface">
			<image class="face-bg" src="../../static/face_bg.png" mode="" v-if="!image"></image>
			<view class="fb-msg" v-if="!image">
				点击录入人脸信息
			</view>
			<image class="face" :src="image" mode="" v-if="image"></image>
		</view>
		<view class="top">
			<view class="t-l">
				姓名:
			</view>
			<input class="t-r" placeholder="请输入姓名" type="text" @input="getuser_name" />
		</view>
		<view class="foot" hover-class="foot-hover" @click="getdata">
			提交信息
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				image:'',
				name:''
			}
		},
		onLoad() {
			
		},
		onShow() {
			var image=uni.getStorageSync('user_face')
			this.image=image
		},
		methods: {
			//获取人脸信息
			getface(){
				uni.navigateTo({
					url:"/pages/face/new_file?type=get"
				})
			},
			getuser_name(e){
				this.name=e.target.value
			},
			getdata(){
				var that=this
				if(that.image&&that.name){
					uniCloud.callFunction({
						name:'face',
						data:{
							type:'signin',
							face_image:that.image,
							name:that.name
						}
					}).then((res)=>{
						console.log('人脸信息注册接口',res)
						if(res.result.code=='200'){
							uni.showToast({
								icon:'none',
								title:res.result.message
							})
							setTimeout(()=>{
								uni.removeStorageSync('user_face')
								uni.navigateBack()
							},1000)
						}
						
					})
					
					
					
				}else{
					uni.showToast({
						icon:"none",
						title:'请完善信息'
					})
				}
			}
		}
	}
</script>

<style>
	.content {
		height: 100%;
		width:100%;
		display: flex;
		flex-direction: column;
		align-items: center;
	}
	.face-box{
		margin-top: 30rpx;
		border-radius: 10rpx;
		border:1px solid #64aff4;
		height: 500rpx;
		width: 400rpx;
		overflow: hidden;
		display: flex;
		flex-direction: column;
		align-items: center;
		position: relative;
	}
	.face-bg{
		height: 100%;
		width: 120%;
	}
	.face{
		height: 160%;
		width: 100%;
	}
	.fb-msg{
		position: absolute;
		bottom: 20rpx;
		color: #ffffff;
	}
	.top{
		width: 80%;
		margin-top: 100rpx;
		height: 100rpx;
		display: flex;
		align-items: center;
		justify-content: center;
	}
	.t-l{
		font-size: 32rpx;
		text-align: center;
	}
	.t-r{
		margin-left: 20rpx;
		height: 100%;
		width: 40%;
		border-radius: 10rpx;
		text-indent: 20rpx;
		border:1px solid #64aff4;
	}
	.foot{
		width: 400rpx;
		text-align: center;
		height: 120rpx;
		line-height: 120rpx;
		border-radius: 15rpx;
		margin-top: 50rpx;
		color: #ffffff;
		background-color: #64aff4;
	}
	.foot-hover{
		width: 400rpx;
		text-align: center;
		height: 120rpx;
		line-height: 120rpx;
		border-radius: 15rpx;
		margin-top: 50rpx;
		color: #ffffff;
		background-color: #487fb0;
	}
</style>

index/index.vue

<template>
	<view class="content">
		<image class="logo" src="/static/logo.png"></image>
		
		<view class="text-area">
			<text class="title" @click="zhuce">注册人脸信息</text>
		</view>
		<view class="text-area">
			<text class="title" @click="bidui">人脸1:N搜索信息</text>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: ''
			}
		},
		onLoad() {
			var that=this
			
		},
		methods: {
			zhuce(){
				console.log('????')
				uni.navigateTo({
					url:'/pages/face_sign_in/face_sign_in'
				})
			},
			bidui(){
				uni.navigateTo({
					url:'/pages/face/new_file?type=comparison'
				})
			}
		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>

注意:需要配置云函数 Node.js 的版本

云函数文件下 package.json 内添加

本文只做了云函数调用百度AI的人脸检测,人脸库注册,人脸1:N搜索的功能 会这些大部分业务都不会有难度了

第一次写文章,有不足的大家多多担待,辛苦大家点个小赞,谢谢喽!!

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值