百度新推出的黑眼圈眼袋检测技术,提供了精准检测能力,具有毫秒级识别响应,并可分类别返回对应位置信息,实现黑眼圈眼袋的像素级语义分割,对于医美、互动娱乐及美颜等场景具有较高的应用价值。
而对于个人而言,如果能够做到坚持检测,可以发现自己的黑眼圈眼袋的变化,从而早到改善黑眼圈眼袋的良好习惯方法,对于维持身体健康具有一定的积极作用。
下面,就关于如何使用百度黑眼圈眼袋检测技术做一个简单的介绍。
一、使用攻略
说明:本文采用C# 语言,开发环境为.Net Core 3.1,采用在线API接口方式实现。
(1)平台接入
登陆 百度智能云-管理中心 创建 “人脸识别”应用,获取 “API Key ”和 “Secret Key”(目前处于邀测阶段,需要提交工单申请):https://console.bce.baidu.com/ai/?_=1600607509709&fromai=1#/ai/face/overview/index
(2)接口文档
文档地址:https://ai.baidu.com/ai-doc/FACE/Ykcvn0pko
接口描述:
通过AI技术,对人脸眼周的黑眼圈及眼袋进行高精度检测和识别
识别轮廓:精准识别左右眼黑眼圈与眼袋轮廓,可检测识别细分类别轮廓,分割IoU业界领先
精细分割:对人脸左右眼黑眼圈与眼袋实现像素级语义分割,分割边缘平滑流畅,明显增强黑眼圈与眼袋边缘细节能力,解决硬分割问题
请求说明
HTTP方法:POST
请求URL:https://aip.baidubce.com/rest/2.0/face/v1/eyesattr
URL参数:
Header如下:
Body中放置请求参数,参数详情如下:
请求参数
返回说明
返回参数
返回示例:
{
"error_code": 0,
"error_msg": "SUCCESS",
"log_id": 1048325060,
"timestamp": 1584091048,
"cached": 0,
"result": {
"face_num": 2,
"face_list": [
{
"face_token": "3bc1c35d3d0df595ed7649d3fd9d9d47",
"location": {
"left": 69.53,
"top": 121.81,
"width": 73,
"height": 68,
"degree": -3
},
"eyesattr": {
"dark_circle_left": [
[
{
"x": 1,
"y": 54
},
{
"x": 1,
"y": 55
},
{
"x": 1,
"y": 56
},
{
"x": 1,
"y": 57
},
{
"x": 1,
"y": 58
},
{
"x": 1,
"y": 59
},
{
"x": 1,
"y": 60
},
{
"x": 1,
"y": 61
},
{
"x": 1,
"y": 62
},
{
"x": 1,
"y": 63
},
{
"x": 1,
"y": 64
},
{
"x": 1,
"y": 65
},
{
"x": 1,
"y": 66
},
{
"x": 1,
"y": 65
},
{
"x": 1,
"y": 64
},
{
"x": 1,
"y": 63
},
{
"x": 1,
"y": 62
},
{
"x": 1,
"y": 61
},
{
"x": 1,
"y": 60
},
{
"x": 1,
"y": 59
},
{
"x": 1,
"y": 58
},
{
"x": 1,
"y": 57
},
{
"x": 1,
"y": 56
},
{
"x": 1,
"y": 55
}
]
],
"dark_circle_right": [],
"eye_bags_left": [],
"eye_bags_right": [
[
{
"x": 2,
"y": 60
},
{
"x": 2,
"y": 61
},
{
"x": 2,
"y": 62
},
{
"x": 2,
"y": 63
},
{
"x": 2,
"y": 64
},
{
"x": 2,
"y": 65
},
{
"x": 2,
"y": 66
},
{
"x": 2,
"y": 65
},
{
"x": 2,
"y": 64
},
{
"x": 2,
"y": 63
},
{
"x": 2,
"y": 62
},
{
"x": 2,
"y": 61
}
]
]
}
},
{
"face_token": "e57ca08b40bf2c073c278b5d30e76ebc",
"location": {
"left": 220.73,
"top": 87.92,
"width": 67,
"height": 67,
"degree": 0
},
"eyesattr": {
"dark_circle_left": [],
"dark_circle_right": [],
"eye_bags_left": [],
"eye_bags_right": []
}
}
]
}
}
(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="Eyesattr" ,提交请求。
一个img:src="@Model.curPath",显示需要识别的图片。
一个img:src="@Model.facePath",显示识别后的图片。
最后显示后台 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; }
public string facePath { get; set; }
string BaiduAI_FacePath="Uploads//BaiduAIs//";
string BaiduAI_FaceUrl="/BaiduAIs/";
string Face_APP_ID="你的APIID";
string Face_API_KEY="你的API KEY";
string Face_SECRET_KEY="你的SECRET KEY";
public async Task OnPostEyesattrAsync()
{
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 = Common.GetFileBase64(fileName);
DateTime startTime = DateTime.Now;
string result = GetFaceEyesJson(imgBase64, Face_APP_ID, Face_API_KEY, Face_SECRET_KEY);
DateTime endTime = DateTime.Now;
TimeSpan ts = endTime - startTime;
JObject jo = (JObject)JsonStringToObj(result);
try
{
if (jo["error_code"].ToString() != "0")
{
msg.Add("调用失败:" + jo["error_code"].ToString() + "-" + jo["error_msg"].ToString());
}
else
{
List msgList = jo["result"]["face_list"].ToList();
int number = msgList.Count;
int curNumber = 1;
msg.Add("黑眼圈眼袋检测识别结果(耗时" + ts.TotalSeconds + "秒):");
msg.Add("识别人脸数:" + number + "");
List aList = new List();
List bList = new List();
foreach (JToken ms in msgList)
{
msg.Add("
");
if (number > 1)
{
msg.Add("第 " + curNumber.ToString() + " 个:");
}
float x = 0;
float y = 0;
Rectangle rec;
#region 获取左黑眼圈信息
if (ms["eyesattr"]["dark_circle_left"].ToList().Count > 0)
{
foreach (JToken jt in ms["eyesattr"]["dark_circle_left"][0].ToList())
{
x = float.Parse(jt["x"].ToString());
y = float.Parse(jt["y"].ToString());
rec = new Rectangle(x, y);
aList.Add(rec);
}
msg.Add("有左黑眼圈!");
}
else
{
msg.Add("无左黑眼圈!");
}
#endregion
#region 获取右黑眼圈信息
if (ms["eyesattr"]["dark_circle_right"].ToList().Count > 0)
{
foreach (JToken jt in ms["eyesattr"]["dark_circle_right"][0].ToList())
{
x = float.Parse(jt["x"].ToString());
y = float.Parse(jt["y"].ToString());
rec = new Rectangle(x, y);
aList.Add(rec);
}
msg.Add("有右黑眼圈!");
}
else
{
msg.Add("无右黑眼圈!");
}
#endregion
#region 获取左眼眼袋信息
if (ms["eyesattr"]["eye_bags_left"].ToList().Count > 0)
{
foreach (JToken jt in ms["eyesattr"]["eye_bags_left"][0].ToList())
{
x = float.Parse(jt["x"].ToString());
y = float.Parse(jt["y"].ToString());
rec = new Rectangle(x, y);
bList.Add(rec);
}
msg.Add("有左眼袋!");
}
else
{
msg.Add("无左眼袋!");
}
#endregion
#region 获取右眼眼袋信息
if (ms["eyesattr"]["eye_bags_right"].ToList().Count > 0)
{
foreach (JToken jt in ms["eyesattr"]["eye_bags_right"][0].ToList())
{
x = float.Parse(jt["x"].ToString());
y = float.Parse(jt["y"].ToString());
rec = new Rectangle(x, y);
bList.Add(rec);
}
msg.Add("有右眼袋!");
}
else
{
msg.Add("无右眼袋!");
}
#endregion
curNumber++;
}
string imgSourcePath = Path.Combine(webRootPath, BaiduAI_FacePath, imgName);
imgName = GetRandomName() + ".png";
string imgSavedPath = Path.Combine(webRootPath, BaiduAI_FacePath, imgName);
await DrawPoint(imgSourcePath, imgSavedPath, aList, bList, SixLabors.ImageSharp.Color.DeepPink, SixLabors.ImageSharp.Color.DarkBlue);
facePath = Path.Combine(BaiduAI_FaceUrl, imgName);
}
}
catch (Exception e1)
{
msg.Add(e1.Message);
msg.Add(result);
}
return Page();
}
其他相关函数:
///
/// 人体检测Json字符串
///
/// 图片base64编码
/// API Key
/// Secret Key
/// 图片类型(BASE64:图片的base64值;URL:图片的 URL( 下载图片时可能由于网络等原因导致下载图片时间过长);FACE_TOKEN: 人脸标识)
/// 最多处理人脸的数目. 默认值为1(仅检测图片中面积最大的那个人脸) 最大值10
///
public static string GetFaceEyesJson( string strbaser64, string appId, string clientId, string clientSecret, string imageType = "BASE64", int maxFaceNnum = 1)
{
string token = GetAccessToken(clientId, clientSecret);
string host = "https://aip.baidubce.com/rest/2.0/face/v1/eyesattr?access_token=" + token;
Encoding encoding = Encoding.Default;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
request.Method = "post";
request.ContentType = "application/json";
request.KeepAlive = true;
string str = "{\"image\":\"" + strbaser64;
if (!string.IsNullOrEmpty(appId))
{
str += "\",\"appId\":\"" + appId;
}
if (!string.IsNullOrEmpty(imageType))
{
str += "\",\"image_type\":\"" + imageType;
}
if (maxFaceNnum > 1)
{
str += "\",\"max_face_num\":\"" + maxFaceNnum;
}
str += "\"}";
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;
}
///
/// 画点
///
/// 原图
/// 目标图
/// 黑眼圈点集合
/// 黑眼袋点集合
/// 黑眼圈点颜色
/// 黑眼袋点颜色
/// 点宽度
public static async Task DrawPoint(string originalPath, string targetPath, List aList, List bList, Color aColor, Color bColor, int pointWith = 1)
{
//黑眼圈点坐标
var aListPath = new List();
foreach (Rectangle rec in aList)
{
var linerLine = new SixLabors.Shapes.LinearLineSegment(rec.point, rec.point);
var shapesPath = new SixLabors.Shapes.Path(linerLine);
aListPath.Add(shapesPath);
}
//黑眼袋点坐标
var bListPath = new List();
foreach (Rectangle rec in bList)
{
var linerLine = new SixLabors.Shapes.LinearLineSegment(rec.point, rec.point);
var shapesPath = new SixLabors.Shapes.Path(linerLine);
bListPath.Add(shapesPath);
}
using (Image image = Image.Load(originalPath))
{
image.Mutate(
x => x.Draw(
Pens.Dot(aColor, pointWith), //大小
new SixLabors.Shapes.PathCollection(aListPath))); //黑眼圈点坐标集合
image.Mutate(
x => x.Draw(
Pens.Dot(bColor, pointWith), //大小
new SixLabors.Shapes.PathCollection(bListPath))); //黑眼袋点坐标集合
image.Save(targetPath);
}
}
Rectangle类:
///
/// 矩形数据
///
public class Rectangle
{
///
/// X坐标
///
[Display(Name = "X坐标")]
public float X { get; set; }
///
/// Y坐标
///
[Display(Name = "Y坐标")]
public float Y { get; set; }
///
/// 点坐标
///
[Display(Name = "点坐标")]
public Vector2 point
{
get
{
return new Vector2(X, Y);
}
}
public Rectangle()
{
}
///
/// 数据初始化
///
/// X坐标
/// Y坐标
public Rectangle(float x, float y)
{
X = x;
Y = y;
}
}
二、效果测试
1、页面:
2、识别结果:
2.1
2.2
2.3
三、测试结果及建议
从测试结果可知,百度的黑眼圈眼袋检测功能识别率还是不错的,特别是对于黑眼圈的识别比较准确,对于眼袋的识别好像不太好。
不过,如果能够将识别到的黑眼圈眼袋再进行细分,是色素型、血管型还是结构型?另外根据识别的数据,给定一个黑眼圈的严重程度,数据越大,越严重。这样的话,对于个人分辨自己黑眼圈眼袋的严重程度,一段时间黑眼圈眼袋的变化有个更直观的体现,对于个人改变坏习惯,减少黑眼圈眼袋,保持身体健康会有更大的帮助。
https://www.cifnews.com/search?keyword=%E7%8E%89%E5%92%8C%E5%A8%B1%E4%B9%90-%E7%BC%85%E7%94%B8%E7%8E%89%E5%92%8C%E9%9B%86%E5%9B%A2%E5%AE%98%E6%96%B9%E7%BD%91%E5%9D%80TL262%C2%B7C%EF%BC%AFM%E8%B4%B5%E9%98%B3%E7%A4%BE%E4%BF%9D%EF%BC%90%EF%BC%94 https://b2b.baidu.com/s?fr=wwwt&q=%E7%BC%85%E7%94%B8%E8%BF%AA%E5%A8%81%E5%A8%B1%E4%B9%90%E5%AE%98%E7%BD%91%E7%9B%B4%E8%90%A5%E5%BC%80%E6%88%B7%3AB2024.CN%E7%8E%89%E6%9E%97%E5%8D%AB%E7%94%9F%E5%B1%80%EF%BD%82%EF%BC%A4 https://quanmin.baidu.com/wise/growth/querypage?keyword=%E5%9B%9B%E5%B7%9D%E7%9C%9F%E4%BA%BA%E6%96%97%E7%89%9B%E3%80%90%E5%AE%98%E7%BD%91%E2%86%92TL262%C2%B7%EF%BC%A3%EF%BC%AF%EF%BC%AD%E3%80%91%E6%BD%8D%E5%9D%8A%E7%94%B5%E4%BF%A1%EF%BC%92%EF%BC%99%EF%BD%9E.htm https://www.1688.com/chanpin/-.html?keywords=hs331.com%CF%D6%B3%A1%BF%AA%BB%A7%B9%D9%CD%F8TL262%A1%A4C%A3%CFM%D3%A5%CC%B6%CD%F8%CD%A8%A3%A5 http://www.yxdown.com/searchsy?wd=%E7%9A%87%E5%AE%B6%E5%9B%BD%E9%99%85%E9%9B%86%E5%9B%A2%E5%AE%A2%E6%9C%8D%E7%94%B5%E8%AF%9D%E3%80%90TL262%C2%B7C%EF%BC%AFM%E3%80%91%E5%8F%B0%E5%B7%9E%E6%96%B0%E9%97%BB%EF%BD%8C%EF%BC%90