百度的人脸3D虚拟形象生成技术可以仅通过单张自拍图,自动生成个性化人脸表情基底,在社交、直播、游戏等涉及人物建模的场景应用广泛,帮助开发者及用户快速、低成本构建相似度高且美观的3D虚拟形象。平台同时具备人脸表情、语音驱动能力,开发者可快速搭建全站应用。
本文就如何调用人脸3D虚拟形象生成技术做个简单的教程。
注:人脸3D虚拟形象生成技术当前处于邀测阶段,如果想要体验,可以提交工单申请:https://ticket.bce.baidu.com/?_=1602834813589&fromai=1#/ticket/create
一、使用攻略
说明:本文采用C# 语言,开发环境为.Net Core 3.1,采用在线API接口方式实现。
(1)平台接入
登陆 百度智能云-管理中心 创建 “人脸识别”应用,获取 “API Key ”和 “Secret Key”:https://console.bce.baidu.com/ai/?fromai=1#/ai/face/overview/index
(2)接口文档
文档地址:https://ai.baidu.com/ai-doc/FACE/Vkdqsax4f
接口描述:
人脸3D虚拟形象生成为基于HTTP请求的REST API接口。根据用户上传的自定义风格的网格(以fbx形式),将单张人脸图片转换成与之在脸型和五官等特征细节相似的虚拟形象,以带表情的fbx文件输出,供后续驱动使用。
请求说明
HTTP方法:POST
请求URL:https://aip.baidubce.com/rest/2.0/face/v1/getfbx
URL参数:
Header如下:
注:实际使用中,发现需要 application/x-www-form-urlencoded 参数才能正确识别。
Body中放置请求参数,参数详情如下:
请求参数
fbx模板下载:https://ai.baidu.com/file/3B20EC398756491E83793515C9AF5202
fbx模板素材设计规范:https://ai.baidu.com/ai-doc/FACE/Hkdsn40a4
注:用户上传的自定义风格网格需要以百度提供的fbx模板为基础,在不改变网格的分组、各部件名称、纹理坐标、拓扑结构的前提下,仅通过改变网格形状来实现自定义的网格风格。用户亦可不对百度提供的fbx模板进行修改,直接上传默认模板。百度提供的fbx模板仅包括基础网格,不包含表情blendshape基底。
示例代码:
{ "image":base64.b64encode(image_file), // image_file 图片文件 "fbx_file":base64.b64encode(fbx_file) // fbx_file fbx文件 }
返回说明
返回参数
返回示例:
{ "log_id": 4579949465753, "gender": "male" , "url": "http://ar-fm.cdn.bcebos.com/ar/pta/20200520/2211fff71bbac8d1bbf480bf9b3ffeab/6f83784293581615f04143fc1ac5fc87/PTAHead_20200520.fbx", }
(3)源码共享
(3-1)根据 API Key 和 Secret Key 获取 AccessToken
/// /// 获取百度access_token /// /// API Key /// Secret Key /// public static string GetAccessToken(string clientId, string clientSecret) { string authHost = "https://aip.baidubce.com/oauth/2.0/token"; HttpClient client = new HttpClient(); List> paraList = new List>(); paraList.Add(new KeyValuePair("grant_type", "client_credentials")); paraList.Add(new KeyValuePair("client_id", clientId)); paraList.Add(new KeyValuePair("client_secret", clientSecret)); HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result; string result = response.Content.ReadAsStringAsync().Result; JObject jo = (JObject)JsonConvert.DeserializeObject(result); string token = jo["access_token"].ToString(); return token; }
(3-2)调用API接口获取识别结果
(3-2-1)在Startup.cs 文件 的 Configure(IApplicationBuilder app, IHostingEnvironment env) 方法中开启虚拟目录映射功能:
string webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");//wwwroot目录 app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(webRootPath, "Uploads", "BaiduAIs")), RequestPath = "/BaiduAIs" });
(3-2-2) 建立Index.cshtml文件
(3-2-2-1)前台代码:
由于html代码无法原生显示,只能简单说明一下:
主要是一个form表单,需要设置属性enctype="multipart/form-data",否则无法上传图片;
form表单里面有几个控件:
一个Input:type="file",asp-for="FileUpload" ,上传图片; 一个Input:type="submit",asp-page-handler="GetFbx" ,提交请求。 一个img:src="@Model.curPath",显示需要生成3D虚拟形象的图片。
最后显示后台 msg 字符串列表信息,如果需要输出原始Html代码,则需要使用@Html.Raw()函数。
(3-2-2-2) 后台代码:
主程序代码:
[BindProperty] public IFormFile FileUpload { get; set; } [BindProperty] public string ImageUrl { get; set; } public List msg = new List(); public string curPath { get; set; } string webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");//wwwroot目录 string BaiduAI_FacePath="Uploads//BaiduAIs//"; string BaiduAI_FaceUrl="/BaiduAIs/"; string BaiduAI_FaceFbxPath="baiduAIFace.fbx"; //fbx模板,可下载百度fbx模板文件进行修改,或直接上传默认模板 string Face_API_KEY="你的API KEY"; string Face_SECRET_KEY="你的SECRET KEY"; public async Task OnPostGetFbxAsync() { if (FileUpload is null) { ModelState.AddModelError(string.Empty, "请先选择需要识别的图片!"); } if (!ModelState.IsValid) { return Page(); } msg = new List(); string fileDir = Path.Combine(webRootPath, BaiduAI_FacePath); string imgName = GetRandomName(); imgName = await UploadFile(FileUpload, fileDir); curPath = Path.Combine(BaiduAI_FaceUrl, imgName); string fileName = Path.Combine(fileDir, imgName); string imgBase64 = GetFileBase64(fileName); string fbxPath = Path.Combine(webRootPath, BaiduAI_FaceFbxPath); string fbxBase64 = GetFileBase64(fbxPath); DateTime startTime = DateTime.Now; string result = GetFaceFbxJson(Face_Getfbx, imgBase64, Face_API_KEY, Face_SECRET_KEY, fbxBase64); DateTime endTime = DateTime.Now; TimeSpan ts = endTime - startTime; JObject jo = (JObject)JsonStringToObj(result); try { msg.Add("人脸3D虚拟形象生成结果(耗时" + ts.TotalSeconds + "秒):"); string gender = jo["gender"].ToString(); string url = jo["url"].ToString(); msg.Add("性别:" + (gender.Equals("male") ? "男" : "女")+ ""); msg.Add("3D虚拟形象生成文件:" + url + ""); } catch (Exception e1) { msg.Add(e1.Message); msg.Add(result); } return Page(); }
其他相关函数:
/// /// 人脸识别检测Json字符串-人脸3D虚拟形象生成 /// /// 图片base64编码 /// API Key /// Secret Key /// fbx文件(:base64编码) /// public static string GetFaceFbxJson( string imgBase64, string clientId, string clientSecret, string fbxFileBase64) { string token = GetAccessToken(clientId, clientSecret); string host = "https://aip.baidubce.com/rest/2.0/face/v1/getfbx?access_token=" + token; Encoding encoding = Encoding.Default; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host); request.Method = "post"; request.ContentType = "application/x-www-form-urlencoded"; request.KeepAlive = true; string str = "image=" + HttpUtility.UrlEncode(imgBase64); if (!string.IsNullOrEmpty(fbxFileBase64)) { str += "&fbx_file=" + HttpUtility.UrlEncode(fbxFileBase64); } byte[] buffer = encoding.GetBytes(str); request.ContentLength = buffer.Length; request.GetRequestStream().Write(buffer, 0, buffer.Length); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); string result = reader.ReadToEnd(); return result; } /// /// 获取百度access_token /// /// API Key /// Secret Key /// public static string GetAccessToken(string clientId, string clientSecret) { string authHost = "https://aip.baidubce.com/oauth/2.0/token"; HttpClient client = new HttpClient(); List> paraList = new List>(); paraList.Add(new KeyValuePair("grant_type", "client_credentials")); paraList.Add(new KeyValuePair("client_id", clientId)); paraList.Add(new KeyValuePair("client_secret", clientSecret)); HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result; string result = response.Content.ReadAsStringAsync().Result; JObject jo = (JObject)JsonConvert.DeserializeObject(result); string token = jo["access_token"].ToString(); return token; } /// /// 生成一个随机唯一文件名(Guid) /// /// public static string GetRandomName() { return Guid.NewGuid().ToString("N"); } /// /// 返回图片的base64编码 /// /// 文件绝对路径名称 /// public static String GetFileBase64(string fileName) { FileStream filestream = new FileStream(fileName, FileMode.Open); byte[] arr = new byte[filestream.Length]; filestream.Read(arr, 0, (int)filestream.Length); string baser64 = Convert.ToBase64String(arr); filestream.Close(); return baser64; } /// /// json转为对象 /// /// Json字符串 /// public static Object JsonStringToObj(string jsonString) { Object s = JsonConvert.DeserializeObject(jsonString); return s; } /// /// 上传文件,返回文件名 /// /// 文件上传控件 /// 文件绝对路径 /// public static async Task UploadFile(IFormFile formFile, string fileDir) { if (!DirectoryExists(directory)) { Directory.CreateDirectory(directory); } string extension = Path.GetExtension(formFile.FileName); string imgName = Guid.NewGuid().ToString("N") + extension; var filePath = Path.Combine(fileDir, imgName); using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { await formFile.CopyToAsync(fileStream); } return imgName; }
二、效果测试
1、页面:
2、识别生成结果:
2.1
fbx模板样式:
2.2
fbx模板样式:
2.3
fbx模板样式:
三、测试结果及建议
从上面的测试结果可以看到,生成的人脸3D虚拟形象还是比较生动相似的,特别是表情比较到位,而且操作方便,只要一张人脸图片就可以了,大大降低了人脸3D虚拟形象设计的难度,提高设计效率。
另外,如果有较好的3D虚拟形象设计能力的,还可以在默认fbx模板的基础上进行修改,并上传自定义风格的网格,从而获得到更加符合自己风格的3D虚拟形象。
人脸3D虚拟形象驱动的介绍blog有吗?