FrCore.cs
/* ---------------------------------------------------------- * 文件名称:FrCore.cs * 作者:秦建辉 * * 微信:splashcn * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * Visual Studio V2017 * .NET Framework 4 * * 版本历史: * V1.1 2018年09月20日 * 接口增强 * * V1.0 2018年03月27日 * 人脸识别抽象类定义 ------------------------------------------------------------ */ using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Windows; namespace Com.FirstSolver.FR { /// <summary> /// 人脸识别通用接口 /// </summary> public abstract class FrCore : IDisposable { /// <summary> /// 厂家名称 /// </summary> public abstract string Company { get; } /// <summary> /// 作者名称 /// </summary> public virtual string Author { get { return "秦建辉"; } } /// <summary> /// 最多处理人脸的数目 /// </summary> public abstract int MaxFaceNum { get; } /// <summary> /// 错误描述 /// </summary> public string ErrorMessage { get; protected set; } /// <summary> /// 参数字典 /// </summary> public Dictionary<string, object> Addons = new Dictionary<string, object>(); /// <summary> /// 初始化接口 /// </summary> /// <returns> /// 0:初始化接口成功 /// 其它:错误编号 /// </returns> public abstract int Initialize(); /// <summary> /// 关闭接口 /// </summary> public virtual void Close() { Dispose(); } /// <summary> /// 释放资源 /// </summary> public virtual void Dispose() { ErrorMessage = null; } /// <summary> /// 人脸位置信息检测 /// </summary> /// <param name="image">图像数据</param> /// <param name="faces">输出:人脸位置信息</param> /// <returns> /// 0:操作成功 /// 其它:错误编号 /// </returns> public abstract int Detect(byte[] image, out Int32Rect[] faces); /// <summary> /// 人脸细节信息检测 /// </summary> /// <param name="image">图像数据</param> /// <param name="faces">输出:人脸细节信息</param> /// <returns> /// 0:操作成功 /// 其它:错误编号 /// </returns> public abstract int DetectDetails(byte[] image, out Newtonsoft.Json.Linq.JArray faces); /// <summary> /// 人脸匹配 /// </summary> /// <param name="imagea">源图像</param> /// <param name="facetypea">源图像人脸类型</param> /// <param name="imageb">目标图像</param> /// <param name="facetypeb">目标图像人脸类型</param> /// <param name="score">输出:图像相似度</param> /// <returns> /// 0:操作成功 /// 其它:错误编号 /// </returns> public abstract int Match(byte[] imagea, string facetypea, byte[] imageb, string facetypeb, out float score); /// <summary> /// 网址编码 /// </summary> /// <param name="str">要编码的字符串</param> /// <param name="e">字符编码方案</param> /// <param name="uppercase">是否输出大写字母</param> /// <returns>编码字符串</returns> public static string UrlEncode(string str, Encoding e, bool uppercase = false) { if (uppercase) { return Regex.Replace(System.Web.HttpUtility.UrlEncode(str, e), @"%[0-9a-f]{2}", m => m.Value.ToUpper()); } else { return System.Web.HttpUtility.UrlEncode(str, e); } } /// <summary> /// 将字节数组转换为16进制编码字符串 /// </summary> /// <param name="buffer">要转换的字节数组</param> /// <param name="uppercase">是否输出大写字母</param> /// <returns>16进制编码字符串</returns> public static string ToHexString(byte[] buffer, bool uppercase = false) { StringBuilder sb = new StringBuilder(); if (uppercase) { foreach (byte b in buffer) sb.Append(b.ToString("X2")); } else { foreach (byte b in buffer) sb.Append(b.ToString("x2")); } return sb.ToString(); } } }
BaiduFr.cs
/* ---------------------------------------------------------- * 文件名称:BaiduFr.cs * 作者:秦建辉 * * 微信:splashcn * * 博客:http://www.firstsolver.com/wordpress/ * * 开发环境: * Visual Studio V2017 * .NET Framework 4 * Newtonsoft.Json 11.0.2 * * 版本历史: * V1.1 2018年09月20日 * 接口增强 * * V1.0 2018年03月27日 * 百度人脸识别类实现 * * 说明: * 人脸检测V3:https://aip.baidubce.com/rest/2.0/face/v3/detect * 人脸比对V3:https://aip.baidubce.com/rest/2.0/face/v3/match ------------------------------------------------------------ */ using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text; using System.Windows; namespace Com.FirstSolver.FR { public class BaiduFr : FrCore { /// <summary> /// 厂家名称 /// </summary> public override string Company { get { return "百度"; } } /// <summary> /// 最多处理人脸的数目 /// </summary> public override int MaxFaceNum { get { return 10; } } /// <summary> /// 应用标识 /// </summary> private const string API_KEY = "Vnrv8o6lmHm3jAYsB62tZBod"; /// <summary> /// 应用密钥 /// </summary> private const string API_SECRET = "VmYQyST8kq3s0HcrGcdRHcLbxeGwNQDe"; /// <summary> /// 访问授权码 /// </summary> public string AccessToken { get; private set; } /// <summary> /// 人脸识别接口初始化 /// </summary> /// <returns> /// 0-成功 /// 其它-失败 /// </returns> public override int Initialize() { ErrorMessage = null; // 获取授权码,授权服务地址:https://aip.baidubce.com/oauth/2.0/token StringBuilder sb = new StringBuilder(); sb.Append("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=").Append(API_KEY).Append("&client_secret=").Append(API_SECRET); try { if (!(WebRequest.Create(sb.ToString()) is HttpWebRequest httpWebRequest)) { return -1; } using (HttpWebResponse response = httpWebRequest.GetResponse() as HttpWebResponse) { using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { AccessToken = JObject.Parse(sr.ReadToEnd())["access_token"].ToString(); return 0; } } } catch (Exception e) { ErrorMessage = e.Message; return -2; } } /// <summary> /// 获取人脸检测结果 /// </summary> /// <param name="url">人脸检测访问接口</param> /// <param name="options">人脸检测参数</param> /// <returns>人脸检测结果</returns> public static JObject DoHttpPost(string url, string options) { if (!(WebRequest.Create(url) is HttpWebRequest httpWebRequest)) return null; httpWebRequest.Method = "POST"; httpWebRequest.KeepAlive = true; httpWebRequest.ContentType = "application/json"; // 内容类型 byte[] Args = Encoding.UTF8.GetBytes(options); httpWebRequest.ContentLength = Args.Length; using (Stream requestStream = httpWebRequest.GetRequestStream()) { requestStream.Write(Args, 0, Args.Length); } using (HttpWebResponse response = httpWebRequest.GetResponse() as HttpWebResponse) { using (StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { return JObject.Parse(sr.ReadToEnd()); } } } /// <summary> /// 创建人脸检测调用参数 /// </summary> /// <param name="image">图像数据</param> /// <returns>人脸检测调用参数</returns> private string CreateFaceDetectParameters(byte[] image) { StringBuilder sb = new StringBuilder(); sb.Append("{\"image\":\"").Append(Convert.ToBase64String(image)).Append("\",\"image_type\":\"BASE64\""); foreach (KeyValuePair<string, object> item in Addons) { if (item.Value != null) { sb.Append(",\"").Append(item.Key).Append("\":\"").Append(item.Value.ToString()).Append("\""); } } sb.Append("}"); return sb.ToString(); } public override int Detect(byte[] image, out Int32Rect[] faces) { ErrorMessage = null; faces = null; try { string options = CreateFaceDetectParameters(image); string url = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=" + AccessToken; while (true) { var result = DoHttpPost(url, options); var error_code = (int)result["error_code"]; if (error_code == 0) { if ((int)result["result"]["face_num"] == 0) { ErrorMessage = "未检测出人脸"; return -1; } JArray FaceJArray = result["result"]["face_list"] as JArray; List<Int32Rect> FaceCollection = new List<Int32Rect>(); foreach (dynamic item in FaceJArray) { var location = item["location"]; FaceCollection.Add(new Int32Rect((int)location["left"], (int)location["top"], (int)location["width"], (int)location["height"])); } faces = FaceCollection.ToArray(); return 0; // 成功 } else if (error_code == 18) { // Open api qps request limit reached continue; } else { ErrorMessage = result["error_msg"].ToString(); return -1; // 人脸检测失败 } } } catch (System.Exception e) { ErrorMessage = e.Message; return -2; // 异常 } } public override int DetectDetails(byte[] image, out JArray faces) { ErrorMessage = null; faces = null; try { string options = CreateFaceDetectParameters(image); string url = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=" + AccessToken; while (true) { var result = DoHttpPost(url, options); var error_code = (int)result["error_code"]; if (error_code == 0) { if ((int)result["result"]["face_num"] == 0) { ErrorMessage = "未检测出人脸"; return -1; } faces = result["result"]["face_list"] as JArray; return 0; // 成功 } else if (error_code == 18) { // Open api qps request limit reached continue; } else { ErrorMessage = result["error_msg"].ToString(); return -1; // 人脸检测失败 } } } catch (System.Exception e) { ErrorMessage = e.Message; return -2; // 异常 } } /// <summary> /// 创建人脸匹配调用参数 /// </summary> /// <param name="imagea">人脸图像A</param> /// <param name="facetypea">图像A人脸类型</param> /// <param name="imageb">人脸图像B</param> /// <param name="facetypeb">图像B人脸类型</param> /// <returns>人脸匹配调用参数</returns> private string CreateFaceMatchParameters(byte[] imagea, string facetypea, byte[] imageb, string facetypeb) { StringBuilder sb = new StringBuilder(); sb.Append("[{\"image\":\"").Append(Convert.ToBase64String(imagea)).Append("\",\"image_type\":\"BASE64\"").Append(",\"face_type\":\"").Append(facetypea).Append("\"}"); sb.Append(",{\"image\":\"").Append(Convert.ToBase64String(imageb)).Append("\",\"image_type\":\"BASE64\"").Append(",\"face_type\":\"").Append(facetypeb).Append("\"}]"); return sb.ToString(); } public override int Match(byte[] imagea, string facetypea, byte[] imageb, string facetypeb, out float score) { ErrorMessage = null; score = float.MinValue; try { string options = CreateFaceMatchParameters(imagea, facetypea, imageb, facetypeb); string url = "https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=" + AccessToken; while (true) { var result = DoHttpPost(url, options); var error_code = (int)result["error_code"]; if (error_code == 0) { score = (float)result["result"]["score"]; return 0; // 成功 } else if (error_code == 18) { // Open api qps request limit reached continue; } else { ErrorMessage = result["error_msg"].ToString(); return -1; // 人脸匹配失败 } } } catch (System.Exception e) { ErrorMessage = e.Message; return -2; // 异常 } } } }