人脸检测哪家强?百度、腾讯、旷视大比拼(3)腾讯人脸检测类实现

同系列文章

/* ----------------------------------------------------------
 * 文件名称:TencentFr.cs
 * 作者:秦建辉
 * 
 * 微信:splashcn
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      Visual Studio V2017
 *      .NET Framework 4
 *      Newtonsoft.Json 11.0.2
 *      
 * 版本历史:
 *      V1.0    2018年03月27日
 *              腾讯人脸检测类实现
------------------------------------------------------------ */
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;

namespace Com.FirstSolver.FR
{
    public class TencentFr : FrCore
    {
        /// <summary>
        /// 厂家名称
        /// </summary>
        public override string Company { get { return "腾讯"; } }

        /// <summary>
        /// 应用标识
        /// </summary>
        private const string AppID = "1106795030";

        /// <summary>
        /// 应用密钥
        /// </summary>
        private const string AppKey = "7jpOpsC0iZDHqpOP";

        /// <summary>
        /// 人脸识别接口初始化
        /// </summary>
        /// <returns>
        ///     0-成功
        ///     其它-失败
        /// </returns>
        public override int Initialize()
        {
            ErrorMessage = null;
            return 0;
        }

        /// <summary>
        /// 人脸检测
        /// </summary>
        /// <param name="image">人脸图像数据</param>
        /// <param name="faceset">输出:人脸特征信息集合</param>
        /// <returns>
        ///     0:成功
        ///     -1:失败
        ///     -2:异常
        /// </returns>
        public override int Detect(byte[] image, out FFI[] faceset)
        {
            ErrorMessage = null;
            faceset = null;

            try
            {
                string options = CreateFaceDetectParameters(image, AppID, AppKey);
                var result = DoHttpPost("https://api.ai.qq.com/fcgi-bin/face/face_detectface", options);

                int ErrorCode = (int)result["ret"];
                if (ErrorCode != 0)
                {
                    ErrorMessage = result["msg"].ToString();
                    return -1;
                }
                else
                {
                    JArray FaceJArray = result["data"]["face_list"] as JArray;
                    if (FaceJArray.Count == 0)
                    {
                        ErrorMessage = "未检测出人脸";
                        return -1; // 人脸检测失败
                    }

                    List<FFI> FaceCollection = new List<FFI>();
                    foreach (dynamic item in FaceJArray)
                    {
                        FFI face = new FFI();

                        // 显示人脸框及特征点
                        face.Region = new Rectangle((int)item["x"], (int)item["y"], (int)item["width"], (int)item["height"]);

                        List<Point> FeaturePoints = new List<Point>();

                        // 描述脸型轮廓的21点
                        foreach (dynamic point in item["face_shape"]["face_profile"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述左眼轮廓的8点
                        foreach (dynamic point in item["face_shape"]["left_eye"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述右眼轮廓的8点
                        foreach (dynamic point in item["face_shape"]["right_eye"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述左眉轮廓的8点
                        foreach (dynamic point in item["face_shape"]["left_eyebrow"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述右眉轮廓的8点
                        foreach (dynamic point in item["face_shape"]["right_eyebrow"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述嘴巴轮廓的22点
                        foreach (dynamic point in item["face_shape"]["mouth"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        // 描述鼻子轮廓的13点
                        foreach (dynamic point in item["face_shape"]["nose"])
                        {
                            FeaturePoints.Add(new Point((int)point["x"], (int)point["y"]));
                        }

                        face.FeaturePoints = FeaturePoints.ToArray();
                        FaceCollection.Add(face);
                    }

                    faceset = FaceCollection.ToArray();
                    return 0; // 成功
                }
            }
            catch (Exception e)
            {
                ErrorMessage = e.Message;
                return -2; // 异常
            }
        }

        /// <summary>
        /// 创建人脸检测调用参数
        /// </summary>
        /// <param name="image">图像数据</param>
        /// <param name="appid">应用标识</param>
        /// <param name="appkey">应用密钥</param>
        /// <returns>人脸检测调用参数</returns>
        public static string CreateFaceDetectParameters(byte[] image, string appid, string appkey)
        {
            SortedDictionary<string, string> options = new SortedDictionary<string, string>();

            // 专有参数
            options.Add("image", Convert.ToBase64String(image)); // 原始图片的Base64编码数据(原图大小上限1MB,支持JPG、PNG、BMP格式)
            options.Add("mode", "0"); // 检测模式,0-正常,1-大脸模式(默认1)

            // 通用参数
            options.Add("app_id", appid); // 应用标识(AppId)            
            options.Add("time_stamp", ((DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks) / 10000000).ToString()); // 请求时间戳(秒级)
            options.Add("nonce_str", new Random().Next().ToString("X")); // 非空且长度上限32字节

            // 计算签名
            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, string> item in options)
            {
                if (!string.IsNullOrEmpty(item.Value))
                {
                    sb.Append(item.Key).Append('=').Append(FrCore.UrlEncode(item.Value, Encoding.UTF8, true)).Append('&');
                }
            }

            string source = sb.ToString();
            byte[] hash = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(source + "app_key=" + appkey));

            // 返回人脸检测参数
            return source + "sign=" + FrCore.ToHexString(hash, true);
        }

        /// <summary>
        /// 获取人脸检测结果
        /// </summary>
        /// <param name="url">人脸检测访问接口</param>
        /// <param name="options">人脸检测参数</param>
        /// <returns>人脸检测结果</returns>
        public static JObject DoHttpPost(string url, string options)
        {
            HttpWebRequest httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
            if (httpWebRequest == null) return null;

            httpWebRequest.Method = "POST";
            httpWebRequest.KeepAlive = true;
            httpWebRequest.ContentType = "application/x-www-form-urlencoded"; // 内容类型

            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());
                }
            }
        }
    }
}

Comments are closed.