UnityC#接入百度SDK实现人脸融合

Unity版本:2020.3.25,VisualStudio版本:2022;
1:注册登录百度账号
2: 在搜索窗口输入人脸融合,并进入人脸融合页面;
在这里插入图片描述
在这里插入图片描述
3:选择立即使用进入控制台-创建应用-(应用名称你随意,接口选择全部,没有领取的可以领取新人福利);创建完后点击该应用,准备好复制你的各种Key;
4:新建Unity工程,新建脚本AccessToken.cs 将百度api中人脸融合APIToken请求方法选择C#代码复制到该脚本中。

 using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using UnityEngine;
using UnityEngine.UI;
public static class AccessToken 
{
    // 调用getAccessToken()获取的 access_token建议根据expires_in 时间 设置缓存 
    public static String TOKEN = "24.adda70c11b9786206253ddb70affdc46.2592000.1493524354.282335-1234567";
 

    public static String getAccessToken(String clientId, String clientSecret)
    {
        String authHost = "https://aip.baidubce.com/oauth/2.0/token";
        HttpClient client = new HttpClient();
        List<KeyValuePair<String, String>> paraList = new List<KeyValuePair<string, string>>();
        paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
        paraList.Add(new KeyValuePair<string, string>("client_id", clientId));
        paraList.Add(new KeyValuePair<string, string>("client_secret", clientSecret));

        HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
        String result = response.Content.ReadAsStringAsync().Result; 
        return result;
    }
    // 人脸融合   注意版本。2.0版本是官网示例中的Demo效果,如果接口不定义版本,则默认为1.0,效果不佳。这里使用3.0
    public static string faceMerge(string token, string image1, string image2)
    {
        // string token = "[调用鉴权接口获取的token]";
        string host = "https://aip.baidubce.com/rest/2.0/face/v1/merge?access_token=" + token;
        Encoding encoding = Encoding.Default;
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
        request.Method = "post";
        request.KeepAlive = true;
        String str = "{\"version\": \"3.0\",\"image_template\":{\"image\":\"" + image1 + "\",\"image_type\":\"BASE64\",\"quality_control\":\"NONE\"},\"image_target\":{\"image\":\"" + image2 + "\",\"image_type\":\"BASE64\",\"quality_control\":\"NONE\"}}";
        byte[] buffer = encoding.GetBytes(str);
        request.ContentLength = buffer.Length;
        request.GetRequestStream().Write(buffer, 0, buffer.Length);
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
        string result = reader.ReadToEnd(); 
        return result;
    } 
}

5: 获取电脑摄像头脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; 
 
public class OpenCamera : MonoBehaviour
{
    public RawImage showImage; 
    private WebCamTexture webCamTexture;

    void Start()
    {
        StartCoroutine("IOpenCamera");
    }

    /// <summary>
    /// 打开摄像机
    /// </summary> 
    public IEnumerator IOpenCamera()
    {  
        yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
        if (Application.HasUserAuthorization(UserAuthorization.WebCam))
        {
            if (webCamTexture != null)
            {
                webCamTexture.Stop();
            }

            //打开渲染图
            if (showImage != null)
            {
                showImage.gameObject.SetActive(true);
            }
            //if (quad != null)
            //{
            //    quad.gameObject.SetActive(true);
            //}

            // 监控第一次授权,是否获得到设备(因为很可能第一次授权了,但是获得不到设备,这里这样避免)
            // 多次 都没有获得设备,可能就是真没有摄像头,结束获取 camera
            int i = 0;
            while (WebCamTexture.devices.Length <= 0 && 1 < 300)
            {
                yield return new WaitForEndOfFrame();
                i++;
            }
            WebCamDevice[] devices = WebCamTexture.devices;//获取可用设备
            if (WebCamTexture.devices.Length <= 0)
                Debug.LogError("没有获取到摄像头设备!");
            else
            {
                string devicename = devices[0].name;
                webCamTexture = new WebCamTexture(devicename, 640,480, 30)
                {
                    wrapMode = TextureWrapMode.Repeat
                };

                // 渲染到 UI  
                if (showImage != null)
                    showImage.texture = webCamTexture;

                webCamTexture.Play();
            }

        }
        else
            Debug.LogError("未获得读取摄像头权限");
    }

    private void OnApplicationPause(bool pause)
    {
        // 应用暂停的时候暂停camera,继续的时候继续使用
        if (webCamTexture != null)
        {
            if (pause)
            {
                webCamTexture.Pause();
            }
            else
            {
                webCamTexture.Play();
            }
        }

    } 
    private void OnDestroy()
    {
        if (webCamTexture != null)
        {
            webCamTexture.Stop();
        }
    }
}

6:工具类脚本以及数据结构

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;

using UnityEngine;

using ZXing.QrCode;
using ZXing;

public class Config
{
    public static Dictionary<string,Texture2D> maleModen = new Dictionary<string, Texture2D>();
    public static Dictionary<string, Texture2D> femaleModen = new Dictionary<string, Texture2D>();
    public static List<Sprite> covers = new List<Sprite>();
    public static KeyBaiDu baiDuKey = null;
    //public static string MODEN_TEXTURE2D=null;
    public static string APP_PATH =Application.streamingAssetsPath;
    public const string TARGET_PATH = @"D:\Program Files (x86)\DeskTop\Demo\TestTexture\";
    public static string SAVEMY_TEXTURE = string.Format("{0}MyPhoto.png", Config.TARGET_PATH);
    public static Transform GetChildTrs(Transform parent,string childName) 
    {
        for (int i = 0; i < parent.childCount; i++)
            if (parent.GetChild(i).name == childName)
                return parent.GetChild(i);
        return null;
    }
    /// <summary>
    /// 返回图片纹理
    /// </summary>
    /// <param name="_strImagePath"></param>
    /// <returns></returns>
    public static Texture2D GetTexture2d(string _strImagePath)
    {
        Texture2D tx = new Texture2D(100, 100);
        tx.LoadImage(GetImageByte(_strImagePath));
       // Sprite sp = Sprite.Create(tx, new Rect(0, 0, tx.width, tx.height), Vector2.zero);
        return tx;
    }

    /// <summary>  
    /// 根据图片路径返回图片的字节流byte[]  
    /// </summary>  
    /// <param name="imagePath">图片路径</param>  
    /// <returns>返回的字节流</returns>  
    public static byte[] GetImageByte(string imagePath)
    {
        FileStream files = new FileStream(imagePath, FileMode.Open);
        byte[] imgByte = new byte[files.Length];
        files.Read(imgByte, 0, imgByte.Length);
        files.Close();
        return imgByte;
    }
    public static void SaveTexture(Texture2D png, string pngName)
    {
        byte[] bytes = png.EncodeToPNG();

        FileStream file = File.Open(Config.APP_PATH + "/" + pngName + ".png", FileMode.Create);
        BinaryWriter writer = new BinaryWriter(file);
        writer.Write(bytes);
        file.Close();
    }
    public static void SaveTexture(Texture2D png, string path, string pngName)
    {
        byte[] bytes = png.EncodeToPNG();

        FileStream file = File.Open(path + "/" + pngName + ".png", FileMode.Create);
        BinaryWriter writer = new BinaryWriter(file);
        writer.Write(bytes);
        file.Close();
    }
    /// <summary>
    /// base64编码文本转换成Texture
    /// </summary> 
    public static Texture2D Base64ToTexter2d(string Base64STR)
    {
        Texture2D pic = new Texture2D(200, 200);
        byte[] data = System.Convert.FromBase64String(Base64STR);
        //File.WriteAllBytes(Application.dataPath + "/BuildImage/Base64ToSaveImage.png", data);
        pic.LoadImage(data);
        return pic;
    }
    /// <summary>
    /// 图片转换为Base64字符
    /// </summary>
    /// <param name="texture2D"></param>
    /// <returns></returns>
    public static string ImgToBase64String(Texture2D texture2D)
    {
        byte[] buffer = GetBytesFromTexture(texture2D);
        string base64String = Convert.ToBase64String(buffer);
        return base64String;
    }
    /// <summary>
    /// 图片转换为byte数据
    /// </summary>
    /// <param name="texture2D"></param>
    /// <returns></returns>
    public static byte[] GetBytesFromTexture(Texture2D texture2D)
    {
        RenderTexture renderTex = RenderTexture.GetTemporary(
                    texture2D.width,
                    texture2D.height,
                    0,
                    RenderTextureFormat.Default,
                    RenderTextureReadWrite.Linear);

        Graphics.Blit(texture2D, renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;
        Texture2D readableText = new Texture2D(texture2D.width, texture2D.height);
        readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
        readableText.Apply();
        byte[] bytes = readableText.EncodeToJPG();
        return bytes;
    } 
}
/// <summary>
/// 百度人脸接口Token数据结构
/// </summary>
[Serializable]
public class BaiduAPIKey
{
    public string refresh_token { get; set; }
    public string expires_in { get; set; }
    public string session_key { get; set; }
    public string access_token { get; set; }
    public string scope { get; set; }
    public string session_secret { get; set; }
}
/// <summary>
/// 百度接口人脸识别接口数据返回
/// </summary>
[Serializable]
public class FaceMergeResult
{
    public string error_code { get; set; }
    public string error_msg { get; set; }
    public string log_id { get; set; }
    public string timestamp { get; set; }
    public string cached { get; set; }
    public ResultData result { get; set; }
}

7:接口调用

 private string token = null;
 FaceMergeResult faceMergeResult = null;  
  aPIKey = JsonConvert.DeserializeObject<BaiduAPIKey>(AccessToken.getAccessToken(Config.baiDuKey.apiKey, Config.baiDuKey.secretKey));
            token = aPIKey.access_token;
    /// <summary>
    /// 使用异步方式获取百度接口返回结构。同步可以使用Loading进度条等待此结果返回
    /// </summary>
    /// <returns></returns>     
  private Task<string> GetWWWTexture()
    {
        var task = Task.Run(() => {
            var imageBase1 = AccessToken.ImgToBase64String(targetTexbyte);//AccessToken.ImgToBase64String(String.Format("{0}/{1}.png", Config.TARGET_PATH, "MyPhoto"));
            var imageBase2 = AccessToken.ImgToBase64String(modenTexbyte);//AccessToken.ImgToBase64String(String.Format("{0}/{1}.png", Config.APP_PATH, "moden"));//Config.MODEN_TEXTURE2D));  
            var reslut = AccessToken.faceMerge(token, imageBase2, imageBase1); 
            return reslut;
        });
        return task;
    }
      /// <summary>
    /// 等待结果处理相关逻辑
    /// </summary>
    async void ChangeFace()
    {
        var ttt = GetWWWTexture(); 
        await ttt; 
        faceMergeResult = JsonConvert.DeserializeObject<FaceMergeResult>(ttt.Result);
        print(faceMergeResult.error_code);

        if (faceMergeResult != null&&faceMergeResult.error_code == "0")
        {
            var texture = AccessToken.Base64ToTexter2d(faceMergeResult.result.merge_image);
            showImage.texture = texture;
            showImage.GetComponent<RectTransform>().anchoredPosition = Vector2.zero;
            byte[] bytes = texture.EncodeToPNG();
            System.IO.File.WriteAllBytes(Config.SAVEMY_TEXTURE, bytes);
            showImage.SetNativeSize();
            showImage.transform.position = ShowImagePos.position;
            //showImage.transform.position = new Vector3(temppos.x, temppos.y-80, temppos.z);
            UIMgr.Instance.HidePanel("PageWait");
            Config.GetChildTrs(buttons, "SaveBtn").GetComponent<Button>().interactable = true;
        }
        else
        {
            try
            {
                UIMgr.Instance.HidePanel("PageWait");
                switch (int.Parse(faceMergeResult.error_code))
                {
                    case 223114:
                    case 223113:
                    case 222301:
                    case 222203:
                    case 222211:
                    case 222202:
                        SetErrorTextValue("无法检测人脸,请不要遮挡脸部!");
                        break;
                    case 222204:
                        SetErrorTextValue("下载图片失败,请再次重试!");
                        break;
                    case 222205:
                    case 222206:
                        SetErrorTextValue("服务端请求失败,请联系工作人员!");
                        break;   
                    default:
                        SetErrorTextValue("未知异常,请联系工作人员!");
                        break;
                }
            }
            catch (Exception e)
            {
                print(e.Message);
            }
        }
    }

本文到此讲解结束,欢迎各位大佬提出宝贵意见以及建议。有项目需求合作也可以加QQ516172386 !!!

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有点朦

您的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值