此文主要围绕小程序实现人脸、手势双重识别认证,针对传统人脸识别业务增加了一些新的元素。内容较长、建议先马后看。
一、小程序
1.1、注册账号及创建小程序
- 访问微信公众平台,点击账号注册。
- 选择小程序,并在表单填写所需的各项信息进行注册。
- 在开发管理选择开发设置,将AppID及AppSecret复制出来进行存储。
- 下载安装微信web开发者工具并创建一个新的项目,填入上图所复制的AppId。
1.2、页面设计及样式实现
- 页面需要提供两个用于上传图片的入口,以及将上传图像进行展示的区域,同时还需要提供图像上传按钮以及识别结果的区域。
- WXML内容
<view class="containerBox">
<view class="leftBtn" bindtap="loadImage">上传人脸库</view>
</view>
<view>
<image src="{{reproduction}}" class="showImg"></image>
</view>
<view class="containerBox">
<view class="rightBtn" bindtap="loadImagethis">上传实时照</view>
</view>
<view class="msgTitle">温馨提示:请上传手势数字2的照片</view>
<view style="display: flex;" >
<image src="{{imgSrc}}" class="nowImg"></image>
<view class="contentBox" wx:if="{{isShowDetail}}">
<view class="msgTitleDetail">
<view class="resultTitle">识别分数:{{score}}</view>
<view class="resultTitle2">人脸相似度得分,推荐阈值80分</view>
<view class="resultTitle2" wx:if="{{gestures==0}}">未检测到手势数字2!请重新上传!</view>
<view class="resultTitle2" wx:else>检测到手势数字2!识别通过!</view>
</view>
</view>
</view>
<view class="centerBtn" bindtap="identify">图像识别</view>
- WXSS内容
.containerBox{
width:750rpx; display:flex;height:62rpx;margin-top:20rpx;
}
.leftBtn{
width:181rpx;height:62rpx;color:#4FAFF2;border:1rpx solid #4FAFF2;border-radius:10rpx;text-align: center;line-height:62rpx;font-size:28rpx;margin-left: 284.5rpx;
}
.rightBtn{
width:181rpx;height:62rpx;color:white;border:1rpx solid #4FAFF2;border-radius:10rpx;text-align: center;line-height:62rpx;font-size:28rpx; margin-left: 284.5rpx;background:#4FAFF2;
}
.centerBtn{
width:181rpx;height:62rpx;color:white;border:1rpx solid #29D124;border-radius:10rpx;text-align: center;line-height:62rpx;font-size:28rpx;margin-left: 284rpx;background:#29D124;margin-top:20rpx;
}
.showImg{
width:300rpx;height:300rpx;margin-left:225rpx;margin-top:25rpx;border-radius:50%;
}
.nowImg{
width:300rpx;height:300rpx;margin-left:20rpx; margin-top:10rpx;border-radius:50%;
}
.result{
margin-top:20rpx;
}
.resultTitle{
margin-left:25rpx;margin-top:10rpx;color:#2B79F5;font-size:25rpx;
}
.resultTitle2{
margin-left:25rpx;margin-top:10rpx;color:red;font-size:25rpx;
}
.msgTitle{
color:#0890FF;font-size:30rpx;height:30rpx;line-height:30rpx;font-weight:bold;margin-top:30rpx;text-align: center;
}
.contentBox{width:430rpx;height:300rpx;margin-top:10rpx;}
.msgTitleDetail{
width:430rpx;height:300rpx;margin-top: 112.5rpx;
}
.productTableTr{
height: 80rpx;line-height: 80rpx;border-bottom: 5rpx solid #F8F8F8;display:flex;
}
.leftTr{
width: 583rpx;height: 80rpx;line-height: 80rpx;
}
.rightTr{
width: 119rpx;height: 80rpx;line-height: 80rpx;color: #FF2525;font-size: 26rpx;
}
.leftTrText{
color: #2B79F5;font-size: 28rpx;margin-left: 15rpx;width: 283rpx;
}
.productDetailTable{
width: 702rpx;margin-left: 24rpx;border:5rpx solid #F8F8F8;border-radius: 6rpx;
}
.copyBtn{
color:white;background:#2B79F5;border-radius:8rpx;width:100rpx;height:50rpx;margin-top:15rpx;
}
- WXML跟WXSS部分的内容比较简单,到JS这一块我们需要实现对应的函数将所选择的图片进行展示到界面上。
wx.chooseImage({
count: 0,
sizeType: ['original', 'compressed'], //原图 / 压缩
sourceType: ['album', 'camera'], //相册 / 相机拍照模式
success(res) {
that.setData({
reproduction: res.tempFilePaths[0]
});
}
})
1.3、接口参数拼接
- 上传人脸库以及上传实时照的图片选择完成后,我们需要将所选择的图片转换为Base64格式。
wx.getFileSystemManager().readFile({
filePath: res.tempFilePaths[0],
encoding: 'base64',
success(data) {
let baseData = data.data; //'data:image/png;base64,' + data.data;
that.setData({
baseData: baseData
});
}
});
- 完成上述步骤后能够在控制台下图这步就算成功。
二、API
2.1、注册账号及创建应用
注意事项:人脸识别、人体分析是两个分开的应用,需要分别创建并获取对应的Key以及secret!!!
- 访问百度开放平台选择人脸识别、人体检测并领取免费资源。
- 填写表单所需要的各项信息创建应用。
- 创建完毕后回到应用列表,将API Key 以及Serect Key复制出来,后面我们需要通过这些凭证来获取Token。
2.2、创建API项目
- 打开Visual Studio,右侧选择创建新项目。
- 搜索框输入ASP.NET Web,然后选择Net Framework的项目,点击下一步。
- 填写对应的项目名称及选择存放路径。
- 因为我们只是需要搭建API,所以选择WebApi项目模板,点击创建。
- API创建成功后如下图。
2.3、实现获取Token接口
- 如何获取Access Token。可以看到如下图,获取Token就是向授权服务地址发送请求,并在URL中带上所需的参数,那两个参数就是创建应用的时候已经复制出来的,在这里就能派上用场了。
- 回到VS,选择右侧解决方案Models文件夹,点击添加,选择类。
- 我们现在需要通过封装一个方法,用于向服务授权地址请求。
/// <summary>
/// 模拟Get请求
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static string HttpGet(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json";
request.Accept = "*/*";
request.Timeout = 15000;
request.AllowAutoRedirect = false;
WebResponse response = null;
string responseStr = null;
try
{
response = request.GetResponse();
if (response != null)
{
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
responseStr = reader.ReadToEnd();
reader.Close();
}
}
catch (Exception)
{
throw;
}
finally
{
request = null;
response = null;
}
return responseStr;
}
- 根据获取Token的接口返回参数创建一个实体类进行接收,这个里面我们主要用到的就是access_token以及expires_in,一个是token值,一个就是过期时间了。
/// <summary>
/// 解析Token帮助类
/// </summary>
public class TokenClass {
public string refresh_token { get; set; }
public string session_key { get; set; }
public string scope { get; set; }
public string session_secret { get; set; }
/// <summary>
/// Access Token的有效期(秒为单位,有效期30天);
/// </summary>
public int expires_in { get; set; }
/// <summary>
/// 获取的Access Token
/// </summary>
public string access_token { get; set; }
}
- 拼接client_id 以及client_secret封装成一个方法,讲两个字段以参数的进行进行传递。
/// <summary>
/// 获取token
/// </summary>
/// <returns></returns>
public static TokenClass GetToken(string client_id,string client_secret) {
var grant_type = "client_credentials";
//拼接参数到地址
string tokenUrl = "https://aip.baidubce.com/oauth/2.0/token?grant_type=" + grant_type + "&client_id=" + client_id + "&client_secret=" + client_secret;
string resultStr = RequestHelper.HttpGet(tokenUrl);
if (string.IsNullOrWhiteSpace(resultStr))
{
//返回false
}
TokenClass info = Newtonsoft.Json.JsonConvert.DeserializeObject<TokenClass>(resultStr);
return info;
}
- 去控制器默认的Index动作方法里面调用获取token的方法,看下能否获取到。
public ActionResult Index()
{
ViewBag.Title = "Home Page";
TokenClass info = GetToken("你申请的应用Key", "你申请的应用的Sercet");
return View();
}
- 启动项目,打上断点,能够如下图获取到就可以。
2.4、接口数据处理
- 能够正常的获取到token后,接下来看一下人脸识别对比的接口请求及回调数据。不要被他长篇大论的介绍所吓到,我们只需要在URL上面拼接对应的参数并将图片转换为Base一起携带过去就可以了。
- 回到VS的RequestHelper这个实体类,定义一个方法用来获取人脸识别匹配的结果。
- 接着去控制器,实现一个动作方法,接收从小程序传递过来的两个格式为base64的图片参数,然后再调用上面那个方法。
/// <summary>
/// 人脸相似度对比及手势识别
/// </summary>
/// <param name="baseSence1"></param>
/// <param name="baseSence12"></param>
/// <returns></returns>
public ActionResult GetImageBase(string img1, string img2)
{
var faceResult = FaceData(img1, img2);
return View();
}
- 回到小程序,在图像识别的按钮实现一个函数,并请求上面所创建的动作方法。
let that = this;
let data = {img1: that.data.baseData,img2: that.data.baseDatathis};
wx.request({
url: 'https://localhost:44312/Home/GetImageBase',
method: 'POST',
data: {
img1: that.data.baseData,
img2: that.data.baseDatathis
},
success: function (identify) {
that.setData({
isShowDetail: true,
score: identify.data.score,
gestures: identify.data.gestures,
});
}
})
- 在RequestHelper的FaceData方法打上断点,启动项目。
- 在小程序点击图像识别按钮,并查看断点内容,如下图所示就是请求人脸识别接口所返回的数据。
- 将数据复制出来,进行JSON转义,然后根据字段的数据类型定义对应的实体类来将接口返回的内容进行转换接收。如下图所示,我们这里主要用到的就是result字段里面的score值,也就是人脸相似度得分。
- 根据数据结构定义三个实体类,分别是FaceClass、scoreInfo、face,其中face于scoreInfo是一对多的关系。这样就能直接使用返回的数据了。
/// <summary>
/// 人脸识别返回参数帮助类
/// </summary>
public class FaceClass {
public int error_code { get; set; }
public string error_msg { get; set; }
public Int64 log_id { get; set; }
public int timestamp { get; set; }
public int cached { get; set; }
public scoreInfo result { get; set; }
}
public class scoreInfo
{
/// <summary>
/// 分数
/// </summary>
public decimal score { get; set; }
public List<face> face_list { get; set; }
}
public class face {
public string face_token { get; set; }
}
- 人脸识别的搞定后,接下来就是图片手势识别了。在RequestHelper再定义一个方法,这里只需要定义一个参数即可,因为人脸识别对比是两张图进行对比,手势识别只需要从实拍图里面获取就行了。
注意事项:在获取图片手势识别的时候需要用到另一个应用key以及sercet!!!
- 接着在控制器刚才的动作方法里面再次调用,打上断点看一下执行结果。如下图,我们将result的结果复制出来并定义实体进行接收,第二个数组中classname字段的值为Two,也就是检测到图片中有手势二的动作。
/// <summary>
/// 手势识别返回参数帮助类
/// </summary>
public class GesturesClass {
public Int64 log_id { get; set; }
public int result_num { get; set; }
public List<gestures> result { get; set; }
}
public class gestures {
/// <summary>
/// 手势名称 [1]
/// </summary>
public string classname { get; set; }
public int height { get; set; }
public int left { get; set; }
public decimal probability { get; set; }
public int top { get; set; }
public int width { get; set; }
}
- 在控制器针对所返回的数据写上对应的判断,如果图片中含有数字二的手势则返回不同的数据。当然,接口的能力不仅限于只能识别数字二,我这里只是挑选出一个来做演示,后期有兴趣的小伙伴可以做成配置。
/// <summary>
/// 人脸相似度对比及手势识别
/// </summary>
/// <param name="baseSence1"></param>
/// <param name="baseSence12"></param>
/// <returns></returns>
public ActionResult GetImageBase(string img1, string img2)
{
var faceResult = FaceData(img1, img2);
var gesturesResult = GesturesData(img2);
var score = faceResult.result.score;//人脸相似度分数
var gestures = 0;
if (gesturesResult.result.Count() > 1)
{
if (gesturesResult.result[1].classname == "Two")
{
gestures = 1;
}
}
JsonData info = new JsonData();
info.score = score;
info.gestures = gestures;
return Json(info);
}
2.4、页面数据渲染
- 查看接口所返回的数据,可以看到score字段以及gestures都返回来了。
- 将返回的字段存储到全局data中,在页面进行对应的逻辑判断,最后运行,就能得到一个人脸识别及手势双重识别认证的项目啦。
大家可以根据自己的业务场景设计不同的效果展示,有不懂的可以私信或者在下面留言,让我们共同学习,一起进步!