当前位置:   article > 正文

unity使用百度AI实现人脸融合_unity 百度人脸融合

unity 百度人脸融合

准备工作:前往百度AI网页注册账号,百度AI开放平台-全球领先的人工智能服务平台

在开放能力平台,能找到想要的功能介绍,然后要创建一个应用,需要用到ak和sk,百度AI开发里边介绍比较清楚,这里就不赘述了。

开发逻辑  调用摄像头 -> 截取一帧画面  -> 上传百度AI云融合  ->  返回融合结果显示

首先呢,需要创建一个WebCamera类,完善摄像头的各种功能。

  1. /// <summary>
  2. /// 简单的摄像头单例类,挂载在场景物体上
  3. /// </summary>
  4. public class WebCamera : MonoBehaviour
  5. {
  6. public static WebCamera Instance;
  7. /// <summary>
  8. /// 当前摄像头下标,存在多个摄像头设备时用于切换功能
  9. /// </summary>
  10. private int curCamIndex = 0;
  11. /// <summary>
  12. /// 所有摄像头设备列表
  13. /// </summary>
  14. private WebCamDevice[] devices;
  15. /// <summary>
  16. /// 摄像头渲染纹理
  17. /// </summary>
  18. private WebCamTexture webCamTex;
  19. /// <summary>
  20. /// 当前设备的名称
  21. /// </summary>
  22. public string deviceName { get; private set; }
  23. /// <summary>
  24. /// 摄像头是否打开
  25. /// </summary>
  26. public bool CameraIsOpen { get; private set; }
  27. /// <summary>
  28. /// 最终渲染画面
  29. /// </summary>
  30. public Texture renderTex { get; private set; }
  31. /// <summary>
  32. /// 最新的截图
  33. /// </summary>
  34. public Texture2D lastShotText { get; private set; }
  35. /// <summary>
  36. /// 画面的宽高
  37. /// </summary>
  38. private int width,height;
  39. /// <summary>
  40. /// 帧率
  41. /// </summary>
  42. private int fps;
  43. void Awake()
  44. {
  45. Instance = this;
  46. }
  47. public void InitCamera(int width,int height,int fps=30)
  48. {
  49. this.width = width;
  50. this.height = height;
  51. this.fps = fps;
  52. }
  53. /// <summary>
  54. /// 打开摄像头
  55. /// </summary>
  56. public void OpenCamera()
  57. {
  58. //用户授权
  59. if (Application.HasUserAuthorization(UserAuthorization.WebCam))
  60. {
  61. //显示画面的设备就是要打开的摄像头
  62. devices = WebCamTexture.devices;
  63. if (devices.Length <= 0)
  64. {
  65. Debug.LogError("没有检测到摄像头,检查设备是否正常"); return;
  66. }
  67. deviceName = devices[curCamIndex].name;
  68. webCamTex = new WebCamTexture(deviceName, width,height,fps);
  69. renderTex = webCamTex;
  70. //开启摄像头
  71. webCamTex.Play();
  72. CameraIsOpen = true;
  73. }
  74. }
  75. /// <summary>
  76. /// 关闭摄像头
  77. /// </summary>
  78. public void CloseCamera()
  79. {
  80. if (CameraIsOpen && webCamTex != null)
  81. {
  82. webCamTex.Stop();
  83. CameraIsOpen=false;
  84. }
  85. }
  86. /// <summary>
  87. /// 切换摄像头
  88. /// </summary>
  89. public void SwapCamera()
  90. {
  91. if (devices.Length > 0)
  92. {
  93. curCamIndex = (curCamIndex + 1) % devices.Length;
  94. if (webCamTex!= null)
  95. {
  96. CloseCamera();
  97. OpenCamera();
  98. }
  99. }
  100. }
  101. public void SaveScreenShot(string path)
  102. {
  103. Texture2D shotTex = TextureToTexture2D(webCamTex);
  104. lastShotText = shotTex;
  105. byte[] textureBytes = shotTex.EncodeToJPG();
  106. string fileName = string.Format("IMG_{0}{1}{2}_{3}{4}{5}.jpg",DateTime.Now.Year,DateTime.Now.Month,
  107. DateTime.Now.Day,DateTime.Now.Hour,DateTime.Now.Minute,DateTime.Now.Second);
  108. if (!Directory.Exists(path))
  109. {
  110. Directory.CreateDirectory(path);
  111. }
  112. Debug.Log($"图片已保存:{path}/{fileName}");
  113. File.WriteAllBytes($"{ path}/{fileName}", textureBytes);
  114. if (File.Exists($"{path}/{fileName}"))
  115. {
  116. Debug.Log("找到照片");
  117. }
  118. else
  119. {
  120. Debug.Log("未找到");
  121. }
  122. }
  123. /// <summary>
  124. /// Texture转换成Texture2D
  125. /// </summary>
  126. /// <param name="texture"></param>
  127. /// <returns></returns>
  128. private Texture2D TextureToTexture2D(Texture texture)
  129. {
  130. Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);
  131. RenderTexture currentRT = RenderTexture.active;
  132. RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);
  133. Graphics.Blit(texture, renderTexture);
  134. RenderTexture.active = renderTexture;
  135. texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);
  136. texture2D.Apply();
  137. RenderTexture.active = currentRT;
  138. RenderTexture.ReleaseTemporary(renderTexture);
  139. return texture2D;
  140. }
  141. }

创建一个脚本AssessToken,用来获取token,官网示例中返回的是一个token对象,需要再次解析。clientAK和clientSk需要写自己申请的应用的ak和sk

  1. public static class AccessToken
  2. {
  3. //调用GetAccessToken()获取的access_token建议根据expires_in时间 设置缓存
  4. //百度云中开通对应服务应用的API Key建议开通应用的时候多选服务
  5. private static string clientAk = "***********************";
  6. //百度云中开通对应服务应用的 Secret Key
  7. private static string clientSk = "****************************";
  8. public static string GetAssessToken()
  9. {
  10. string authHost = "https://aip.baidubce.com/oauth/2.0/token";
  11. HttpClient client = new HttpClient();
  12. List<KeyValuePair<string, string>> paraList = new List<KeyValuePair<string, string>>();
  13. paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
  14. paraList.Add(new KeyValuePair<string, string>("client_id", clientAk));
  15. paraList.Add(new KeyValuePair<string, string>("client_secret", clientSk));
  16. HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
  17. string result = response.Content.ReadAsStringAsync().Result;
  18. TokenInfo tokenInfo = JsonUtility.FromJson<TokenInfo>(result);
  19. return tokenInfo.access_token;
  20. }
  21. public class TokenInfo
  22. {
  23. public string refresh_token;
  24. public string access_token;
  25. }
  26. }

创建一个FaceMerge,用来请求人脸融合的API,当然也可以丰富更多的功能

  1. public class FaceMerge : MonoBehaviour
  2. {
  3. public static FaceMerge Instance;
  4. private void Awake()
  5. {
  6. Instance = this;
  7. }
  8. //人脸融合
  9. public void PostFaceMerge(string json, UnityAction<string> sucessResponse, UnityAction<string> errorRes = null)
  10. {
  11. StartCoroutine(IPostFaceMerge(json, sucessResponse, errorRes));
  12. }
  13. private IEnumerator IPostFaceMerge(string json, UnityAction<string> sucessResponse, UnityAction<string> errorRes = null)
  14. {
  15. string token = AccessToken.GetAssessToken();
  16. string url = "https://aip.baidubce.com/rest/2.0/face/v1/merge?access_token=" + token;
  17. using (UnityWebRequest request = new UnityWebRequest(url, "POST"))
  18. {
  19. Encoding encoding = Encoding.Default;
  20. byte[] buffer = encoding.GetBytes(json);
  21. request.uploadHandler = new UploadHandlerRaw(buffer);
  22. request.downloadHandler = new DownloadHandlerBuffer();
  23. yield return request.SendWebRequest();
  24. if (request.result == UnityWebRequest.Result.Success)
  25. {
  26. sucessResponse?.Invoke(request.downloadHandler.text);
  27. request.Abort();
  28. }
  29. else
  30. {
  31. errorRes?.Invoke(request.downloadHandler.text);
  32. request.Abort();
  33. }
  34. }
  35. }
  36. public Texture2D Base64ToTexture2D(int width,int height,string base64Str)
  37. {
  38. Texture2D pic = new Texture2D(width, height, TextureFormat.RGBA32, false);
  39. byte[] data = System.Convert.FromBase64String(base64Str);
  40. pic.LoadImage(data);
  41. return pic;
  42. }
  43. public string Texture2DToBase64(Texture2D tex2d)
  44. {
  45. byte[] bytes = tex2d.EncodeToJPG();
  46. string strBase64 = Convert.ToBase64String(bytes);
  47. return strBase64;
  48. }
  49. }

需要一个Response类反序列化返回的结果

  1. public class Response
  2. {
  3. public int error_code;
  4. public string error_msg;
  5. public long log_id;
  6. public long timestamp;
  7. public int cached;
  8. public Result result;
  9. }
  10. public class Result
  11. {
  12. public string merge_image;
  13. }

创建一个Test测试类,调试功能,里边json解析的时候,用到了一个JsonMapper的类,这个类是在LitJson插件中的,需要大家自行下载。

  1. public class Test : MonoBehaviour
  2. {
  3. /// <summary>
  4. /// 显示相机渲染的画面
  5. /// </summary>
  6. [SerializeField] RawImage rawImg;
  7. /// <summary>
  8. /// 融合模板图
  9. /// </summary>
  10. [SerializeField] Texture2D targetFusionTex;
  11. /// <summary>
  12. /// 融合结果显示
  13. /// </summary>
  14. [SerializeField] RawImage resultImg;
  15. /// <summary>
  16. /// 截图保存的路径
  17. /// </summary>
  18. private string path;
  19. void Start()
  20. {
  21. path = Application.streamingAssetsPath + "/";
  22. WebCamera.Instance.InitCamera(800,600);
  23. WebCamera.Instance.OpenCamera();
  24. rawImg.texture = WebCamera.Instance.renderTex;
  25. }
  26. private void FunsionFace()
  27. {
  28. WebCamera.Instance.SaveScreenShot(path);
  29. var curTex = WebCamera.Instance.lastShotText;
  30. //序列化字典内容到json格式 上传到百度ai
  31. Dictionary<string,object> dict = new Dictionary<string,object>();
  32. dict.Add("version","4.0");
  33. dict.Add("alpha",0);
  34. ImageInfo imgTemplate = new ImageInfo();
  35. imgTemplate.image = FaceMerge.Instance.Texture2DToBase64(targetFusionTex);
  36. imgTemplate.image_type = "BASE64";
  37. imgTemplate.quality_control = "NONE";
  38. dict.Add("image_template", imgTemplate);
  39. ImageInfo imgTarget = new ImageInfo();
  40. imgTarget.image = FaceMerge.Instance.Texture2DToBase64(curTex);
  41. imgTarget.image_type = "BASE64";
  42. imgTarget.quality_control = "NONE";
  43. dict.Add("image_target",imgTarget);
  44. dict.Add("merge_degree", "COMPLETE");
  45. string json = JsonMapper.ToJson(dict); // 反序列化用了 litjson的工具,使用JsonUtility序列化dict会是空的
  46. FaceMerge.Instance.PostFaceMerge(json, OnFaceMerge);
  47. }
  48. private void OnFaceMerge(string info)
  49. {
  50. Debug.Log(info);
  51. Response response = JsonMapper.ToObject<Response>(info);
  52. if (response.error_code == 0) // 0 表示成功融合图片
  53. {
  54. Debug.Log(response.error_msg);
  55. string ImgBase64 = response.result.merge_image;
  56. resultImg.texture = FaceMerge.Instance.Base64ToTexture2D(targetFusionTex.width, targetFusionTex.height, ImgBase64);
  57. }
  58. }
  59. void Update()
  60. {
  61. if (Input.GetKeyUp(KeyCode.W))
  62. {
  63. FunsionFace();
  64. }
  65. }
  66. public class ImageInfo
  67. {
  68. public string image; //图片信息
  69. public string image_type; //图片类型 BASE64 URL FACE_TOKEN
  70. public string quality_control; //质量控制 NONE LOW NORMAL HIGH HIGH
  71. }
  72. }

csdn资源链接地址:https://download.csdn.net/download/qq_40666661/87704717不需要积分就可以下载

百度网盘:链接:https://pan.baidu.com/s/1LTqsc8bxf69RZAWWB9Nw0Q?pwd=heyo 
提取码:heyo 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/123525?site
推荐阅读
相关标签
  

闽ICP备14008679号