微软认知服务开发实践(3) - 人脸识别

前言

人们对人脸识别的研究已经有很长一段时间,起初局限于获取基础的人脸信息,随着机器学习领域的发展,人脸识别的应用更加广泛,已经可以被用于人脸搜索、人脸鉴权等相关应用。本文将针对微软认知服务中提供的人脸识别API的调用方法进行一些初步的讲解。

Face API

Face API中提供了3方面功能:

  1. 人脸检测
  2. 人脸分组
  3. 人脸识别(搜索)

首先是人脸检测,主要是指传统概念上的人脸识别功能,识别图片中的人的面孔,给出人脸出现的坐标区域,并根据识别出来的人脸分析出一些基本的信息(例如年龄)。

其次是人脸分组,可以在已经预制好的若干张人脸中根据相似度进行相似度搜索或者是根据相似度进行分组或者是认证操作。

最后是人脸识别,这里的人脸识别是指,通过给定一张人脸在构建并训练完成的人脸库中搜索名称的功能。

同样,Face API在调用过程中,也有一系列的限制,如果在调用过程中确认代码逻辑没有问题的情况下,依然出错,可以检查如下几点:

  1. 图片的格式需要是JPEG、PNG、GIF(仅限第一帧)以及BMP
  2. 图片尺寸不可以大于4MB
  3. 人脸像素需要介于36x36 (px)与4096x4096 (px)之间
  4. 每张照片中最多包含64张面部信息
  5. FaceID的有效期为24小时(自生成之时起)

人脸检测(Detect)

人脸检测功能,可以识别照片中人脸的位置信息,包括脸部的范围以及脸部的各个细节的位置(眼睛、鼻子、嘴等信息),还可以识别出面部装束信息(是否有胡子等),最后还可以针对所识别出来的人脸做一些智能的分析功能,可以获取性别、年龄、是否微笑等。

首先是接口URL:

https://api.projectoxford.ai/face/v1.0/detect[?returnFaceId][&returnFaceLandmarks][&returnFaceAttributes]

URL中包含了3个参数returnFaceId、returnFaceLandmarks以及returnFaceAttributes,3个参数都是可选参数。

returnFaceId 设定是否返回FaceID,默认值是true
returnFaceLandmarks 设定是否返回详细的面部细节位置信息(包括鼻子、眼睛、嘴等),默认值是false
*returnFaceAttributes 设定进行面部智能分析(分析性别、年龄、微笑等)的项目,可设置为agegenderheadPosesmilefacialHairglasses.多个项目中间使用逗号进行分割(,

*每项分析内容都需要增加额外的计算时间。

和之前在计算机视觉中介绍的类似,微软认知服务每个API的调用,都需要在Header中包含Ocp-Apim-Subscription-Key来标示出服务订阅的Key,可以在自己的账户中找到。

这个API通过POST的方式进行调用,除了必要的之外Ocp-Apim-Subscription-Key,还可以设置Content-Type

Content-Type(可选) 设定Content-Type信息,这个是可选的,不设定会根据Post过去的数据自动识别出来,可以设定为application/jsonapplication/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个功能,

  1. 首先是相似度搜索,将给定的面部信息在一系列面部信息中筛选出相似度比较高的前几项
  2. 其次是自动分组,将给定的一系列面部信息中,自动的进行分组
  3. 最后是鉴权认证,给定两个面部信息项,比对是否为相同,并给出相似度的值

这3个功能,都是基于相似度来进行的,所以这里将这三种都归结到人脸分组下面。

相似度搜索

在介绍相似度搜索前,笔者将对Face List API做一些简单的说明,因为相似度搜索包含两个参数项,首先是搜索的目标,其次是一组面部信息,而这组面部信息可以由JSON数组将ID传入,也可以根据以构建好的FaceList的ID传入。所以在此需要先介绍下FaceListAPI。

Face List

FaceListAPI中包含了一系列的调用用于构建、查询、修改以及删除一个FaceList这几种操作。

List Face Lists

接口URL:

https://api.projectoxford.ai/face/v1.0/facelists

该接口用于列举出该账户下已经注册了哪些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/jsonapplication/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:

https://api.projectoxford.ai/face/v1.0/findsimilars

该接口通过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:

https://api.projectoxford.ai/face/v1.0/group

该接口通过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:

https://api.projectoxford.ai/face/v1.0/verify

该接口通过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的调用,

  1. List Person Groups
  2. Create a Person Group
  3. Update a Person Group
  4. Delete a Person Group

List Person Groups

其中List Person Groups API的接口URL为,

https://api.projectoxford.ai/face/v1.0/persongroups

返回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,

  1. List Persons in a Person Group
  2. Create a Person
  3. Get a Person
  4. Update a Person
  5. 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信息进行构建,

  1. Add a Person Face to Person
  2. Update a Person Face
  3. 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,

  1. Train Person Group
  2. 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:

https://api.projectoxford.ai/face/v1.0/identify

请求通过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方面功能,

  1. 人脸检测

    主要是指传统概念上的人脸识别功能,识别图片中的人的面孔,给出人脸出现的坐标区域,并根据识别出来的人脸分析出一些基本的信息(例如年龄)。

  2. 人脸分组

    可以在已经预制好的若干张人脸中根据相似度进行相似度搜索或者是根据相似度进行分组或者是认证操作。

  3. 人脸识别

    可以通过给定一张人脸在构建并训练完成的PersonGroup中搜索指定的Person的功能。

微软认知服务中提供的有关人脸相关的API,涵盖了基本的人脸识别的任务,加以具体的业务逻辑,即可简单的实现人脸搜索、人脸鉴权等相关应用。望本文能够为初接触微软认知服务人脸识别的开发者给予一定便利。

时间: 2024-10-17 01:55:38

微软认知服务开发实践(3) - 人脸识别的相关文章

微软认知服务开发实践(2) - 计算机视觉

前言 计算机视觉所涉及的面很广泛,Computer Vision API中提供了几个常用的分析功能,可实现解读图片内容信息,对图片进行OCR识别,生成缩略图,未来也许会增加更多功能.本文将针对其分别是本文将针对Cognitive Services中提供的功能的调用方法做一些讲解. Computer Vision API 微软认知服务中的计算机视觉分析主要是针对一张静态图片进行分析,当然图片的格式会有一定的要求, 图片的格式需要是JPEG.PNG.GIF以及BMP 图片尺寸不可以大于4MB 图片像

【AI开发第一步】微软认知服务API应用

目录 介绍 API分类 使用‘视觉’API完成的Demo 点击直接看干货 介绍 从3月份Google家的阿尔法狗打败韩国围棋冠军选手李世石,到之后微软Build2016大会宣布的“智能机器人”战略.种种迹象表明未来慢慢会进入“人工智能”时代,人工智能不再像以前那样听起来高大上,普通的码农屌丝也能开发出具备人类智慧的APP.听起来是不是很叼? 以前是这样的: You:吴博士,您研究的主要方向是撒? 吴博士:人工智能. You:挖槽,好叼.你觉得未来机器人会不会控制人类呢? 吴博士:...... 现

微软认知服务应用秘籍 – 搭建基于云端的中间层以支持跨平台的智能视觉服务

不断演进的应用场景 初级应用场景—宅在家里 场景:Bob同学有一天在网上看到了一张建筑物的图片,大发感慨:"好漂亮啊!这是哪里?我要去亲眼看看!"Bob同学不想问别人,可笑的自尊心让他觉得这肯定是个著名的建筑,如果自己不知道多丢脸!怎么解决Bob同学的烦恼呢? 我们看看微软认知服务是否能帮助到Bob同学,打开这个链接: https://azure.microsoft.com/zh-cn/services/cognitive-services/computer-vision/ 向下卷滚屏

利用微软认知服务实现语音识别功能

想实现语音识别已经很久了,也尝试了许多次,终究还是失败了,原因很多,识别效果不理想,个人在技术上没有成功实现,种种原因,以至于花费了好多时间在上面.语音识别,我尝试过的有科大讯飞.百度语音,微软系.最终还是喜欢微软系的简洁高效.(勿喷,纯个人感觉) 最开始自己的想法是我说一句话(暂且在控制台上做Demo),控制台程序能识别我说的是什么,然后显示出来,并且根据我说的信息,执行相应的行为.(想法很美好,现实很糟心)初入语音识别,各种错误各种来,徘徊不定的选择哪家公司的api,百度上查找各种语音识别的

使用微软认知服务进行人脸识别

最近在搞一个人脸识别的功能,使用了微软的认知服务,一下讲一个我遇到的小问题. 首先添加相关相应的NuGet:Microsoft.ProjectOxford.Face 然后构造FaceServiceClient并调用DetectAsync方法识别人脸信息. 构造FaceServiceClient需要一个key,之前公司申请好了,过程没什么问题.之后由于使用的是免费的API,调用次数受到限制,打算自己再申请一个账户,过程麻烦的一B,实名制以及上传身份证等,,, 最后当然还是搞定了并拿到了Key,然而

PHP使用微软认知服务Face API

下面主要介绍基于PHP语言,基于guzzle类库,调用微软最新推出的认知服务:人脸识别. 实验环境: IDE:Eclipse for PHP Developers Version: Neon.1 Release (4.6.1) Server:WampServer Version 2.5 HttpClient:guzzle 1. 使用composer安装Guzzle composer.json文件 { "require": { "guzzlehttp/guzzle":

微软在Build 2016开发者大会中发布 “认知服务”,牛津计划有正式名字啦!

2016年3月30日:微软在Build 2016开发者大会中发布"认知服务". 在Build 2016开发者大会中,微软发布了新的智能服务:微软认知服务(Microsoft Cognitive Services).该服务集合了多种智能API以及知识API.借助这些API,开发者可以开发出更智能,更有吸引力的产品.微软认知服务集合了多种来自Bing,前"牛津计划"等项目的智能API.应用了这些API的系统能看,能听,能说话,并且能理解和解读我们通过自然交流方法所传达的

服务大众的人工智能---认知服务

什么是认知服务Cognitive Service? 认知服务是由微软在IBM认知计算[^1]的基础上提出来的,简单来讲,认知服务是基于文本分析.语音理解.以及视觉输入等形式经过人工智能网络分析后所提供的一种服务形式.微软认知服务的前身就是其大名鼎鼎的牛津计划[^2]项目,2015年火爆朋友圈的How-Old.net[^3]应用就是利用图片识别和情感分析等技术来判断一张图片中所有人的年龄,在很大程度上分析一个人的年龄基于一些固定的算法或者由于机器无法“理解”人类的“欺骗”技巧,所以可以对图片进行特

Android课程设计 人脸识别签到(二)

学习完百度人脸API的调用,现在即可开发自己的人脸识别签到系统,下面作者先贴上部分功能源码来给大家参考和学习 (一)百度人脸库的人脸验证 1°   获取待识别的照片 既然是人脸认证 那么当然首先得向百度人脸库添加你的人脸 然后再把你需要进行人脸识别的照片与百度人脸库的人脸进行校对,如果校对成功,即签到打卡成功 关于获取带人脸识别的照片,作者采取了两种方式获取(即时拍照.从相册导入) 即时拍照: Camera.setOnClickListener(new View.OnClickListener(