当前位置: 首页 > news >正文

Unity 百度AI实现无绿幕拍照抠像功能(详解版)

目录

一、前言

1.抠像效果

2.去哪找百度ai抠图

3.基础流程跳过 

二、获取AccessToken

1.什么是Token

2.为什么要获取Token

3.如何获取token

4.解析json

5.完整代码

三、抠像

1.准备地址

2.建立链接,和基本配置

3.图片格式转换

4.开始上传

5.获取回复

6.解析json

7.纯净代码

四、作者的碎碎念

五、常见问题

1.WWWForm写法


一、前言

1.抠像效果

抠像效果一般,边缘还是会生硬,然后用羽化来过渡。(如图1所示)

图1 抠像

这是网上找的图,侵权删。

2.去哪找百度ai抠图

在百度,这个功能叫人像分割,链接如下。

人像分割技术_人像分割算法_人像分割-百度AI开放平台

3.基础流程跳过 

接下来注册账号之类的,咱就跳过了哈。

过程:
1.注册百度的账号

2.实名认证

3.领百度送的,对应功能的使用次数(我测试的时候送1w次,有效期一年)。

4.创建应用(这个不需要你有做好的程序,只需要走一下流程就行),这里走流程的意义就是,百度有很多功能,你需要什么功能选一下,然后我们给你一个账户和密码,这样你才能调用这些功能。

5.你就获得了一组账户和密码(如图2所示)

图2 账号和密码

api Key和Secret Key

api Key:api的英文是Application Programming Interface,应用程序编程接口的缩写,到这里就是我们获取了可以用来实现人像分割这个功能的用户名。

Secret Key:就是秘钥,上面用户名的密码。

上面两个Key,只要你自己不去更新,一般是不会改变的

但是,如果你的调用行为百度觉得很奇怪,也会暂时给你封了。

备注:百度ai有很多功能,假如百度ai是一个手机,手机里面装了很多个app,但是你登录每一个app都需要不同的用户名和密码。

这里就是,我们通过百度这个总的账号,去选择了自己想要的功能,然后百度给你生成一个用户名和密码,你通过这个可以使用你选好的功能。

二、获取AccessToken

1.什么是Token

不知道大家去过东北澡堂子没有,进去的时候,会被发一个手牌。(如图3所示)

图3 手牌

然后你只要带着这个手牌,就可以在澡堂子里吃饭,消费等,最后出来的时候,带着手牌去结账就行了。不同的手牌会有不同的权限,比如普通宾客,贵宾,vip,超级vip什么的。手牌上面还会有号码,号码就类似身份证号一样,大家都不一样,用来识别。

弄这个手牌的目的大致有两种:

1.澡堂子里有很多水,一直带着手机很麻烦,但不带手机,又会不知道你是哪一个宾客。

2.手机不能直观的看出来你是哪种宾客,但是牌子可以。

Token和这个手牌基本是一样的,你先把自己的账号和密码上交,根据你购买的套餐,会给你一串序列号,在一定的时间内,你只要提交序列号就可以用你购买的功能,百度也知道是哪个账号购买的。

2.为什么要获取Token

我们可以直接用账号和密码访问,我们也能使用token访问,但是,因为是用互联网传递消息,如果用账号和密码,那你每一次提出请求都要提供账户和密码,这样不是很安全,黑客一拦截一个准,所以,换成token,就减少了提交用户和密码的次数,就安全很多。

可以简单这么理解一下,至于细致的,大家可以自行百度,但总之,有这么一个流程。

3.如何获取token

这个可以在百度的官方文档中找到。在百度,这部分官方的名称叫做鉴权认证机制。

https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu

想看官方的可以看官方的,或者看我的也可以。

获取token需要三个东西:

1.往哪个网站发请求

(上面的官方链接里有写,往https://aip.baidubce.com/oauth/2.0/token?发请求)

2.用户名(前言里获取过)

3.密码(前言里获取过)

在代码里,我们可以先把他们写出来。

我们的目的是获取token,我们可以再建一个字符串用来接token。(如图4所示)

图4 常用字符
 void Start(){GetToken();}public void GetToken(){//声明一个客户端,就是自己HttpClient client = new HttpClient();//建立一个字典,把我们需要的信息都放进去//但是建立字典的类型是KeyValuePair,因为我们后面要传递数据List<KeyValuePair<String, String>> paraList = new List<KeyValuePair<string, string>>();paraList.Add(new KeyValuePair<string, string>("client_id", client_id));paraList.Add(new KeyValuePair<string, string>("client_secret", client_secret));paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));//这里本来要放httpContent,但是这个方法可以把//接受网络的回复                                               //keyValuePair转换成httpContentHttpResponseMessage response = client.PostAsync(token_url, new FormUrlEncodedContent(paraList)).Result;//最后接受回复,转换成stringstring resultJson = response.Content.ReadAsStringAsync().Result;//打印一下stringDebug.Log(resultJson);}

打印结果为:

图5 打印结果

你会得到一大堆数据,其中有一个部分是access_token,我们要的就是这部分,这部分就是token。

4.解析json

得到数据后,这个数据是json格式的数据,如果你会解析json数据,就可以自己解决了。

如果解决不了,你也可以采用string的手法直接弄出来。

up很懒,用了一个叫LitJson.dll,里面直接有解析的方法。

        //先读取json格式的文本JsonReader json = new JsonReader(resultJson);//把上面读取的文本转换成可以直接调用的数据格式JsonData jsonData = JsonMapper.ToObject<JsonData>(json);//直接获取名称是access_token后面的数据        jsonData["access_token"].ToString();
5.完整代码
using System;
using System.Collections.Generic;
using System.Net.Http;
using LitJson;
using UnityEngine;public class GetAccessToken : MonoBehaviour
{//网址string token_url = "https://aip.baidubce.com/oauth/2.0/token?";//用户名string client_id = "填自己的id";//密码string client_secret = "填自己的密码";//tokenpublic string token;void Start(){token = GetToken();Debug.Log("获得token:" + token);}public string GetToken(){HttpClient client = new HttpClient();List<KeyValuePair<String, String>> paraList = new List<KeyValuePair<string, string>>();paraList.Add(new KeyValuePair<string, string>("client_id", client_id));paraList.Add(new KeyValuePair<string, string>("client_secret", client_secret));paraList.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));HttpResponseMessage response = client.PostAsync(token_url, new FormUrlEncodedContent(paraList)).Result;string resultJson = response.Content.ReadAsStringAsync().Result;//Debug.Log(resultJson);JsonReader json = new JsonReader(resultJson);JsonData jsonData = JsonMapper.ToObject<JsonData>(json);return jsonData["access_token"].ToString();}
}

三、抠像

官方文档:https://ai.baidu.com/ai-doc/BODY/Fk3cpyxua

可以自己去研究,也可以往下看我的。

首先从官方那里拿到网址:

然后准备一下中途要用的方法(这些方法均不是重点,都不讲了)

方法1:图片从Texture转换到Texture2D

    //Texture转Texture2Dprivate Texture2D TextureToTexture2D(Texture texture){width = texture.width;height = texture.height;Texture2D texture2D = new Texture2D(texture.width, texture.height, TextureFormat.RGBA32, false);RenderTexture currentRT = RenderTexture.active;RenderTexture renderTexture = RenderTexture.GetTemporary(texture.width, texture.height, 32);Graphics.Blit(texture, renderTexture);RenderTexture.active = renderTexture;texture2D.ReadPixels(new Rect(0, 0, renderTexture.width, renderTexture.height), 0, 0);texture2D.Apply();RenderTexture.active = currentRT;RenderTexture.ReleaseTemporary(renderTexture);return texture2D;}

方法2:图片从Texture2D转换为Base64

    //texture2D转base64public string TextureToBase64(Texture2D texture2D){byte[] bytes;bytes = texture2D.EncodeToPNG();return Convert.ToBase64String(bytes);}

方法3:Base64转texture2D

    //base转texture2Dpublic Texture2D Base64ToTexture2d(string base64){byte[] bytes = Convert.FromBase64String(base64);Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);tex.LoadImage(bytes);return tex;}
1.准备地址

在前面给出地址的基础上,加上我们前面获取的token

//host地址
string host = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg?access_token=" + token;
2.建立链接,和基本配置
//设置编码格式是默认
Encoding encoding = Encoding.Default;
//发送请求到前面配好的网址
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
//这是前面要求的
request.Method = "post";
//一直保持链接
request.KeepAlive = true;
3.图片格式转换

这里假设我们有一个RawImage,名字叫photo,最后转换成buffer

//获取图片并转换成texture2D
Texture2D texture2D = TextureToTexture2D(photo.texture);
//再转换成base64
string base64 = TextureToBase64(texture2D);
//转换成url格式
string str = "image=" + HttpUtility.UrlEncode(base64);
//转换成byte格式
byte[] buffer = encoding.GetBytes(str);
4.开始上传
//获取长度
request.ContentLength = buffer.Length;
//发送请求
request.GetRequestStream().Write(buffer, 0, buffer.Length);
5.获取回复
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
string result = reader.ReadToEnd();
Debug.Log("人像分割:" + result);
6.解析json
JsonReader jr = new JsonReader(result);
JsonData data = JsonMapper.ToObject<JsonData>(jr);//拿到的扣好的数据
string picData = data["foreground"].ToString();
Texture2D tex = Base64ToTexture2d(picData);
7.纯净代码
 IEnumerator IBody_seg(){string host = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg?access_token=" + token;Encoding encoding = Encoding.Default;HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);request.Method = "post";request.KeepAlive = true;yield return null;Texture2D texture2D = TextureToTexture2D(photo.texture);string base64 = TextureToBase64(texture2D);string str = "image=" + HttpUtility.UrlEncode(base64);byte[] buffer = encoding.GetBytes(str);request.ContentLength = buffer.Length;request.GetRequestStream().Write(buffer, 0, buffer.Length);yield return null;HttpWebResponse response = (HttpWebResponse)request.GetResponse();StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);string result = reader.ReadToEnd();Debug.Log("人像分割:" + result);yield return null;JsonReader jr = new JsonReader(result);JsonData data = JsonMapper.ToObject<JsonData>(jr);string picData = data["foreground"].ToString();Texture2D tex = Base64ToTexture2d(picData);//如果你有个image,可以使用图片pic.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0, 0));pic2.sprite = pic.sprite;}

四、作者的碎碎念

如果有什么疑问,可以在评论区发出来讨论一下,我看见了会回复。

照片是直接在网上找的,侵权立删。

五、常见问题

1.WWWForm写法

以上写法来自百度官方写法,但还有一种常用写法叫做WWWForm,具体讲解在:

Unity C# 网络学习—WWWForm-CSDN博客

针对本篇文章,WWWForm的写法为:

由于是备用写法,就不细讲了

 IEnumerator IBody_seg(){//host地址string host = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_seg?access_token=" + token;Texture2D texture2D = TextureToTexture2D(photo.texture);string base64 = TextureToBase64(texture2D);//Form写法WWWForm form = new WWWForm();form.AddField("image", base64);form.AddField("type", "foreground");UnityWebRequest request = UnityWebRequest.Post(host, form);yield return request.SendWebRequest();if (request.result == UnityWebRequest.Result.ProtocolError|| request.result == UnityWebRequest.Result.ConnectionError|| request.result == UnityWebRequest.Result.DataProcessingError){Debug.LogError(request.error);}else{var result = request.downloadHandler.text;resultbody = JsonUtility.FromJson<ResultBody>(result);resultbody.t2d = Base64ToTexture2d(resultbody.foreground);}}

 


http://www.mrgr.cn/news/35155.html

相关文章:

  • 【分布式】CAP理论
  • JWT 过期后 自动刷新方案
  • Flutter开发者进阶:接入安卓原生页面
  • react 中 useEffect Hook 作用
  • Keithley吉时利2612B数字源表
  • Anaconda安装(2024最新版)
  • 统一建模语言(UML)在软件研发过程中常用图接受:类图、用例图、时序图、状态图、活动图、流程图、顺序图
  • 什么是BOM?
  • 【Kubernetes】常见面试题汇总(三十六)
  • Activiti7《第九式:破气式》——流畅驱动工作流进程。面试题大全
  • 牛客周赛 Round 61 (C++实现)
  • 在不牺牲质量的情况下压缩 WebP 图片大小的 3 种方法
  • CDA Level 1 考试成绩汇报
  • QT 中的信号与槽机制详解
  • 基于python+django+vue的电影数据分析及可视化系统
  • Redisson使用详解:一个强大的Redis Java客户端
  • Win11右键默认显示更多设置教程
  • linux sigprocmask函数
  • Voxel mamba :基于Mamba的3D目标检测算法解析
  • 设计模式之备忘录
  • C++ :借助栈完成二叉树的非递归遍历
  • word怎么加密?掌握这4种加密技巧,保护你的文件安全!
  • workerman 接入文心一言的流式输出
  • PHPMailer低版本用法(实例)
  • NLP自然语言处理
  • windows使用JEnv实现一键临时或全局切换java版本