Unity多媒体互动开发,Unity最新技术学习

腾讯AI滤镜之Unity实现

准备工作

  因为我们要调用的是腾讯的远程API滤镜接口,因此要先注册账号(注册地址),然后创建应用程序,进入控制台,点击“创建应用”即可完成创建。再查看应用信息,拷贝app_id和app_key,后面要用到。如下图所示:

这里也给出腾讯AI滤镜的开发文档地址(开发文档),大家可以先自己了解一下,然后再往下看。

核心代码讲解

  总共有天天P图和AI Lab两个滤镜API接口,不过参数基本相同,都是htpp post请求。本文是基于Unity2018.3.0进行开发,将使用UnityWebRequest进行post请求。API 具体的请求参数如下:

  对于天天P图的API接口,总共有6个参数,app_id大家可以在上面创建的应用信息中找到,如下图:
filter对应的是滤镜的效果id,天天P图有32种效果,为1-32;AI Lab有65种效果为1-65;接下来主要重点讲解一下其他三个参数。   首先是time_stamp,int类型,根据字段描述,可以知道是请求时间戳,以秒为单位,因此只要算出当前时间距1970.01.01:00:00:00的秒数就好,具体代码如下:
1
2
3
4
5
6
7
8

private string GetUnixTimestamp()
{
//获取时间
TimeSpan timeSpan = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0);
//将时间转换为以秒为单位,因此是64位的整型值
return Convert.ToInt64(timeSpan.TotalSeconds).ToString();
}

  然后是image参数,string类型,要求是base64编码数据(这是什么鬼)。刚看到,我也是一头雾水,通过查阅资料发现用C#实现就是先把图片转换为byte数组,然后再转换为base64字符串即可。具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13

private string Bytes2Base64(byte[] bytes)
{
string base64 = Convert.ToBase64String(bytes);

int mod = base64.Length % 4;
if(mod > 0)
{
base64 += new string('=', 4 - mod);
}

return base64;
}

  不过有个坑就是,通过在线工具转换的base64字符串长度是4的整数倍,不足的用”=”补足了。因此上面的代码进行了4的倍数判断并自动补足。
  最后一个参数是sign,授权密钥,比较头疼,不过看过描述之后,觉得也还好。授权描述如下:

  从上面的描述,我们可以知道主要就是对请求参数按键值对中key值进行升序排列,然后并对value进行URL编码,并且URL编码采用大写字母;接着再将app_key放到字符串的最后;最后对得到的字符串进行MD5加密运算,并把加密字符串全部转换为大写字母。   不过问题又来了,什么是URL编码?查阅资料,最后发现Unity中实现了该算法,调用UnityWebRequest.EscapeURL(string)即可,但对得到的字符串要转换为大写字母。具体实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

private string ConvertURLEncode(string str, bool isImage=false)
{
string urlCode = UnityWebRequest.EscapeURL(str);
if (isImage)
{
string str1 = UnityWebRequest.EscapeURL("+");
string str2 = UnityWebRequest.EscapeURL("/");
string str3 = UnityWebRequest.EscapeURL("=");

urlCode = urlCode.Replace(str1, str1.ToUpper());
urlCode = urlCode.Replace(str2, str2.ToUpper());
urlCode = urlCode.Replace(str3, str3.ToUpper());
return urlCode;
}
else
return urlCode;
}

  对于上面的代码,大家会发现为什么对于图片的base64字符没有直接进行URL编码。这是因为URL编码只对部分字符进行编码,对数字和英文字母不进行编码(具体请看这里URL编码)。而且如果我们对整个base64字符串进行URL编码,会消耗相当长的一段时间。因此我采用了如上的代码实现URL编码。
  URL编码我们已经会了,接下来就是对得到的字符串进行MD5运算,得到sign授权字符串。而C#刚好实现了MD5加密算法,具体代码如下:

1
2
3
4
5
6
7

private string GetMD5Str(string str)
{
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
//转换为大写字母字符串
return BitConverter.ToString(bytes).ToUpper().Replace("-", "");
}

  所有的参数我们都已经准备好了,那就可以进行Http post请求了,不过请求成功返回什么样的结果呢?具体可以看文档的描述,如下图所示:

  可以看到,返回的图片任然是base64字符串的形式,因此我们要自己将base64字符串转换为图片,这个实现我就留给大家自己做了。不过有人该问了,这么多数据项,我要怎么拿到呀?其实返回的结果是以json字符串给我们的,我们只要把json字符串利用Unity中的JsonUtility转换为对应参数的对象就可以了。我们可以将返回的结果定义为如下的数据结构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14

[Serializable]
public class Data
{
public string image;
}

[Serializable]
public class ImageData
{
public int ret;
public string msg;
public Data data;
}

  最后一点就是对于AI Lab的API接口参数多了一个session_id参数,对应的是string类型,作用是请求id,只要保证每次请求值与之前不一样即可。下面是post请求表单和sign计算代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

private WWWForm GetPostForm(byte[] imgBytes, FilterType filterType, int filterId)
{
//将图片转换为Base64字符串
string imgStr = Bytes2Base64(imgBytes);//图片转为JPG格式的字符串,减小图片大小

//获取时间戳
string timeStamp = GetUnixTimestamp();

//设置请求字段
WWWForm form = new WWWForm();
form.AddField("app_id", int.Parse(app_id));
form.AddField("filter", filterId);
form.AddField("image", imgStr);
form.AddField("time_stamp", int.Parse(timeStamp));
form.AddField("nonce_str", timeStamp);

//获取加密原字符串,对<key,value>按key升序排列
string originalStr = "app_id=" + app_id +
"&filter=" + filterId +
"&image=" + ConvertURLEncode(imgStr, true) +
"&nonce_str=" + timeStamp;
if (filterType == FilterType.TTPTUFilter)
{
originalStr += "&time_stamp=" + timeStamp +
"&app_key=" + app_key;
}
else
{
originalStr += "&session_id=" + timeStamp +
"&time_stamp=" + timeStamp +
"&app_key=" + app_key;
form.AddField("session_id", timeStamp);
}
form.AddField("sign", GetMD5Str(originalStr));

return form;
}

效果展示

  总算把这篇文章给写完写出来了,本来准备上周日就写的,一直拖到现在......后面会专注于新媒体互动开发的相关分享,不过只做应用方面的分享,不过多讲底层的东西,大家可以自己去深挖研究。还有源工程就不放出来了,至于原因,就不说了,github速度......我已经不可以说什么了,不过这个速度慢的原因太多!!!

如有侵权,请联系删除!

-------------本文结束感谢您的阅读-------------