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

同系列文章

/* ----------------------------------------------------------
 * 文件名称:MegviiFr.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.Text;

namespace Com.FirstSolver.FR
{
    public class MegviiFr : FrCore
    {
        /// <summary>
        /// 公司名称
        /// </summary>
        public override string Company { get { return "旷视科技"; } }

        /// <summary>
        /// 应用标识
        /// </summary>
        private const string API_KEY = "taGMgUCmjHZAukiP6IUQlFyhwzD9m0Dx";

        /// <summary>
        /// 应用密钥
        /// </summary>
        private const string API_SECRET = "7tGn92YATD307rEqhyTNqSKE9eV-0Akl";

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

        public override int Detect(byte[] image, out FFI[] faceset)
        {
            ErrorMessage = null;
            faceset = null;

            try
            {
                string options = CreateFaceDetectParameters(image, API_KEY, API_SECRET, out string contentType);
                var result = DoHttpPost("https://api-cn.faceplusplus.com/facepp/v3/detect", contentType, options);
                if (result["error_message"] != null)
                {
                    ErrorMessage = result["error_message"].ToString();
                    return -1; // 人脸检测失败
                }
                else
                {
                    JArray FaceJArray = result["faces"] as JArray;
                    if (FaceJArray.Count == 0)
                    {
                        ErrorMessage = "未检测出人脸";
                        return -1; // 人脸检测失败
                    }

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

                        // 显示人脸框及特征点
                        dynamic region = item["face_rectangle"];
                        face.Region = new Rectangle((int)region["left"], (int)region["top"], (int)region["width"], (int)region["height"]);

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

                        // 83个人脸关键点或者106个人脸关键点
                        foreach (dynamic point in item["landmark"])
                        {
                            dynamic value = point.First;
                            FeaturePoints.Add(new Point((int)value["x"], (int)value["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="apiKey">应用标识</param>
        /// <param name="apiSecret">应用密钥</param>
        /// <returns>参数字典</returns>
        private static string CreateFaceDetectParameters(byte[] image, string apiKey, string apiSecret, out string contentType)
        {
            Dictionary<string, object> options = new Dictionary<string, object>();
            options.Add("api_key", apiKey);
            options.Add("api_secret", apiSecret);
            options.Add("image_base64", Convert.ToBase64String(image));
            options.Add("return_landmark", "2"); // 是否检测并返回人脸关键点 0:不检测 1:83个人脸关键点 2:106个人脸关键点

            string boundary = string.Format("----------{0:N}", Guid.NewGuid()); // 内容分隔符
            contentType = "multipart/form-data; boundary=" + boundary;

            StringBuilder sb = new StringBuilder();
            foreach (KeyValuePair<string, object> item in options)
            {
                sb.Append(string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, item.Key, item.Value));
            }

            sb.Append("--" + boundary + "--\r\n");
            return sb.ToString();
        }

        private static JObject DoHttpPost(string url, string contentType, string options)
        {
            HttpWebRequest httpWebRequest = WebRequest.Create(url) as HttpWebRequest;
            if (httpWebRequest == null) return null;

            httpWebRequest.Method = "POST";
            httpWebRequest.KeepAlive = true;
            httpWebRequest.ContentType = contentType;

            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.