此文主要通过WinForm来制作的一个人脸识别考勤打卡程序,有兴趣的小伙伴可以接入到打卡机上。
一、实现流程
1.1、创建项目
- 打开Visual Studio,右侧选择创建新项目。
- 搜索框输入winform,选择windows窗体应用,填写对应的保存路径点击下一步,创建成功后如下图。
1.2、设计页面
- Form1就是我们需要操作的窗体了,根据自己的想法给窗体设置对应的背景颜色。
- 在页面增加timer1控件,在Form1_Load事件中执行start,达到一个获取当前年月日时分秒的效果。
private void Form1_Load(object sender, EventArgs e)
{
this.timer1.Start();
}
private void timer1_Tick_1(object sender, EventArgs e)
{
this.label1.Text = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
}
- 获取电脑摄像头权限,没有摄像头的同学可以先通过图片上传模拟此效果。
private void btnBase_Click(object sender, EventArgs e)
{
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
Image fromImage = Image.FromFile(this.openFileDialog1.FileName);
baseFileName = this.openFileDialog1.FileName;
fromImage = fromImage.AdjImageToFitSize(pbMatch.Width, pbMatch.Height); //350 l;
this.pbBase.Image = fromImage;
string[] names = baseFileName.Split('\\');
baseShortName = names[names.Length - 1];
baseBM = Resize(baseFileName, tempFilePath + "base_" + baseShortName);
}
}
- 在窗体上拖拽进来一个pictureBox控件,用于展示我们上传或者摄像头捕捉到的人像,同时给它增加一个圆角边框的效果。这个控件的SizeMode属性需要设置为Zoom,图片自适应。
GraphicsPath gp = new GraphicsPath();
gp.AddEllipse(pictureBox1.ClientRectangle);
Region region = new Region(gp);
pictureBox1.Region = region;//赋值
gp.Dispose();//释放资源
region.Dispose();//释放资源
1.3、创建应用
- 访问开放平台选择人脸识别并领取免费资源。
- 填写表单所需要的各项信息创建应用。
- 创建完毕后回到应用列表,将API Key 以及Serect Key复制出来,后面我们需要通过这些凭证来获取Token。
1.4、获取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();
}
- 启动项目,打上断点,能够如下图获取到就可以。
1.5、与人脸数据比对并展示
- 能够正常的获取到token后,从人脸库或者数据库中进行比对。
- 回到VS的RequestHelper这个实体类,定义一个方法用来获取人脸识别匹配的结果。
- 将方法绑定到摄像头捕捉到人像的事件中,启动项目,如下图所示就是请求人脸识别接口所返回的数据。
- 将数据复制出来,进行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; }
}
- 将比对结果以及用户信息在窗体上通过lable控件进行展示,也可以加上一些加载中的动画,优化体验。有兴趣的小伙伴可以针对具体的业务进行调整。