Unity调用Face++ 人脸识别 Detect API

Face++提供的 人脸识别 SDK 和 公开的API 可以实现精确的人脸识别,返回多达106个识别点,是目前市面上非常理想的人脸识别产品。这里记录一下 通过Unity 使用c# 调用Face++的detect API的过程。

首先申请Face++账号,创建应用、绑定BundleID(BundleID 与 unity 中PlaySetting的Package Name 保持一致)等必备条件,具体步骤 在Face++的官网上有详细流程点击打开链接,对于Detect API的调用参数介绍等点击打开链接。

调用代码:静态类 HttpHelper4MultipartForm

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using UnityEngine;

namespace MgLiveCOM_Eyes
{
    public static class HttpHelper4MultipartForm 
    {
        public class FileParameter
        {
            public byte[] File
            {
                get;
                set;
            }

            public string FileName
            {
                get;
                set;
            }

            public string ContentType
            {
                get;
                set;
            }

            public FileParameter(byte[] file) : this(file, null)
            {
            }

            public FileParameter(byte[] file, string filename) : this(file, filename, null)
            {
            }

            public FileParameter(byte[] file, string filename, string contenttype)
            {
                this.File = file;
                this.FileName = filename;
                this.ContentType = contenttype;
            }
        }
        private static readonly Encoding encoding = Encoding.UTF8;
        /// 
        /// MultipartForm请求
        /// 
        /// 服务地址
        /// 
        /// 参数
        /// 
        public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary postParameters)
        {
            string text = string.Format("----------{0:N}", Guid.NewGuid());
            string contentType = "multipart/form-data; boundary=" + text;//multipart类型
            Debug.Log("contentType " + contentType);
            byte[] multipartFormData = GetMultipartFormData(postParameters, text);
            return PostForm(postUrl, userAgent, contentType, multipartFormData);
        }

        private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
        {
            HttpWebRequest httpWebRequest = WebRequest.Create(postUrl) as HttpWebRequest;
            if (httpWebRequest == null)
            {
                throw new NullReferenceException("request is not a http request");
            }

            httpWebRequest.Method = "POST";//post方式
            httpWebRequest.SendChunked = false;
            httpWebRequest.KeepAlive = true;
            httpWebRequest.Proxy = null;
            httpWebRequest.Timeout = Timeout.Infinite;
            httpWebRequest.ReadWriteTimeout = Timeout.Infinite;
            httpWebRequest.AllowWriteStreamBuffering = false;
            httpWebRequest.ProtocolVersion = HttpVersion.Version11;
            httpWebRequest.ContentType = contentType;
            httpWebRequest.CookieContainer = new CookieContainer();
            httpWebRequest.ContentLength = (long)formData.Length;

            try
            {
                using (Stream requestStream = httpWebRequest.GetRequestStream())
                {
                    int bufferSize = 4096;
                    int position = 0;

                    while (position < formData.Length)
                    {
                        bufferSize = Math.Min(bufferSize, formData.Length - position);
                        byte[] data = new byte[bufferSize];
                        Array.Copy(formData, position, data, 0, bufferSize);
                        requestStream.Write(data, 0, data.Length);
                        position += data.Length;
                    }
                    requestStream.Close();
                }
            }
            catch (Exception ex)
            {
                return null;
            }

            HttpWebResponse result;
            try
            {
                result = (httpWebRequest.GetResponse() as HttpWebResponse);
            }
            catch (WebException arg_9C_0)
            {
                result = (arg_9C_0.Response as HttpWebResponse);
            }
            return result;
        }

        public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        }
        /// 
        /// 从表单中获取数据
        /// 
        /// 
        /// 
        /// 
        private static byte[] GetMultipartFormData(Dictionary postParameters, string boundary)
        {
            Stream stream = new MemoryStream();
            bool flag = false;
            foreach (KeyValuePair current in postParameters)
            {
                if (flag)
                {
                    stream.Write(encoding.GetBytes("\r\n"), 0, encoding.GetByteCount("\r\n"));
                }
                flag = true;
                if (current.Value is FileParameter)
                {
                    FileParameter fileParameter = (FileParameter)current.Value;
                    string s = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: {3}\r\n\r\n", new object[]
                    {
                        boundary,
                        current.Key,
                        fileParameter.FileName ?? current.Key,
                        fileParameter.ContentType ?? "application/octet-stream"
                    });
                    stream.Write(encoding.GetBytes(s), 0, encoding.GetByteCount(s));
                    stream.Write(fileParameter.File, 0, fileParameter.File.Length);
                    Debug.Log("s1 " + s);
                }
                else
                {
                    string s2 = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\";\r\n\r\n{2}", boundary, current.Key, current.Value);
                    Debug.Log("s2 " + s2);
                    stream.Write(encoding.GetBytes(s2), 0, encoding.GetByteCount(s2));
                   
                }
            }
            string s3 = "\r\n--" + boundary + "--\r\n";
            Debug.Log("s3 " + s3);
            stream.Write(encoding.GetBytes(s3), 0, encoding.GetByteCount(s3));
            stream.Position = 0L;
            byte[] array = new byte[stream.Length];
            stream.Read(array, 0, array.Length);
            stream.Close();
            Debug.Log("array " + array.Length);
            return array;
        }
    }
}

具体调用类:Test

using System.Collections.Generic;
using UnityEngine;
using System.Net;
using MgLiveCOM_Eyes;
using System.IO;
using System;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Text;

public class Test : MonoBehaviour {
    //参数字典
    Dictionary verifyPostParameters = new Dictionary();

    public void TestFunc()
    {
        verifyPostParameters.Add("api_key", "MyKey");
        verifyPostParameters.Add("api_secret", "MySecret");
        verifyPostParameters.Add("return_landmark", "1");
        verifyPostParameters.Add("return_attributes", "gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus");
        byte[] fileImage = GetPictureData(Application.dataPath + "/Images/test0.jpg");
       
        //string base64S = ToBase64();
        // 使用参数 image _base64
        //verifyPostParameters.Add("image_base64", base64S);
        // 使用参数 image_file
         verifyPostParameters.Add("image_file", new HttpHelper4MultipartForm.FileParameter(fileImage, "1.jpg", "application/octet-stream"));
        // 使用参数 image_url
        // verifyPostParameters.Add("image_url", "http://yutoar-test.oss-cn-shenzhen.aliyuncs.com/test/girl.jpg");

        // test
        ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
        HttpWebResponse verifyResponse = HttpHelper4MultipartForm.MultipartFormDataPost("https://api-cn.faceplusplus.com/facepp/v3/detect", "", verifyPostParameters);
       
        if (verifyResponse != null)
        {
            StreamReader sr = new StreamReader(verifyResponse.GetResponseStream(), Encoding.UTF8);
            string sReturn = sr.ReadToEnd().Trim();
            Debug.Log("  " + sReturn);
            sr.Close();
        }
        else
            Debug.Log("返回数据为空!");
    }

    //转化图片为字节数组
    private byte[] GetPictureData(string imagePath)
    {
        FileStream fs = new FileStream(imagePath,FileMode.Open);
        byte[] byData = new byte[fs.Length];
        fs.Read(byData,0,byData.Length);
        fs.Close();
       
        return byData;
    }

    /// 
    /// 将图片数据转换为Base64字符串
    /// 
    /// 
    /// 
    private string ToBase64()
    {
        byte[] bytes = GetPictureData(Application.dataPath + "/Images/test1.jpg");
       
        string base64 = Convert.ToBase64String(bytes);
        return base64;
    }

    public bool MyRemoteCertificateValidationCallback(System.Object sender,
    X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        bool isOk = true;
        // If there are errors in the certificate chain,
        // look at each error to determine the cause.
        if (sslPolicyErrors != SslPolicyErrors.None)
        {
            for (int i = 0; i < chain.ChainStatus.Length; i++)
            {
                if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
                {
                    continue;
                }
                chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
                bool chainIsValid = chain.Build((X509Certificate2)certificate);
                if (!chainIsValid)
                {
                    isOk = false;
                    break;
                }
            }
        }
        return isOk;
    }

}

具体代码如上,与官网给出的代码差不多,直接使用官网代码在静态类的 PostForm的catch中会抛出异常,返回空,异常信息如下 “The authentication or decryption has failed”,

解决方案 在一个国外的网站上找到了,记录一下  点击打开链接

首先需要添加两个using 引用:
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

然后增加一个方法:

  public bool MyRemoteCertificateValidationCallback(System.Object sender,
    X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
    {
        bool isOk = true;
        // If there are errors in the certificate chain,
        // look at each error to determine the cause.
        if (sslPolicyErrors != SslPolicyErrors.None)
        {
            for (int i = 0; i < chain.ChainStatus.Length; i++)
            {
                if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
                {
                    continue;
                }
                chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
                chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
                chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
                chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
                bool chainIsValid = chain.Build((X509Certificate2)certificate);
                if (!chainIsValid)
                {
                    isOk = false;
                    break;
                }
            }
        }
        return isOk;
    }

最后在调用post请求之前 添加这句代码

 ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

就可以正常调用API啦~

从返回的HttpWebResponse 类型数据中 取出返回信息:

StreamReader sr = new StreamReader(verifyResponse.GetResponseStream(), Encoding.UTF8);
 string sReturn = sr.ReadToEnd().Trim();

完结~




你可能感兴趣的:(Unity调用Face++ 人脸识别 Detect API)