استخدم هيكل بيانات PersonDirectory (معاينة)

تنبيه

الوصول إلى خدمة Face محدود استنادا إلى معايير الأهلية والاستخدام من أجل دعم مبادئنا الذكاء الاصطناعي المسؤولة. تتوفر خدمة Face فقط للعملاء والشركاء المدارين من Microsoft. استخدم نموذج إدخال التعرف على الوجوه لتقديم طلب للوصول. لمزيد من المعلومات، راجع صفحة Face ذات الوصول المحدود.

من أجل تنفيذ عمليات التعرف على الوجه مثل تحديد الهوية والعثور على ما يشابهه، يحتاج عملاء واجهة برمجة التطبيقات لإنشاء قائمة متنوعة من كائنات الشخص. PersonDirectory هو بنية بيانات في معاينة عامة تحتوي على معرفات فريدة وسلاسل أسماء اختيارية وسلاسل بيانات تعريف مستخدم اختيارية لكل هوية شخص تمت إضافتها إلى الدليل. اتبع هذا الدليل لمعرفة كيفية القيام بالمهام الأساسية باستخدام PersonDirectory.

مزايا PersonDirectory

حاليًا، توفر واجهة برمجة التطبيقات Face بنية LargePersonGroup التي لديها وظائف مماثلة ولكن تقتصر على 1 مليون هوية. يمكن لبنية PersonDirectory توسيع نطاق ما يصل إلى 75 مليون هوية.

هناك اختلاف رئيسي آخر بين PersonDirectory وهياكل البيانات السابقة، وهو أنك لن تحتاج بعد الآن إلى إجراء أي تدريب استدعاء واجهة برمجة التطبيقات للنظام بعد إضافة الوجوه إلى عنصر شخص - تحدث عملية التحديث تلقائياً.

المتطلبات الأساسية

  • اشتراك Azure - إنشاء حساب مجانًا
  • بمجرد اشتراكك في Azure، أنشئ مورد Face في مدخل Microsoft Azure للحصول على المفتاح ونقطة النهاية. بعد انتشاره، حدد "Go to resource".
    • ستحتاج إلى المفتاح ونقطة النهاية من المورد الذي تنشئه لتوصيل التطبيق بواجهة برمجة تطبيقات Face. ستلصق المفتاح ونقطة النهاية في التعليمة البرمجية أدناه.
    • يمكنك استخدام مستوى التسعير الحر (F0⁩) لتجربة الخدمة، والترقية لاحقًا إلى مستوى مدفوع للإنتاج.

تتم إضافة أشخاص إلى PersonDirectory

الأشخاص هم وحدات التسجيل الأساسية في PersonDirectory. بمجرد إضافة شخص إلى الدليل، يمكنك إضافة ما يصل إلى 248 صورة وجه إلى هذا شخص، لكل نموذج التعرف. ثم يمكنك تحديد الوجوه ضدهم باستخدام نطاقات مختلفة.

إنشاء شخص

لإنشاء شخص، تحتاج إلى استدعاء واجهة برمجة تطبيقات CreatePerson وتوفير اسم أو قيمة خاصية 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));

بمجرد إرجاع الحالة على أنها "succeeded"، يعتبر عنصر الشخص مضافًا إلى الدليل.

إشعار

لا يلزم أن تظهر العملية غير المتزامنة من استدعاء Create شخص حالة "succeeded" قبل إضافة الوجوه إليها، ولكنها تحتاج إلى إكمالها قبل أن يمكن إضافة شخص إلى 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 وتحديثه

تمثل مجموعات DynamicPersonGroups مجموعات من المراجع إلى عناصر شخص داخل PersonDirectoryيتم استخدامها لإنشاء مجموعات فرعية من الدليل. الاستخدام الشائع هو عندما تريد الحصول على عدد أقل من الإيجابيات الخاطئة وزيادة الدقة في عملية تحديد عن طريق قصر النطاق على عناصر شخص التي تتوقع مطابقتها فحسب. تتضمن حالات الاستخدام العملية دلائل للوصول إلى مبنى معين بين حرم أو مؤسسة أكبر. قد يحتوي دليل المؤسسة على 5 ملايين شخص، ولكنك تحتاج إلى البحث في 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

بعد الإنشاء الأولي، يمكنك إضافة مراجع شخص وإزالتها من DynamicPersonGroup باستخدام تحديث Dynamic Person Group API. لإضافة كائنات شخص إلى المجموعة، قم بإدراج معرفات شخص في الوسيطة 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");
}

بمجرد إرجاع الاستدعاء، ستنعكس تحديثات المجموعة عند الاستعلام عن المجموعة. كما هو الحال مع واجهة برمجة تطبيقات الإنشاء، تشير العملية التي تم إرجاعها إلى حالة تحديث علاقة شخص إلى مجموعة لأي شخص مشارك في التحديث. لا تحتاج إلى انتظار اكتمال العملية قبل إجراء مزيد من استدعاءات التحديث إلى المجموعة.

تحديد الوجوه في PersonDirectory

الطريقة الأكثر شيوعًا لاستخدام بيانات الوجه في PersonDirectory هي مقارنة عناصر شخص المسجلة بوجه معين وتحديد المرشح الأكثر احتمالًا الذي تنتمي إليه. يمكن توفير وجوه متعددة في الطلب، وسيتلقى كل منها مجموعة نتائج المقارنة الخاصة به في الاستجابة.

في PersonDirectory، توجد ثلاثة أنواع من النطاقات يمكن تحديد كل وجه مقابلها:

السيناريو 1: تحديد مقابل DynamicPersonGroup

يؤدي تحديد الخاصية dynamicPersonGroupId في الطلب إلى مقارنة الوجه مع كل Person مشار إليه في المجموعة. يمكن تحديد 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 لتخزين بيانات الوجه والشخص لتطبيق Face. بعد ذلك، تعرف على أفضل الممارسات لإضافة بيانات وجه المستخدمين.