基于ASP.NET使用C#实现简单人脸识别功能


案例概述

本案例基于ASP.NET和百度云人脸库,主要实现静态人脸添加和静态人脸检测的功能,是笔者一个练习的小Demo

使用的工具

主要使用了VS 2017、MS SQL Server数据库和百度云人脸库

实现的功能

  • 人脸注册
  • 人脸搜索

功能及代码展示

知识背景

百度人脸库的创建

1.打开浏览器登录百度智能云,(百度账号即可登录)


2.应用列表|创建应用


3.人脸库管理|选择刚刚创建好的应用

4.在这个应用中创建新分组(这个分组将在之后上传图片信息中用到)

本项目中用到的类

1.AccessToken.cs

主要功能:将创建人脸库时获取的API Key和Sercet Key,放入json字符串中传给百度云人脸识别接口,与自己创建的人脸库建立连接,并获取连接凭证。
返回回来的json字符串中含有的Access_Token就是这个凭证。

这个类不是笔者写的,是百度云提供的api调用方式文档(点此访问),在这个文档的基础上,笔者进行了一些修改,形成了下面的类。

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Web.Script.Serialization;

namespace com.baidu.ai
{
    public static class AccessToken

    {
        // 调用getAccessToken()获取的 access_token建议根据expires_in 时间 设置缓存
        // 返回token示例
        public static String TOKEN = "24.adda70c11b9786206253ddb70affdc46.2592000.1493524354.282335-1234567";

        // 百度云中开通对应服务应用的 API Key 建议开通应用的时候多选服务
        private static String clientId = "*********";
        // 百度云中开通对应服务应用的 Secret Key
        private static String clientSecret = "**********";

        public static String getAccessToken()
        {
            String authHost = "https://aip.baidubce.com/oauth/2.0/token";
            HttpClient client = new HttpClient();
            List> paraList = new List>();
            paraList.Add(new KeyValuePair("grant_type", "client_credentials"));
            paraList.Add(new KeyValuePair("client_id", clientId));
            paraList.Add(new KeyValuePair("client_secret", clientSecret));

            HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
            String result = response.Content.ReadAsStringAsync().Result;
            Console.WriteLine(result);


            //获取返回的字符串
            //string test = AccessToken.getAccessToken();
            //Response.Write(test + "
"); //获取返回的Access_Token string Access_Token = ""; JavaScriptSerializer Jss = new JavaScriptSerializer(); Dictionary DicText = (Dictionary)Jss.DeserializeObject(result); //如果返回值中含有access_token,则将其值赋予Access_Token,不存在则说明获取失败。 if (!DicText.ContainsKey("access_token")) { Access_Token = "获取Access_Token失败"; } else { Access_Token = DicText["access_token"].ToString(); } //Session["Token"] = Access_Token; //Response.Write(Access_Token); return Access_Token; } } }

2.FaceAdd.cs

主要功能:在人脸库中新建人脸,并设置这个人脸的编号和分组,这个类也是基于百度云的开发文档

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;

namespace com.baidu.ai
{
    public class FaceAdd
    {
        // 人脸注册
        ///参数说明:token->之前获取的Access_Token,base64->图片数据,tel->人脸编号
        public static string add(string token,string base64,string tel)
        {
            //string token = "[调用鉴权接口获取的token]";
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "post";
            request.KeepAlive = true;

            //将数据写入json字符串中
            Dictionary dic = new Dictionary();
            dic.Add("image", base64);
            dic.Add("image_type", "BASE64");
            //人脸库里的分组名
            dic.Add("group_id", "Users");
            //这个人脸的编号
            dic.Add("user_id", tel);
            //图片质量检测,Low表示可以接受较低画质的人脸数据
            dic.Add("quality_control", "LOW");
            //活体检测,这里只是一个小Demo,所以没有添加活体检测的功能
            dic.Add("liveness_control", "NONE");
            JavaScriptSerializer js = new JavaScriptSerializer();
            String str = js.Serialize(dic);
            
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            Console.WriteLine("人脸注册:");
            Console.WriteLine(result);
            return result;
        }
    }
}

3.FaceSearch.cs

主要功能:将从前端获取的Base64格式的人脸图片信息和人脸库中已有的人脸进行对比,匹配的编号和匹配程度(百分制),参考百度云人脸搜索。

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;

namespace com.baidu.ai
{
    public class FaceSearch
    {
        // 人脸搜索
        public static string Search(string token, string strbase64)
        {
            //服务器地址,Access_Token作为凭证
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "post";
            request.KeepAlive = true;
            //序列化,生成json字符串
            Dictionary dic = new Dictionary();
            dic.Add("image", strbase64);
            dic.Add("image_type", "BASE64");
            dic.Add("group_id_list", "Users");
            dic.Add("quality_control", "LOW");
            dic.Add("liveness_control", "NONE");
            JavaScriptSerializer js = new JavaScriptSerializer();
            String str = js.Serialize(dic);

            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            Console.WriteLine("人脸搜索:");
            Console.WriteLine(result);
            return result;
        }
    }
}

主类其实就是上面三个类,但是为了方便从上面三个类返回的json字符串中取值和判断,笔者又添加了两个类

4.SearchReturn.cs

主要功能:实现json的反序列化,这个类文件中的几个类定义了一个数据类型,用于存放FaceSearch返回的json字符串转换成的变量。
其关系是 SearchReturn>Result>User_List

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// 
/// SearchReturn 的摘要说明
/// 
namespace com.baidu.ai
{
    public class SearchReturn
    {
        public int error_code { get; set; }
        public string error_msg { get; set; }
        public long log_id { get; set; }
        public int timestamp { get; set; }
        public int cached { get; set; }
        public Result result { get; set; }
    }

    public class Result
    {
        public string face_token { get; set; }
        public User_List[] user_list { get; set; }
    }

    public class User_List
    {
        public string group_id { get; set; }
        public string user_id { get; set; }
        public string user_info { get; set; }
        public float score { get; set; }
    }
}



5.ReturnResultDetect.cs

主要功能:基于FaceAdd和FaceSearch返回的json字符串,获取相应的值并返回相应的标记以帮助业务代码的实现。

(*需要在Nuget中添加Newtonsoft包)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
using Newtonsoft.Json.Linq;
using com.baidu.ai;
using Newtonsoft.Json;

/// 
/// ReturnResultDetect 的摘要说明
/// 
namespace com.baidu.ai
{
    public static class ReturnResultDetect
    {
        public static int GetFaceAddReturnResult(string strjson)
        {
            int BackResult = 0;
            SearchReturn feedback = JsonConvert.DeserializeObject(strjson);
            if (feedback.result==null)
            {
                BackResult = 0;
            }
            else
            {
                BackResult = 1;
            }
            return BackResult;
        }
        public static string GetFaceSearchReturnResult(string strjson)
        {
            string BackResult ="";
            int score = 0;
            //将收到的json字符串转化成SearchReturn类型的变量,即反序列化
            SearchReturn feedback = JsonConvert.DeserializeObject(strjson);
            if (feedback.result==null)
            {
                BackResult = "_0";   //未检测到人脸
            }
            else
            {
                score = Convert.ToInt32(feedback.result.user_list[0].score);
                if (score<80)
                {
                    BackResult = "_1";   //人脸不匹配
                }
                else
                {
                    BackResult = feedback.result.user_list[0].user_id;
                }
            }
            return BackResult;
        }
    }
}

人脸注册

人脸注册的图像获取主要是通过HTML5的Video标签Canvas标签,原理是将前置摄像头的视频内容放到video中显示,然后通过点击按钮获取点击时刻的video截图,将图片信息放入canvas中保存,并且将图片内容编码为Base64再通过Hiddenfield控件传给后端,实现后端对图片信息的获取。

前端代码

/*<%@ Page Language="C#" AutoEventWireup="true" CodeFile="User_Face_Signup.aspx.cs" Inherits="User_Face_Signup" %>





    
    
    
    人脸注册
    
    
    
    
    
    
    
    
    
    


    
<%--
--%>
人脸注册
<%--
--%>
*/

后端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using com.baidu.ai;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;


public partial class User_Face_Signup : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text= "**请在光线充足的地方录入人脸以提高刷脸登录准确度!**
**准备好后点击下方按钮即可录入人脸!** "; } protected void capture_Click(object sender, EventArgs e) { //下面几个从session传过来的值是笔者这个项目里前一个页面的值,可以不看,但是为了保证程序完整性笔者还是将其放了上来 string name = Session["UserName"].ToString(); string tel = Session["UserTel"].ToString(); string password = Session["UserPass"].ToString(); string email = Session["UserMail"].ToString(); string PreBase64 = HiddenField1.Value; string Base64 = ""; //兼容各种不同的图片格式 if (PreBase64.Contains("data:image/png;base64,")) { Base64 = PreBase64.Replace("data:image/png;base64,", ""); } if(PreBase64.Contains("data:image/jpg; base64,")) { Base64 = PreBase64.Replace("data:image/jpg;base64,", ""); } if (PreBase64.Contains("data:image/jpeg; base64,")) { Base64 = PreBase64.Replace("data:image/jpeg;base64,", ""); } //调用类AccessToken中的getAccessToken方法,获取返回值Access_Token //注:Access_Token其实每次取值都可以保留一段时间,但是为了减少不必要的麻烦,笔者这里还是每次都获取新的Access_Token,代价是每次都要多连接一次人脸库,浪费时间 string Access_Token = AccessToken.getAccessToken(); //将图片信息和对应人脸编号传入,上传到服务器 string Face_Add_Return = FaceAdd.add(Access_Token, Base64, tel); //获取人脸添加的返回值,1表示添加成功,否则为失败 int Face_Add_Result = ReturnResultDetect.GetFaceAddReturnResult(Face_Add_Return); if (Face_Add_Result==1) { SqlConnection conn = new SqlConnection(); conn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionStringProManage"].ConnectionString; try { conn.Open(); string SQL = "insert into Users (uername,password,usertype,name,tel,email) values (@tel,@password,2,@name,@tel,@email)"; SqlCommand cmd = new SqlCommand(); cmd.Connection = conn; cmd.CommandType = CommandType.Text; cmd.CommandText = SQL; //依次添加每个字段的值 SqlParameter ptel = new SqlParameter("@tel", SqlDbType.VarChar, 11); ptel.Value = tel; cmd.Parameters.Add(ptel); SqlParameter ppassword = new SqlParameter("@password", SqlDbType.VarChar, 20); ppassword.Value = password; cmd.Parameters.Add(ppassword); SqlParameter pname = new SqlParameter("@name", SqlDbType.NVarChar, 10); pname.Value = name; cmd.Parameters.Add(pname); SqlParameter pemail = new SqlParameter("@email", SqlDbType.NVarChar, 30); pemail.Value = email; cmd.Parameters.Add(pemail); int R = cmd.ExecuteNonQuery(); //R 的值就是返回影响表的行数 if (R > 0) { Session["ReturnPath"] = "Move_login.aspx"; Session["Message"] = "恭喜,注册成功!"; Response.Redirect("Success.aspx"); } else { Session["Message"] = "插入失败,请检查您的操作!"; Response.Redirect("Error.aspx"); } //Session["ReturnPath"] = "Admin_Add.aspx"; //Response.Redirect("Mid.aspx"); } finally { conn.Close(); } } else { Label1.Text = "**未检测到人脸,请重试!** "; } } }

人脸搜索

人脸搜索和人脸注册的实现方式是类似的,只不过一个是写(注册),一个是读(搜索)。注册是把人脸信息录入人脸库,并给其分配一个唯一标识号——人脸编号,而搜索就是一个相反的过程,通过上传的人脸与数据库中的人脸对比,返回这个人脸编号和相似度。

前端代码

<%--和人脸注册的代码基本一致-->
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="User_Face_Login.aspx.cs" Inherits="User_Face_Login" %>





    
    
    
    刷脸登录
    
    
    
    
    
    
    
    
    
    


    
<%--
--%>
刷脸登录
<%--
--%>

后端代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using com.baidu.ai;

public partial class User_Face_Login : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Label1.Text = "**请保持环境光线充足以提高刷脸登录准确度!**
**准备好后点击下方按钮即可登录!** "; } protected void capture_Click(object sender, EventArgs e) { //与上面类似的,获取前端传过来的Base64格式的图片编码 string PreBase64 = HiddenField1.Value; string Base64 = ""; if (PreBase64.Contains("data:image/png;base64,")) { Base64 = PreBase64.Replace("data:image/png;base64,", ""); } if (PreBase64.Contains("data:image/jpg; base64,")) { Base64 = PreBase64.Replace("data:image/jpg;base64,", ""); } if (PreBase64.Contains("data:image/jpeg; base64,")) { Base64 = PreBase64.Replace("data:image/jpeg;base64,", ""); } //获取Access_Token,同上 string Access_Token = AccessToken.getAccessToken(); //获取返回的json字符串 string feedback = FaceSearch.Search(Access_Token, Base64); //从返回的字符串中取值,并根据值给出相应的判断 string backid = ReturnResultDetect.GetFaceSearchReturnResult(feedback); if (backid=="_0") { Label1.Text = "**未检测到人脸,请重试!** "; } else if (backid == "_1") { Label1.Text = "**您尚未注册,请注册后登录** "; Response.Redirect("Faca_Login_error.aspx"); } else { Session["Move_Name"] = backid; Session["Move_Islogin"] = 2; Response.Redirect("Move_User.aspx"); } } }

本文是小弟在学习过程中做的一个小Demo,如有错误或者不当之处还请各位大佬斧正。

转载请注明原文链接。

你可能感兴趣的:(基于ASP.NET使用C#实现简单人脸识别功能)