微信小程序之百度人脸识别系统-人脸注册前后端代码
在微信小程序加入百度人脸识别登陆系统,简直是一步一坑。在网上查找了不少文章,经过几天的连续奋战,终于基本实现了这个功能。或许还有不少BUG,但是已经能完成我想要的功能了。在此贴出前后端完整代码。并对每条语句详细说明下。相信对自己以后做类似程序会有所帮助吧。
先上大家最关心的后台PHP代码吧。这个才是重点。。。前台微信小程序端其实很简单了。
首先需要进入百度人脸库下载PHP ,只需要以下SDK目录结构的文件就行了。
PHP后端代码:(我创建了两个PHP页面)
A.PHP 负责图片上传及图片识别
<?php
//百度人脸入库
/**第一个坑: 注释不能写在“<?php前面或者在<?php前面留空行。不是在小程序端会原样输出,,这样就无法正确读取您想要的数据了” **/
$user_id = $_POST['user_id']; //小程序端传入的用户名
date_default_timezone_set("Asia/Shanghai"); //设置时区
$code = $_FILES['file'];//获取小程序传来的图片
if(is_uploaded_file($_FILES['file']['tmp_name'])) {
//把文件转存到你希望的目录
$uploaded_file=$_FILES['file']['tmp_name'];
//我们给每个用户动态的创建一个文件夹$user_path=$_SERVER['DOCUMENT_ROOT']."uploadphoto/hwphoto/userface";
//判断该用户文件夹是否已经有这个文件夹
if(!file_exists($user_path)) {
mkdir($user_path);
}
//上传上来的文件名
$file_true_name=$_FILES['file']['name'];
//文件需要保存的本地路径
$move_to_file=$user_path."/".date("Y-m-d")."-".uniqid().substr($file_true_name,strrpos($file_true_name,"."));
//保存文件
move_uploaded_file($uploaded_file,iconv("utf-8","gb2312",$move_to_file));
}
//需要定义一个类,名字随意
class post{
//入口函数
private function init_face(){
$APP_ID = 'XXXXX';
$API_KEY = 'XXXXXXX';
$SECRET_KEY = 'XXXXXXXXXXXXX';
require_once '/www/wwwroot/WWW.XXX.COM/AipFace.php';
return new \AipFace($APP_ID,$API_KEY,$SECRET_KEY);
}
//验证照片
public function facevalid(){
//这里需要把类以外的变量定义为全局变量,不是在类里的函数根本找不到“第二坑”
global $move_to_file;
global $user_id;
//定义这个变量就是填坑的意思了,其实不用定义这个变量了
$userId ="$user_id";
$file = "$move_to_file"; //照片服务器路径
if(!file_exists($file)){
die('文件不存在');
}
//获取上传的图片并转换成64位的,百度人脸识别要求的
$image = file_get_contents($file);
$image = base64_encode($image);
//可选项,必须是数组形式
$options = array();
//最大人脸数不能超过2个
$options['max_face_num'] = 2;
//这个完全是搞起玩的。这行代码可以忽略,判断下年龄,评分,性别
$options['face_field'] = 'age,beauty,gender';
//调取入口函数
$client = $this->init_face();
//通过入口函数调用人脸识别方法,传入要求的参数
$ret = $client->detect($image,'BASE64',$options);
//输出百度人脸识别反馈的结果。这行代码可忽略。
echo json_encode($ret,JSON_UNESCAPED_UNICODE);
//根据刚才百度人脸识别返回的结果判定
if($ret['error_code']==0){ //有人脸
$result = $ret['result'];
$face_num = $result['face_num']; //人脸数
$opp = array();
$opp['user_info'] ='2'; //附加信息。以后会用到,我这里2为数据库需要的用户组
if(1==$face_num){ //人脸数目为1才执行
$face_probability = $result['face_list'][0]['face_probability'];
if(1==$face_probability){ //可靠性为1,判断人脸真实性
$client->addUser($image,'BASE64','stu',$userId,$opp);
echo "$file";
}else{
die('可靠性为:' . $face_probability);
}
}else{
die('人脸数量大于1');
}
}
}
}
//最后调动类里的方法
$post =new post();
echo $post->facevalid();
?>
B.PHP(负责数据库管理)
//检测用户名是否重复
elseif($type == "checkname"){
$post_name = $_POST["name"]; //用户名
$con = mysqli_connect("xxxx","xxxx","xxxx") or die("数据库连接失败");//连接数据库
mysqli_query($con,"set names utf8");
mysqli_select_db($con,"stu") or die("数据库选择失败");
$sql_search="SELECT name from user where name = '$_POST[name]'";
$result_search = mysqli_query($con,$sql_search);
$num_search = mysqli_num_rows($result_search);
if ($num_search >=1){
echo "1";}
}
//人脸注册
elseif($type == "resface"){
$post_name = $_POST["name"]; //用户名
$post_face = $_POST["vface"]; //照片本地地址
$level = "2"; //用户组
$con = mysqli_connect("xxxxx","xxxxx","xxxxxx") or die("数据库连接失败");//连接数据库
mysqli_query($con,"set names utf8");
mysqli_select_db($con,"stu") or die("数据库选择失败");
$sql_insert="INSERT INTO user (id,name,level,vface) VALUES (null,'$post_name','$level','$post_face')";
$result_insert = mysqli_query($con,$sql_insert);
echo "注册成功";
}
微信小程序端
JS代码
Page({
data: {
nickName: "", //用户昵称
src: "", //上传到服务器的照片路径
msg: "", //服务器返回信息
url: "", //注册成功后自动回到登录界面
disabled: false, //注册按钮判断用户名是否重复显示状态
},
//拍照
takePhoto() {
var that = this
var user_id = that.data.nickName
wx.chooseImage({
//只能使用摄像头上传一张照片。一点点防止作弊的方法吧
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['camera'],
success(res) {
wx.showLoading({
title: '人脸上传中',
mask: true
})
//上传人脸进行注册
var tempFilePaths = res.tempFilePaths
//上传照片到服务器
wx.uploadFile({
url: 'https://www.ailaiyun.com/A.php',
filePath: tempFilePaths[0],
name: 'file',
//携带的参数,输入框输入的用户名。方便在百度人脸库根据这个用户名建立相应的用户
formData: {
user_id: that.data.nickName
},
success(res) {
//上传成功后隐藏loading窗口
wx.hideLoading()
//把服务器返回的图片本地地址保存到data里面,方便调用
var msg = res.data
that.setData({
msg
})
console.log(that.data.msg)
//判断上传成功后,把服务器端图片上传的本地地址保存的数据库,以此判断此用户是否绑定人脸注册
if (res.statusCode == "200") {
wx.request({
url: 'https://www.ailaiyun.com/B.php',
method: "post",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: {
//服务器端执行类型为resface的条件语句,加入图片服务器端地址到数据库
type: "resface",
name: that.data.nickName,
vface: that.data.msg
},
success(res) {
},
})
wx.showToast({
title: '人脸注册成功',
icon: 'success',
})
setTimeout(function () {
//这是延时返回到登陆窗口
wx.switchTab({
url: '../index/index'
})
}, 3000)
}
}
})
}
})
},
//获取用户信息
bindGetUserInfo: function(e) {
var that = this;
//获取输入框输入的名字并赋值。。。坑。。。。这里不能有空格,只能是字母、数字、下划线。否者百度人脸库无法识别就无法入库了
this.setData({
nickName: e.detail.value
})
//查询数据库里是否已经有这个用户名
wx.request({
url: 'https://www.ailaiyun.com/B.php',
method: "post",
header: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: {
//更具type判断应该在后端使用那条语句
type: "checkname",
name: that.data.nickName,
},
success(res) {
console.log(res.data)
//后端返回查询到的数量
if (res.data == 1) {
wx.showToast({
title: '用户已经存在',
icon: 'success',
duration: 4000
})
//如果用户名已注册,设置按钮禁用
that.setData({
disabled: true
})
} else {
wx.showToast({
title: '用户名可以注册',
icon: 'success',
})
//如果用户名可使用,设置注册按钮可用
that.setData({
disabled: false
})
}
}
})
},
})
WXML代码:
<!--pages/camera/camera.wxml-->
<view class='text-info'>
<view class='title'>人脸注册须知</view>
<view class='content-text'>用户名只能由数字、字母、下划线组成——不支持中文</view>
<view class='content-text'>先输入用户名,再拍照注册哦!网络可能故障,如果不成功,请再试一下!</view>
</view>
<!-- 需要使用 button 来授权登录 -->
<input bindinput="bindGetUserInfo" placeholder='请输入用户名' class='inputname' />
<!-- 拍照按钮 -->
<button type="warn" bindtap="takePhoto" class='btn' disabled='{{disabled}}'> 人脸注册 </button>
WXSS代码:(这里只是基本样式,待修改)
/* pages/res_face/res_face.wxss */
.btn{
width: 80%;
margin-top: 30rpx;
}
.inputname{
background-color: rgb(228, 240, 186);
border-radius: 15rpx;
height: 70rpx;
width: 80%;
margin: 30rpx auto;
text-align: center;
}
.text-info{
display: flex;
flex-direction: column;
width: 90%;
margin: 0 auto;
}
.title{
font-size: 40rpx;
font-weight: bolder;
margin: 0 auto;
}
.content-text{
color: red;
margin: 20rpx auto;
}