使用 PersonDirectory 資料結構 (預覽版)

警告

臉部辨識服務存取受限於資格和使用準則,以支援我們的「負責任的 AI 原則」。 臉部辨識服務僅供 Microsoft 受管理的客戶和合作夥伴使用。 請使用臉部辨識受理表單以申請存取。 如需詳細資訊,請參閱臉部的有限存取權頁面。

若要執行臉部辨識作業 (例如識別和尋找類似的項目),臉部 API 客戶必須建立各種人員物件清單。 PersonDirectory 是公開預覽中的一種資料結構,其中包含新增至目錄之每個 Person 身分識別的唯一識別碼、選擇性的名稱字串和選擇性的使用者中繼資料字串。 請遵循本指南,了解如何使用 PersonDirectory 進行基本工作。

PersonDirectory 的優點

目前,臉部 API 提供的 LargePersonGroup 結構具有類似的功能,但受限於 1 百萬個身分識別。 PersonDirectory 結構最多可擴大至 7 千 5 百萬個身分識別。

PersonDirectory 和先前的資料結構的主要差別在於,在向人員物件新增臉部後,您就不再需要進行任何定型 API 呼叫,更新程序會自動發生。

Prerequisites

  • Azure 訂用帳戶 - 建立免費帳戶
  • 擁有 Azure 訂用帳戶之後,在 Azure 入口網站中建立臉部資源,以取得您的金鑰和端點。 在其部署後,選取 [前往資源]。
    • 您需要來自所建立資源的金鑰和端點,以將應用程式連線至 Face API。 您將在下列程式碼中貼上您的金鑰和端點。
    • 您可以使用免費定價層 (F0) 來試用服務,之後可升級至付費層以用於生產環境。

將人員新增至 PersonDirectory

人員PersonDirectory 中的基本註冊單位。 將人員新增至目錄之後,您可以為該人員新增多達 248 個臉部影像 (每一辨識模型)。 然後,您可以使用不同的範圍識別這些影像中的臉部。

建立人員

若要建立人員,您必須呼叫 CreatePerson API,並提供名稱或 userData 屬性值。

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var addPersonUri = "https:// {endpoint}/face/v1.0-preview/persons";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Person");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(addPersonUri, content); 
}

CreatePerson 呼叫會傳回為人員和作業位置產生的識別碼。 人員資料將以非同步方式處理,因此您可以使用作業位置來擷取結果。

等候非同步作業完成

您必須使用傳回的作業位置字串查詢非同步作業狀態,以檢查作業進度。

首先,您應該定義如下的資料模型來處理狀態回應。

[Serializable]
public class AsyncStatus
{
    [DataMember(Name = "status")]
    public string Status { get; set; }

    [DataMember(Name = "createdTime")]
    public DateTime CreatedTime { get; set; }

    [DataMember(Name = "lastActionTime")]
    public DateTime? LastActionTime { get; set; }

    [DataMember(Name = "finishedTime", EmitDefaultValue = false)]
    public DateTime? FinishedTime { get; set; }

    [DataMember(Name = "resourceLocation", EmitDefaultValue = false)]
    public string ResourceLocation { get; set; }

    [DataMember(Name = "message", EmitDefaultValue = false)]
    public string Message { get; set; }
}

使用上述 HttpResponseMessage,您即可輪詢 URL 並等候結果。

string operationLocation = response.Headers.GetValues("Operation-Location").FirstOrDefault();

Stopwatch s = Stopwatch.StartNew();
string status = "notstarted";
do
{
    if (status == "succeeded")
    {
        await Task.Delay(500);
    }

    var operationResponseMessage = await client.GetAsync(operationLocation);

    var asyncOperationObj = JsonConvert.DeserializeObject<AsyncStatus>(await operationResponseMessage.Content.ReadAsStringAsync());
    status = asyncOperationObj.Status;

} while ((status == "running" || status == "notstarted") && s.Elapsed < TimeSpan.FromSeconds(30));

傳回的狀態為「成功」,則會將人員物件視為已新增至目錄。

注意

來自建立人員呼叫的非同步作業不需要顯示「成功」狀態,即可將臉部新增至其中,但必須先完成作業,才能將人員新增至 DynamicPersonGroup (請參閱下方的建立和更新 DynamicPersonGroup),或是在識別呼叫期間進行比較。 確認呼叫可在臉部成功新增至人員之後立即運作。

將臉部新增至人員

在您透過「建立人員」呼叫取得人員識別碼後,即可為每個辨識模型的人員新增最多 248 個臉部影像。 指定要在呼叫中使用的辨識模型 (並選擇性地指定偵測模型),因為每個辨識模型下的資料將會在 PersonDirectory 內個別處理。

目前支援的辨識模型為:

  • Recognition_02
  • Recognition_03
  • Recognition_04

此外,如果影像包含多個臉部,您必須為作為預定目標的臉部指定矩形週框方塊。 下列程式碼會將臉部新增至人員物件。

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var queryString = "userData={userDefinedData}&targetFace={left,top,width,height}&detectionModel={detectionModel}";
var uri = "https://{endpoint}/face/v1.0-preview/persons/{personId}/recognitionModels/{recognitionModel}/persistedFaces?" + queryString;

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("url", "{image url}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

在「新增臉部呼叫」之後,臉部資料將會以非同步方式處理,而您必須以和之前相同的方式等候作業成功。

當新增臉部的作業完成時,資料會在識別呼叫中準備就緒。

建立和更新 DynamicPersonGroup

DynamicPersonGroupsPersonDirectory人員物件的參考集合,可用來建立目錄子集。 常見用法之一,是您想要在識別作業中取得較少的誤判為真和較高的精確度,而將範圍限定為您預期要符合的人員物件。 實際的使用案例包括在較大的校園或組織間存取特定建築物的目錄。 組織目錄可能包含 500 萬個人,但您只需要搜尋特定的 800 個人以找出特定建築物,因此您將建立包含這些特定人員的 DynamicPersonGroup

如果您先前使用過 PersonGroup,請留意兩項主要的差異:

  • DynamicPersonGroup 內的每個都是 PersonDirectory 中實際人員的參考,這表示不需要在每個群組中重新建立人員
  • 如前幾節所述,不需要進行定型呼叫,因為臉部資料會自動在目錄層級進行處理。

建立群組

若要建立 DynamicPersonGroup,您必須提供包含英數字元或虛線字元的群組識別碼。 此識別碼將作為群組各種用途的唯一識別碼。

有兩種方式可以初始化群組集合。 您可以先建立空的群組,稍後再加以填入:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);
}

此程序是即時的,不需要等待任何非同步作業成功。

或者,您可以在 AddPersonIds 引數中提供一組人員識別碼,用以建立在一開始就包含這些參考的群組:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example DynamicPersonGroup");
body.Add("userData", "User defined data");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PutAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

注意

一旦呼叫傳回,已建立的 DynamicPersonGroup 即可在識別呼叫中使用,並在程序中提供任何人員參考。 另一方面,傳回的作業識別碼的完成狀態表示「人員對群組」關聯性的更新狀態。

更新 DynamicPersonGroup

初始建立後,您可以使用「更新動態人員群組 API」來新增和移除 DynamicPersonGroup 中的人員參考。 若要將 Person 物件新增至群組,請在 addPersonsIds 引數中列出人員識別碼。 若要移除人員物件,請在 removePersonIds 引數中將其列出。 新增和移除可以在單一呼叫中執行:

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/dynamicpersongroups/{dynamicPersonGroupId}";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("name", "Example Dynamic Person Group updated");
body.Add("userData", "User defined data updated");
body.Add("addPersonIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("removePersonIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PatchAsync(uri, content);

    // Async operation location to query the completion status from
    var operationLocation = response.Headers.Get("Operation-Location");
}

呼叫傳回後,就會在查詢群組時反映集合的更新。 如同建立 API,傳回的作業會指出涉及更新的任何的「人員-群組」關聯性的更新狀態。 在對群組進行進一步的更新呼叫之前,不需要等待作業完成。

識別 PersonDirectory 中的臉部

PersonDirectory 中使用臉部資料的常見方式,首推將已註冊的人員物件與指定的臉部進行比較,並識別最有可能屬於哪個候選項目。 在要求中可提供多個臉部,每個臉部都會在回應中收到本身的比較結果集。

PersonDirectory 中,每個臉部有三種類型的範圍可供識別:

案例 1:對 DynamicPersonGroup 進行識別

在要求中指定 dynamicPersonGroupId 屬性,會將臉部與群組中參考的每個進行比較。 在一個呼叫中只能對單一 DynamicPersonGroup 進行識別。

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

// Optional query strings for more fine grained face control
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("dynamicPersonGroupId", "{dynamicPersonGroupIdToIdentifyIn}");
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

案例 2:對特定人員清單進行識別

您也可以在 personIds 屬性中指定人員識別碼清單,將臉部與其一一比較。

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"{guid1}", "{guid2}", …});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

案例 3:對整個 PersonDirectory 進行識別

在要求的 personIds 屬性中提供單一星號,會將臉部與註冊於 PersonDirectory 中的每個進行比較。

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");
            
var uri = "https://{endpoint}/face/v1.0-preview/identify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceIds", new List<string>{"{guid1}", "{guid2}", …});
body.Add("personIds", new List<string>{"*"});
byte[] byteData = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

在這三個案例中,識別只會將傳入的臉部與 AddPersonFace 呼叫傳回了「成功」回應的臉部進行比較。

PersonDirectory 中的人員驗證臉部

透過從偵測呼叫傳回的臉部識別碼,您可以確認臉部是否屬於在 PersonDirectory 內註冊的特定人員。 使用 personId 屬性指定人員

var client = new HttpClient();

// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "{subscription key}");

var uri = "https://{endpoint}/face/v1.0-preview/verify";

HttpResponseMessage response;

// Request body
var body = new Dictionary<string, object>();
body.Add("faceId", "{guid1}");
body.Add("personId", "{guid1}");
var jsSerializer = new JavaScriptSerializer();
byte[] byteData = Encoding.UTF8.GetBytes(jsSerializer.Serialize(body));

using (var content = new ByteArrayContent(byteData))
{
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    response = await client.PostAsync(uri, content);
}

回應會包含布林值,指出服務是否將新的臉部視為屬於相同人員,以及預測的信賴分數。

下一步

在本指南中,您已了解如何使用 PersonDirectory 結構來儲存臉部應用程式的臉部和人員資料。 接下來,請了解新增使用者臉部資料的最佳做法。