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

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 常用字符
 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,里面直接有解析的方法。

        //先读取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 = "填自己的密码";

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

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

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

方法3:Base64转texture2D

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

//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;

 }

四、作者的碎碎念

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

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


http://www.kler.cn/news/309924.html

相关文章:

  • Flask-JWT-Extended登录验证
  • 构建常态化安全防线:XDR的态势感知与自动化响应机制
  • python学习笔记目录
  • JS全选反选案例
  • 海杂波分级方法
  • springboot项目中 前端浏览器访问时遇到跨域请求问题CORS怎么解决?has been blocked by CORS policy
  • 【UEFI基础】BIOS模块执行的优先级
  • 集成网口连接器国产化替代--RJ45内置网络变压器网口生产工厂在行动
  • HarmonyOS学习(十一)——安全管理
  • 说说synchronized的锁升级过程
  • 请求转发和重定向的区别
  • Eureka原理与实践:构建高效的微服务架构
  • 宠物空气净化器该怎么选?希喂、352、霍尼韦尔哪款对吸附浮毛有效
  • Python协程详解
  • uniapp中使用uni.$emit和uni.$on在vue和nvue页面之间传值但是无法赋值的问题
  • HarmonyOS 实现自定义启动页
  • 鸿蒙开发协调布局CollapsibleLayout
  • Unity3d 以鼠标位置点为中心缩放视角(正交模式下)
  • 待办: 杂七杂八——大杂烩.....懒得整理了,我自己凑合看
  • 新手学习Python第七天-新手笔记
  • 基于STM32C8T6的CubeMX:HAL库点亮LED
  • Datawhale X 李宏毅苹果书 AI夏令营 《深度学习详解》第十九章 ChatGPT
  • Python 入门教程(3)基础知识 | 3.6、标准输入与输出
  • c++----模板(进阶)
  • 什么是VHDX文件?
  • 国科云域名解析课堂:一个域名可以解析到多个IP地址吗?
  • 高校能耗管控方案如何做到节能减排
  • 【Python123题库】#绘制温度曲线 #XRD谱图绘制 #态密度曲线绘制
  • 3个WebSocket的.Net开源项目
  • 基于vue框架的宠物店管理系统的设计与实现4czn0(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。