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.抠像效果

抠像效果一般,边缘还是会生硬,然后用羽化来过渡。(如图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 常用字符

cs 复制代码
 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转换成httpContent
     HttpResponseMessage response = client.PostAsync(token_url, new FormUrlEncodedContent(paraList)).Result;
     //最后接受回复,转换成string
     string resultJson = response.Content.ReadAsStringAsync().Result;
     //打印一下string
     Debug.Log(resultJson);
 }

打印结果为:
图5 打印结果

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

4.解析json

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

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

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

cs 复制代码
        //先读取json格式的文本
        JsonReader json = new JsonReader(resultJson);
        //把上面读取的文本转换成可以直接调用的数据格式
        JsonData jsonData = JsonMapper.ToObject<JsonData>(json);
        //直接获取名称是access_token后面的数据        
        jsonData["access_token"].ToString();
5.完整代码
cs 复制代码
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 = "填自己的密码";

    //token
    public 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

cs 复制代码
    //Texture转Texture2D
    private 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

cs 复制代码
    //texture2D转base64
    public string TextureToBase64(Texture2D texture2D)
    {
        byte[] bytes;
        bytes = texture2D.EncodeToPNG();
        return Convert.ToBase64String(bytes);
    }

方法3:Base64转texture2D

cs 复制代码
    //base转texture2D
    public 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

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

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

cs 复制代码
//获取图片并转换成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.开始上传
cs 复制代码
//获取长度
request.ContentLength = buffer.Length;
//发送请求
request.GetRequestStream().Write(buffer, 0, buffer.Length);
5.获取回复
cs 复制代码
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
string result = reader.ReadToEnd();
Debug.Log("人像分割:" + result);
6.解析json
cs 复制代码
JsonReader jr = new JsonReader(result);
JsonData data = JsonMapper.ToObject<JsonData>(jr);

//拿到的扣好的数据
string picData = data["foreground"].ToString();
Texture2D tex = Base64ToTexture2d(picData);
7.纯净代码
cs 复制代码
 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;

 }

四、作者的碎碎念

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

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

相关推荐
artificiali2 小时前
Anaconda配置pytorch的基本操作
人工智能·pytorch·python
酱香编程,风雨兼程3 小时前
深度学习——基础知识
人工智能·深度学习
Lossya3 小时前
【机器学习】参数学习的基本概念以及贝叶斯网络的参数学习和马尔可夫随机场的参数学习
人工智能·学习·机器学习·贝叶斯网络·马尔科夫随机场·参数学习
#include<菜鸡>4 小时前
动手学深度学习(pytorch土堆)-04torchvision中数据集的使用
人工智能·pytorch·深度学习
躺下睡觉~4 小时前
Unity-Transform类-父子关系
java·unity·游戏引擎
程序员-杨胡广4 小时前
从0-1 用AI做一个赚钱的小红书账号(不是广告不是广告)
人工智能
躺下睡觉~4 小时前
Unity-Transform类-缩放和看向
unity·游戏引擎
AI进修生4 小时前
全新WordPress插件简化成功之路
人工智能·语言模型·自然语言处理
GG_Bond194 小时前
【项目设计】Facial-Hunter
服务器·人工智能
chnyi6_ya5 小时前
深度学习的笔记
服务器·人工智能·pytorch