前言
人们对人脸识别的研究已经有很长一段时间,起初局限于获取基础的人脸信息,随着机器学习领域的发展,人脸识别的应用更加广泛,已经可以被用于人脸搜索、人脸鉴权等相关应用。本文将针对微软认知服务中提供的人脸识别API的调用方法进行一些初步的讲解。
Face API
Face API中提供了3方面功能:
- 人脸检测
- 人脸分组
- 人脸识别(搜索)
首先是人脸检测,主要是指传统概念上的人脸识别功能,识别图片中的人的面孔,给出人脸出现的坐标区域,并根据识别出来的人脸分析出一些基本的信息(例如年龄)。
其次是人脸分组,可以在已经预制好的若干张人脸中根据相似度进行相似度搜索或者是根据相似度进行分组或者是认证操作。
最后是人脸识别,这里的人脸识别是指,通过给定一张人脸在构建并训练完成的人脸库中搜索名称的功能。
同样,Face API在调用过程中,也有一系列的限制,如果在调用过程中确认代码逻辑没有问题的情况下,依然出错,可以检查如下几点:
- 图片的格式需要是JPEG、PNG、GIF(仅限第一帧)以及BMP
- 图片尺寸不可以大于4MB
- 人脸像素需要介于36x36 (px)与4096x4096 (px)之间
- 每张照片中最多包含64张面部信息
- FaceID的有效期为24小时(自生成之时起)
人脸检测(Detect)
人脸检测功能,可以识别照片中人脸的位置信息,包括脸部的范围以及脸部的各个细节的位置(眼睛、鼻子、嘴等信息),还可以识别出面部装束信息(是否有胡子等),最后还可以针对所识别出来的人脸做一些智能的分析功能,可以获取性别、年龄、是否微笑等。
首先是接口URL:
URL中包含了3个参数returnFaceId、returnFaceLandmarks以及returnFaceAttributes,3个参数都是可选参数。
键 | 值 |
---|---|
returnFaceId | 设定是否返回FaceID,默认值是true |
returnFaceLandmarks | 设定是否返回详细的面部细节位置信息(包括鼻子、眼睛、嘴等),默认值是false |
*returnFaceAttributes | 设定进行面部智能分析(分析性别、年龄、微笑等)的项目,可设置为age 、gender 、headPose 、smile 、facialHair 、glasses .多个项目中间使用逗号进行分割(, ) |
*每项分析内容都需要增加额外的计算时间。
和之前在计算机视觉中介绍的类似,微软认知服务每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
这个API通过POST
的方式进行调用,除了必要的之外Ocp-Apim-Subscription-Key,还可以设置Content-Type
键 | 值 |
---|---|
Content-Type(可选) | 设定Content-Type信息,这个是可选的,不设定会根据Post过去的数据自动识别出来,可以设定为application/json 、application/octet-stream |
当设置为application/octet-stream
时, POST
中的数据直接就是Binary流。而当设置为application/json时,POST中的数据按如下格式实现,
{“url”:”http://example.com/images/test.jpg“}
最后介绍的是这个API的返回值,返回信息为一串JSON字符串。格式如下:
[
{
"faceId": "c5c24a82-6845-4031-9d5d-978df9175426",
"faceRectangle": {
"width": 78,
"height": 78,
"left": 394,
"top": 54
},
"faceLandmarks": {
"pupilLeft": {
"x": 412.7,
"y": 78.4
},
"pupilRight": {
"x": 446.8,
"y": 74.2
},
"noseTip": {
"x": 437.7,
"y": 92.4
},
"mouthLeft": {
"x": 417.8,
"y": 114.4
},
"mouthRight": {
"x": 451.3,
"y": 109.3
},
"eyebrowLeftOuter": {
"x": 397.9,
"y": 78.5
},
"eyebrowLeftInner": {
"x": 425.4,
"y": 70.5
},
"eyeLeftOuter": {
"x": 406.7,
"y": 80.6
},
"eyeLeftTop": {
"x": 412.2,
"y": 76.2
},
"eyeLeftBottom": {
"x": 413.0,
"y": 80.1
},
"eyeLeftInner": {
"x": 418.9,
"y": 78.0
},
"eyebrowRightInner": {
"x": 4.8,
"y": 69.7
},
"eyebrowRightOuter": {
"x": 5.5,
"y": 68.5
},
"eyeRightInner": {
"x": 441.5,
"y": 75.0
},
"eyeRightTop": {
"x": 446.4,
"y": 71.7
},
"eyeRightBottom": {
"x": 447.0,
"y": 75.3
},
"eyeRightOuter": {
"x": 451.7,
"y": 73.4
},
"noseRootLeft": {
"x": 428.0,
"y": 77.1
},
"noseRootRight": {
"x": 435.8,
"y": 75.6
},
"noseLeftAlarTop": {
"x": 428.3,
"y": 89.7
},
"noseRightAlarTop": {
"x": 442.2,
"y": 87.0
},
"noseLeftAlarOutTip": {
"x": 424.3,
"y": 96.4
},
"noseRightAlarOutTip": {
"x": 446.6,
"y": 92.5
},
"upperLipTop": {
"x": 437.6,
"y": 105.9
},
"upperLipBottom": {
"x": 437.6,
"y": 108.2
},
"underLipTop": {
"x": 436.8,
"y": 111.4
},
"underLipBottom": {
"x": 437.3,
"y": 114.5
}
},
"faceAttributes": {
"age": 71.0,
"gender": "male",
"smile": 0.88,
"facialHair": {
"mustache": 0.8,
"beard": 0.1,
"sideburns": 0.02
}
},
"glasses": "sunglasses",
"headPose": {
"roll": 2.1,
"yaw": 3,
"pitch": 0
}
}
}
]
返回的JSON数据中,人脸的数目不一定只有一个,每一个面部信息,都将会被阻止在JSON数据中的第一层中。
每个面部信息中包含3部分,首先是FaceID,这个ID可以用于后续的一些API调用中使用(例如Verify之类的)。
其次是照片中人脸识别的结果,结果会以坐标以及范围的矩形方式给出,如果在请求的URL中指定需要获取面部细节的位置信息,还会在其中给出具体的眼睛、鼻子以及嘴部的详细坐标。
最后如果请求了高级别的智能分析功能,还会给出性别、年龄、微笑程度等信息。
同样,如果请求(或调用)API的过程中,如果其中有异常抛出,则会在Response中返回异常的详细内容,类似格式如下:
{
"error":{
"code":"BadArgument",
"message":"Request body is invalid."
}
}
整个API的具体调用示例,C#可以参考如下:
static async void MakeRequest()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
// Request parameters
queryString["returnFaceId"] = "true";
queryString["returnFaceLandmarks"] = "false";
queryString["returnFaceAttributes"] = "{string}";
var uri = "https://api.projectoxford.ai/face/v1.0/detect?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("{body}");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
response = await client.PostAsync(uri, content);
}
}
人脸分组(Group)
分组这部分其实包含了3个功能,
- 首先是相似度搜索,将给定的面部信息在一系列面部信息中筛选出相似度比较高的前几项
- 其次是自动分组,将给定的一系列面部信息中,自动的进行分组
- 最后是鉴权认证,给定两个面部信息项,比对是否为相同,并给出相似度的值
这3个功能,都是基于相似度来进行的,所以这里将这三种都归结到人脸分组下面。
相似度搜索
在介绍相似度搜索前,笔者将对Face List API做一些简单的说明,因为相似度搜索包含两个参数项,首先是搜索的目标,其次是一组面部信息,而这组面部信息可以由JSON数组将ID传入,也可以根据以构建好的FaceList的ID传入。所以在此需要先介绍下FaceListAPI。
Face List
FaceListAPI中包含了一系列的调用用于构建、查询、修改以及删除一个FaceList这几种操作。
List Face Lists
接口URL:
该接口用于列举出该账户下已经注册了哪些FaceList。
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
返回的JSON的格式如下:
[
{
"faceListId": "sample_list",
"name": "list1",
"userData":"User-provided data attached to the face list"
},
…
]
Get a Face List
接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}
该接口用于或许某一个FaceList的详细信息,其中的FaceListId可以通过List Face Lists接口获得。
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
返回的JSON的格式如下:
{
"faceListId": "sample_list",
"name": "list1",
"userData":"User-provided data attached to the face list",
"persistedFaces":[
{
"persistedFaceId":"B8D802CF-DD8F-4E61-B15C-9E6C5844CCBD",
"userData":"User-provided data attached to the face"
},
…
]
}
Create a Face List
PUT方式的接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}
该接口用于在该账户下已经注册一个新的FaceList。
除了请求的URL中需要指定FaceListID之外,还需要在其POST过去的RequestBody中按如下格式指定一些信息,其中的userData可以由用于写入一些特定的数据信息。
{
"name":"sample_list",
"userData":"User-provided data attached to the face list"
}
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
Update a Face List
UPDATE方式的接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}
该接口用于更新在该账户下某一指定的FaceList,调用方式与Create a Face List API相同。
除了请求的URL中需要指定FaceListID之外,还需要在其POST过去的RequestBody中按如下格式指定一些信息,其中的userData可以由用于写入一些特定的数据信息。
{
"name":"sample_list",
"userData":"User-provided data attached to the face list"
}
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
Delete a Face List
DELETE方式的接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}
该接口用于删除在该账户下某一指定的FaceList。
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
Add a Face to a Face List
接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}/persistedFaces[?userData][&targetFace]
该接口用于添加Face信息到一个FaseList中,除了请求的URL中需要指定FaceListID之外,还可以在URL中指定如下几项可选内容,
键 | 值 |
---|---|
userData | 在该条数据上指定一些用户数据(字符串的Tag信息) |
targetFace | 按照格式targetFace=left,top,width,height 标记图片中面部信息的坐标, 例如argetFace=10,10,100,100 。如果没有指定则代表先对图片进行面部识别后获得的唯一面部信息。 |
这个API通过POST
的方式进行调用,除了必要的之外Ocp-Apim-Subscription-Key,还可以设置Content-Type
键 | 值 |
---|---|
Content-Type(可选) | 设定Content-Type信息,这个是可选的,不设定会根据Post过去的数据自动识别出来,可以设定为application/json 、application/octet-stream |
当设置为application/octet-stream
时, POST
中的数据直接就是Binary流。而当设置为application/json时,POST中的数据按如下格式实现,
{“url”:”http://example.com/images/test.jpg“}
调用后,根据返回的ResponseCode是否为200来识别是否调用成功,并返回如下信息。
{
"persistedFaceId": "B8D802CF-DD8F-4E61-B15C-9E6C5844CCBA"
}
其中的persistedFaceId
用于标记所录入的面部信息的ID。
Delete a Face from a Face List
DELETE方式的接口URL:
https://api.projectoxford.ai/face/v1.0/facelists/{faceListId}/persistedFaces/{persistedFaceId}
该接口用于删除在该账户下某一指定FaceList中某一个面部信息。需要在请求的URL中指定faceListId以及persistedFaceId。
每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
Find Similar
相似度搜索功能,可以在给定的一组面部信息中,寻找特定的面部信息匹配的情况,并返回前若干条相似度比较高的面部信息的ID,以及匹配度,可以借此来实现面部搜索功能。
首先是接口URL:
该接口通过POST
方式进行调用,调用时Header中需要包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key。
POST请求的Body中,需要包含如下几项内容,
键 | 值 |
---|---|
faceId | 需要进行搜索的faceID |
*faceListId | 指定faceListId来设定搜索的范围 |
*faceIds | 同构构建的faceID的数组来设定搜索的范围 |
maxNumOfCandidatesReturned | 返回的最大条目,可以设定为1-20的值,默认值为20 |
*faceListId与faceIds只可以同时指定其中的一个,不可一同指定。
类似的请求的Body的格式如下:
{
"faceId":"c5c24a82-6845-4031-9d5d-978df9175426",
"faceListId":"sample_list",
"maxNumOfCandidatesReturned":10
}
当使用faceIds来设定搜索范围时,faceIds为一个数组,使用如下格式替换faceListId,即可:
{
"faceId":"c5c24a82-6845-4031-9d5d-978df9175426",
"faceIds":[
"c5c24a82-6845-4031-9d5d-978df9175426",
"015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
"65d083d4-9447-47d1-af30-b626144bf0fb",
"fce92aed-d578-4d2e-8114-068f8af4492e",
"30ea1073-cc9e-4652-b1e3-d08fb7b95315",
"be386ab3-af91-4104-9e6d-4dae4c9fddb7",
"fbd2a038-dbff-452c-8e79-2ee81b1aa84e",
"b64d5e15-8257-4af2-b20a-5a750f8940e7",
...
]
"maxNumOfCandidatesReturned":10
}
最后使用POST的方式将其发送出去后如果没有异常发生则返回如下格式的JSON响应,
[
{
"persistedFaceId" : "015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
"confidence" : 0.82
},
...
]
其中会按照相似度倒序返回符合的数据项。
人脸分组(Group)
人脸分组功能可以自动的将给定的一些列面部信息进行自动的分组,最大支持1000个面部信息的分组计算。
首先是接口URL:
该接口通过POST
方式进行调用,调用时Header中需要包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key。
POST请求的Body中,需要包含如下几项内容,
键 | 值 |
---|---|
faceIds | 指定用于分组的数据源的faceID数组 |
类似的请求的Body的格式如下:
{
"faceIds":[
"c5c24a82-6845-4031-9d5d-978df9175426",
"015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
"65d083d4-9447-47d1-af30-b626144bf0fb",
"fce92aed-d578-4d2e-8114-068f8af4492e",
"30ea1073-cc9e-4652-b1e3-d08fb7b95315",
"be386ab3-af91-4104-9e6d-4dae4c9fddb7",
"fbd2a038-dbff-452c-8e79-2ee81b1aa84e",
"b64d5e15-8257-4af2-b20a-5a750f8940e7"
]
}
最后使用POST的方式将其发送出去后如果没有异常发生则返回如下格式的JSON响应,
{
"groups": [
[
"c5c24a82-6845-4031-9d5d-978df9175426",
"015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
"fce92aed-d578-4d2e-8114-068f8af4492e",
"b64d5e15-8257-4af2-b20a-5a750f8940e7"
],[
"65d083d4-9447-47d1-af30-b626144bf0fb",
"30ea1073-cc9e-4652-b1e3-d08fb7b95315"
]
],
"messyGroup": [
"be386ab3-af91-4104-9e6d-4dae4c9fddb7"
]
}
返回的数据中包含两部分,其中第一个部分是groups,里面即使分组的结果,但是一些面部信息可能无法被安排到任何一个分组中,则会被单独的放在messyGroup中。
C#的调用示例如下:
static async void MakeRequest()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
var uri = "https://api.projectoxford.ai/face/v1.0/group?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("{body}");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
response = await client.PostAsync(uri, content);
}
}
人脸认证(鉴权)(Verify)
人脸认证功能,是传入两张人脸信息,然后比对其相似度,来判断是否为同一个人。虽然也可以使用相似度搜索功能来实现,但是人脸认证功能背后的算法也许更加精确。
首先是接口URL:
该接口通过POST
方式进行调用,调用时Header中需要包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key。
POST请求的Body中,只需要包含两个面部信息即可(faceId1、faceId2),类似的请求的Body的格式如下:
{
"faceId1":"c5c24a82-6845-4031-9d5d-978df9175426",
"faceId2":"015839fb-fbd9-4f79-ace9-7675fc2f1dd9"
}
最后使用POST的方式将其发送出去后如果没有异常发生则返回如下格式的JSON响应,
{
"isIdentical":true,
"confidence":0.9
}
其中isIdentical
表示是否通过鉴权,confidence
表示可信程度(相似度)为多少。
C#的调用示例如下:
static async void MakeRequest()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
var uri = "https://api.projectoxford.ai/face/v1.0/verify?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("{body}");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
response = await client.PostAsync(uri, content);
}
}
人脸识别
人脸识别功能可以从已经制作并且训练好的PersonGroup中,根据指定面部信息来识别出特定的Person信息。简答的说就是给定一张面部的照片,可以识别出来这个人是谁,当然这个识别的范围需要预先构建并训练好。
本章节将先讲解如何构建PersonGroup并且进行训练,然后再介绍人脸识别(Identify)接口如何调用。
构建PersonGroup
人脸识别需要预先构建好PersonGroup,然后再PersonGroup中构建Person信息。
构建PersonGroup涉及到如下几个API的调用,
- List Person Groups
- Create a Person Group
- Update a Person Group
- Delete a Person Group
List Person Groups
其中List Person Groups API的接口URL为,
返回JSON中包含目前该账户下所构建的所有PersonGroup的列表,
[
{
"personGroupId":"sample_group",
"name":"group1",
"userData":"User-provided data attached to the person group"
},{
"personGroupId":"sample_group2",
"name":"group2",
"userData":"User-provided data attached to the person group"
}
]
* Create/Update/Delete a Person Group*
其中 Create/Update/Delete a Person Group API的接口URL三者相同,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}
区别是,使用不同的调用方式,其中Create使用
PUT
调用,Update使用UPDATE
调用,最后Delete使用DELETE
方式进行调用。调用过程中,除了Delete操作不需要特定的Body以外,Create、Update两种操作都需要指定PersonGroup的信息。
{
"name":"group1",
"userData":"user-provided data attached to the person group"
}
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
构建Person相关操作
Person则为对应在PersonGroup中的一个单独的实例,其查询以及构建方式通PersonGroup类似,包括如下4条API,
- List Persons in a Person Group
- Create a Person
- Get a Person
- Update a Person
- Delete a Person
List Persons in a Person Group以及Get a Person
其中List Persons in a Person Group API的接口URL为,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/persons
而Get a Person API的接口为,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/persons/{personId}
返回JSON中包含目前该账户下所构建的所有Person的列表,其中每个Person还包括了已经录入的FaceID,
两个API的区别是,List Persons in a Person Group返回所有的而Get a Person只返回指定的。
[
{
"personId":"25985303-c537-4467-b41d-bdb45cd95ca1",
"name":"Ryan",
"userData":"User-provided data attached to the person",
"persistedFaceIds":[
"015839fb-fbd9-4f79-ace9-7675fc2f1dd9",
"fce92aed-d578-4d2e-8114-068f8af4492e",
"b64d5e15-8257-4af2-b20a-5a750f8940e7"
]
},{
"personId":"2ae4935b-9659-44c3-977f-61fac20d0538",
"name":"David",
"userData":"User-provided data attached to the person",
"faceIds":[
"30ea1073-cc9e-4652-b1e3-d08fb7b95315",
"fbd2a038-dbff-452c-8e79-2ee81b1aa84e"
]
}
]
* Create/Update/Delete a Person*
其中 Create/Update/Delete a Person API的接口URL相同,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/persons/{personId}
区别是,使用不同的调用方式,其中Create使用
PUT
调用,Update使用UPDATE
调用,最后Delete使用DELETE
方式进行调用。调用过程中,除了Get以及Delete操作不需要特定的Body以外,Create、Update两种操作都需要指定PersonGroup的信息。
{
"name":"Person1",
"userData":"User-provided data attached to the person"
}
调用后,根据返回的ResponseCode是否为200来识别是否调用成功。
构建PersonFace
每个Person可以预先指定若干条面部信息用于训练,可以通过如下几条API来对每个Person的Face信息进行构建,
- Add a Person Face to Person
- Update a Person Face
- Delete a Person Face
除Delete操作外,PersonFace API的URL接口都为,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/persons/{personId}/persistedFaces[?userData][&targetFace]
而Delete操作则是在URL中多了一项persistedFaceId而已,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/persons/{personId}/persistedFaces/{persistedFaceId}
在URL中需要指定PersonGroupId以及personId来指定当前操作的面部信息属于哪个组的那个人,在Add或者Update操作中,可以通过userData来定义一小段有关该面部信息的描述,以及通过targetFace来传入当前图片中的面部信息的位置信息,如果没有传入的话将会通过面部检测功能自动识别出当前图片中唯一的面部信息的位置。
Add以及Update以及Delete3种虽然都是用同一个URL但是调用方式不同,Add是通过PUT
方式进行调用,而Update则使用过UPDATE
方式调用,最后的Delete通过DELETE
方式进行调用。
在Add以及Update中,Body可以是Binary的图片数据,也可以是JSON来指定来自互联网的URL的图片地址,如果使用后者则Body格式如下,
{
"url":"http://example.com/1.jpg"
}
Add以及Update的调用结果为返回新添加的或者更新的面部信息id,
{
“persistedFaceId”: “B8D802CF-DD8F-4E61-B15C-9E6C5844CCBA”
}
而Delete操作则是以ResponseCode是否为200来识别是否调用成功。
训练PersonGroup
PersonGroup在进行构建或者修改后,需要训练后才可真正用于人脸识别操作。训练操作涉及2个API,
- Train Person Group
- Get Person Group Training Status
由于训练过程不是立刻就能完成的,并且也不一定是立刻开始执行的,所以在启动训练后需要通过查询状态来了解训练的结果。
首先是Train API的URL,该URL中只需要指定需要训练的PersonGroupId后直接调用即可,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/train
根据返回的ResponseCode是否为200来识别是否调用成功。
在启动训练后,可以通过如下URL查询其训练的状态,
https://api.projectoxford.ai/face/v1.0/persongroups/{personGroupId}/training
调用后可能返回的JSON数据包含status、createdDataTime、lastActionDateTime、message信息,其格式如下,
{
"status":"succeeded",
"createdDateTime": "2015-05-15T13:45:30",
"lastActionDateTime": null,
"message": "The operation was timeout."
}
人脸识别(Identify)
人脸识别功能,可以在已经构建好的PersonGroup中,根据指定的照片中人脸信息,搜索出具体的某一个Person。该API可以一次请求多个Face的识别(但是最多10项)。
首先是接口URL:
请求通过POST调用中,且需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key。类似的请求Body的格式如下,
{
"personGroupId":"sample_group",
"faceIds":[
"c5c24a82-6845-4031-9d5d-978df9175426",
"65d083d4-9447-47d1-af30-b626144bf0fb"
],
"maxNumOfCandidatesReturned":1
}
在POST过去的Body中需要包括如下几项内容,
键 | 值 |
---|---|
faceIds | 设定查询FaceId的数组,由于是使用数组,所以可以一次请求多个Face的识别过程,但是最多10个 |
personGroupId | 通过设定personGroupId来指定搜索的范围 |
maxNumOfCandidatesReturned | 设定返回候选项的数目(1到5),默认值为1 |
如果调用过程中未发生异常,则返回识别的结果,格式如下:
{
[
{
"faceId":"c5c24a82-6845-4031-9d5d-978df9175426",
"candidates":[
{
"personId":"25985303-c537-4467-b41d-bdb45cd95ca1",
"confidence":0.92
}
]
},{
"faceId":"65d083d4-9447-47d1-af30-b626144bf0fb",
"candidates":[
{
"personId":"2ae4935b-9659-44c3-977f-61fac20d0538",
"confidence":0.89
}
]
}
]
}
其中返回的单位为具体的PersonId,可以通过GetPersionAPI来获取该Person的详细信息。
整个API的具体调用示例,C#可以参考如下:
static async void MakeRequest()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
var uri = "https://api.projectoxford.ai/face/v1.0/identify?" + queryString;
HttpResponseMessage response;
// Request body
byte[] byteData = Encoding.UTF8.GetBytes("{body}");
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("< your content type, i.e. application/json >");
response = await client.PostAsync(uri, content);
}
}
总结
本文中对微软认知服务中的面部识别部分做了一些简单的介绍,并针对其所提供的API进行了一些调用相关的说明。微软在计算机视觉中提供的3方面功能,
- 人脸检测
主要是指传统概念上的人脸识别功能,识别图片中的人的面孔,给出人脸出现的坐标区域,并根据识别出来的人脸分析出一些基本的信息(例如年龄)。
- 人脸分组
可以在已经预制好的若干张人脸中根据相似度进行相似度搜索或者是根据相似度进行分组或者是认证操作。
- 人脸识别
可以通过给定一张人脸在构建并训练完成的PersonGroup中搜索指定的Person的功能。
微软认知服务中提供的有关人脸相关的API,涵盖了基本的人脸识别的任务,加以具体的业务逻辑,即可简单的实现人脸搜索、人脸鉴权等相关应用。望本文能够为初接触微软认知服务人脸识别的开发者给予一定便利。