البرنامج التعليمي: الكشف عن الحياة في الوجوه

تعلم كيفية دمج اكتشاف حيوية الوجه في سير عملك باستخدام منطق الخادم وتطبيقات العملاء المرافقة للواجهة الأمامية.

نصيحة

للحصول على معلومات عامة حول الكشف عن فعالية الوجه، راجع الدليل المفاهيمي.

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

مهم

تعد مجموعات SDK لعميل Face للحيوية ميزة مسورة. يجب عليك طلب الوصول إلى ميزة الحياة عن طريق ملء نموذج كمية التعرف على الوجه. عندما يتم منح اشتراكك في Azure الوصول، يمكنك تحميل حزمة تطوير Face Liveness.

المتطلبات المسبقه

  • اشتراك Azure - إنشاء واحد مجانا
  • يجب أن يكون لحسابك Azure دور مساهم خدمات معرفية حتى تتمكن من الموافقة على شروط الذكاء الاصطناعي المسؤول وإنشاء مورد. لتعيين هذا الدور إلى حسابك، اتبع الخطوات الواردة في تعيين الأدوار الوثائق، أو اتصل بالمسؤول.
  • بعد أن تحصل على اشتراك Azure، وأنشئ موردا في بوابة Azure للحصول على مفتاحك ونقطة النهاية الخاصة بك. بعد انتشاره، حدد "Go to resource".
    • تحتاج إلى المفتاح ونقطة النهاية من المورد الذي تقوم بإنشائه لتوصيل التطبيق الخاص بك بخدمة Face.
  • الوصول إلى القطع الأثرية المغلقة المطلوبة ل Azure Vision في Foundry Tools وحزمة تطوير Face Client SDK للهواتف المحمولة (iOS وAndroid) والويب.
  • الإلمام بميزة الكشف عن فعالية Face. راجع الدليل المفاهيمي.

نصيحة

بعد إكمال المتطلبات الأساسية، يمكنك تجربة تجربة الحياة على المنصات التالية:

  • iOS: متجر تطبيقات iOS — اضغط على شاشة التطبيق 10 مرات بعد التثبيت لتفعيل وضع المطور.
  • أندرويد: متجر Google Play — اضغط على شاشة التطبيق 10 مرات بعد التثبيت لتفعيل وضع المطور.
  • ويب: جربها مباشرة في Vision Studio.

يمكنك أيضا بناء وتشغيل عينة كاملة للواجهة الأمامية (iOS، أندرويد، أو ويب) من قسم Samples.

إعداد تطبيق الواجهة الأمامية

تتوفر مجموعات تطوير البرمجيات (SDKs) بعدة لغات لتبسيط التكامل مع تطبيق الواجهة الأمامية الخاص بك. راجع ملف README لمجموعة تطوير البرمجيات التي اخترتها في الأقسام التالية لدمج واجهة المستخدم والكود المطلوب.

مهم

تتطلب كل SDK للواجهة الأمامية الوصول إلى أصل مسور لتجميعه بنجاح. راجع التعليمات التالية لإعداد هذا الوصول.

بالنسبة إلى Swift iOS:

بالنسبة ل Kotlin/Java Android:

بالنسبة إلى JavaScript Web:

بمجرد دمجه في تطبيق الواجهة الأمامية، يبدأ SDK الكاميرا، ويوجه المستخدم لتعديل موقعه، ويجمع حمولة الحيوية، ويرسلها إلى خدمة Azure Face للمعالجة.

راقب قسم Releases في المستودع لتحديثات إصدارات SDK الجديدة وتمكين تنبيهات تحديث الاعتماد التلقائي—مثل GitHub Dependabot (لمستودعات GitHub) أو Renovate (GitHub، GitLab، Bitbucket، Azure Repos).

إجراء الكشف عن الحياة

تصف الخطوات التالية عملية التوزيع الموسيقي للحيوية:

مخطط لسير العمل الحيوي في Azure Face.

  1. يبدأ تطبيق الواجهة الأمامية فحص الحياة ويعلم خادم التطبيق.

  2. يقوم خادم التطبيق بإنشاء جلسة حياة جديدة باستخدام Azure Face Service. تنشئ الخدمة جلسة حيوية وتستجيب برمز تفويض جلسة. لمزيد من المعلومات حول كل معلمة طلب مرتبطة بإنشاء جلسة الحياة، راجع عملية إنشاء جلسة الحيوية.

    var endpoint = new Uri(System.Environment.GetEnvironmentVariable("FACE_ENDPOINT"));
    var key = new AzureKeyCredential(System.Environment.GetEnvironmentVariable("FACE_APIKEY"));
    
    var body = JsonSerializer.Serialize(new
    {
        livenessOperationMode = "PassiveActive",
        deviceCorrelationId = "723d6d03-ef33-40a8-9682-23a1feb7bccd",
        enableSessionImage = true
    });
    
    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
    
    var response = await client.PostAsync(
        $"{endpoint}/face/v1.2/detectLiveness-sessions",
        new StringContent(body, Encoding.UTF8, "application/json"));
    
    response.EnsureSuccessStatusCode();
    
    using var doc  = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
    var root       = doc.RootElement;
    
    Console.WriteLine("Session created");
    Console.WriteLine($"sessionId : {root.GetProperty("sessionId").GetString()}");
    Console.WriteLine($"authToken : {root.GetProperty("authToken").GetString()}");
    

    مثال على نص الاستجابة:

    {
        "sessionId": "a6e7193e-b638-42e9-903f-eaf60d2b40a5",
        "authToken": "<session-authorization-token>",
        "status": "NotStarted",
        "modelVersion": "2025-05-20",
        "results": {
            "attempts": []
        }
    }
    
  3. يوفر خادم التطبيق رمز تفويض الجلسة مرة أخرى إلى تطبيق الواجهة الأمامية.

  4. يستخدم تطبيق الواجهة الأمامية رمز تفويض الجلسة لبدء كاشف حيوية الوجه، الذي يطلق تدفق الحيوية.

        FaceLivenessDetector(
            sessionAuthorizationToken = FaceSessionToken.sessionToken,
            verifyImageFileContent = FaceSessionToken.sessionSetInClientVerifyImage,
            deviceCorrelationId = "null",
            onSuccess = viewModel::onSuccess,
            onError = viewModel::onError
        )
    
  5. تبدأ مجموعة تطوير البيانات الكاميرا، وتوجه المستخدم إلى الموقع الصحيح، ثم تجهز الحمولة للاتصال بنقطة نهاية خدمة كشف الحيوية.

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

  7. ينقل تطبيق الواجهة الأمامية إكمال التحقق من الحياة إلى خادم التطبيق.

  8. يقوم خادم التطبيق بالاستعلام عن نتيجة اكتشاف الحيوية من خدمة Azure Vision Face.

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
    
    var response = await client.GetAsync(
        $"{endpoint}/face/v1.2/livenessSessions/{sessionId}/result");
    
    response.EnsureSuccessStatusCode();
    
    using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
    var root = doc.RootElement;
    var attempts = root.GetProperty("results").GetProperty("attempts");
    var latestAttempt = attempts[attempts.GetArrayLength() - 1];
    var attemptStatus = latestAttempt.GetProperty("attemptStatus").GetString();
    
    Console.WriteLine($"Session id: {root.GetProperty("sessionId").GetString()}");
    Console.WriteLine($"Session status: {root.GetProperty("status").GetString()}");
    Console.WriteLine($"Latest attempt status: {attemptStatus}");
    
    if (attemptStatus == "Succeeded")
        Console.WriteLine($"Liveness detection decision: {latestAttempt.GetProperty("result").GetProperty("livenessDecision").GetString()}");
    else
    {
        var error = latestAttempt.GetProperty("error");
        Console.WriteLine($"Error: {error.GetProperty("code").GetString()} - {error.GetProperty("message").GetString()}");
    }
    

    مثال على نص الاستجابة:

    {
        "sessionId": "b12e033e-bda7-4b83-a211-e721c661f30e",
        "authToken": "eyJhbGciOiJFUzI1NiIsIm",
        "status": "NotStarted",
        "modelVersion": "2024-11-15",
        "results": {
            "attempts": [
                {
                    "attemptId": 2,
                    "attemptStatus": "Succeeded",
                    "result": {
                    "livenessDecision": "realface",
                    "targets": {
                        "color": {
                        "faceRectangle": {
                                "top": 669,
                                "left": 203,
                                "width": 646,
                                "height": 724
                            }
                        }
                    },
                    "digest": "B0A803BB7B26F3C8F29CD36030F8E63ED3FAF955FEEF8E01C88AB8FD89CCF761",
                    "sessionImageId": "Ae3PVWlXAmVAnXgkAFt1QSjGUWONKzWiSr2iPh9p9G4I"
                    }
                },
                {
                    "attemptId": 1,
                    "attemptStatus": "Failed",
                    "error": {
                    "code": "FaceWithMaskDetected",
                    "message": "Mask detected on face image.",
                    "targets": {
                            "color": {
                            "faceRectangle": {
                                "top": 669,
                                "left": 203,
                                "width": 646,
                                "height": 724
                            }
                            }
                        }
                    }
                }
            ]
        }
    }
    
  9. يقوم خادم التطبيق بحذف الجلسة بعد أن يستعلم بجميع نتائج الجلسات.

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
    
    await client.DeleteAsync($"{endpoint}/face/v1.2/livenessSessions/{sessionId}");
    Console.WriteLine($"Session deleted: {sessionId}");
    

إجراء الكشف عن الحياة مع التحقق من الوجه

يتيح الجمع بين التحقق من الوجه والكشف عن الحياة التحقق البيومتري لشخص معين ذي أهمية مع ضمان إضافي بأن الشخص موجود فعليا في النظام.

مخطط لسير عمل التحقق من الوضوح مع الوجه ل Azure Face.

دمج اكتشاف الحيوية مع التحقق يتضمن جزأين:

الخطوة 1 - تحديد صورة مرجعية

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

الخطوة 2 - إعداد تنسيق الحيوية مع التحقق

تظهر الخطوات العامة التالية كيفية تنظيم الحيوية مع التحقق:

  1. قدم صورة مرجعية للتحقق باستخدام إحدى الطريقتين التاليتين:

    • يوفر خادم التطبيق الصورة المرجعية عند إنشاء جلسة العمل. لمزيد من المعلومات حول كل معلمة طلب مرتبطة بإنشاء جلسة حيوية مع التحقق، راجع Liveness مع التحقق من إنشاء عملية الجلسة.

      var endpoint = new Uri(System.Environment.GetEnvironmentVariable("FACE_ENDPOINT"));
      var key      = System.Environment.GetEnvironmentVariable("FACE_APIKEY");
      
      // Create the JSON part
      var jsonPart = new StringContent(
          JsonSerializer.Serialize(new
          {
              livenessOperationMode = "PassiveActive",
              deviceCorrelationId = "723d6d03-ef33-40a8-9682-23a1feb7bcc",
              enableSessionImage = true
          }),
          Encoding.UTF8,
          "application/json"
      );
      jsonPart.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
      {
          Name = "CreateLivenessWithVerifySessionRequest"
      };
      
      // Create the file part
      using var fileStream = File.OpenRead("test.png");
      var filePart = new StreamContent(fileStream);
      filePart.Headers.ContentType = new MediaTypeHeaderValue("image/png");
      filePart.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
      {
          Name = "VerifyImage",
          FileName = "test.png"
      };
      
      // Build multipart form data
      using var formData = new MultipartFormDataContent();
      formData.Add(jsonPart);
      formData.Add(filePart);
      
      using var client = new HttpClient();
      client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
      
      var response = await client.PostAsync($"{endpoint}/face/v1.2/createLivenessWithVerifySession", formData);
      response.EnsureSuccessStatusCode();
      
      using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
      var root = doc.RootElement;
      
      Console.WriteLine("Session created.");
      Console.WriteLine($"Session id: {root.GetProperty("sessionId").GetString()}");
      Console.WriteLine($"Auth token: {root.GetProperty("authToken").GetString()}");
      

      مثال على نص الاستجابة:

      {
          "sessionId": "3847ffd3-4657-4e6c-870c-8e20de52f567",
          "authToken": "<session-authorization-token>",
          "status": "NotStarted",
          "modelVersion": "2024-11-15",
          "results": {
              "attempts": [],
              "verifyReferences": [
              {
                  "referenceType": "image",
                  "faceRectangle": {
                  "top": 98,
                  "left": 131,
                  "width": 233,
                  "height": 300
                  },
                  "qualityForRecognition": "high"
              }
              ]
          }
      }
      
    • يوفر تطبيق الواجهة الأمامية الصورة المرجعية عند تهيئة حزم SDK للأجهزة المحمولة. هذا السيناريو غير مدعوم في حل الويب.

          FaceLivenessDetector(
              sessionAuthorizationToken = FaceSessionToken.sessionToken,
              verifyImageFileContent = FaceSessionToken.sessionSetInClientVerifyImage,
              deviceCorrelationId = "null",
              onSuccess = viewModel::onSuccess,
              onError = viewModel::onError
          )
      
  2. يمكن لخادم التطبيق الآن الاستعلام عن نتيجة التحقق بالإضافة إلى نتيجة الحياة.

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
    
    var response = await client.GetAsync($"{endpoint}/face/v1.2/livenessSessions/{sessionId}/result");
    response.EnsureSuccessStatusCode();
    
    using var doc = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
    var root = doc.RootElement;
    
    var attempts = root.GetProperty("results").GetProperty("attempts");
    var latestAttempt = attempts[attempts.GetArrayLength() - 1];
    var attemptStatus = latestAttempt.GetProperty("attemptStatus").GetString();
    
    Console.WriteLine($"Session id: {root.GetProperty("sessionId").GetString()}");
    Console.WriteLine($"Session status: {root.GetProperty("status").GetString()}");
    Console.WriteLine($"Latest attempt status: {attemptStatus}");
    
    if (attemptStatus == "Succeeded")
    {
        var decision = latestAttempt.GetProperty("result").GetProperty("livenessDecision").GetString();
        var verify   = latestAttempt.GetProperty("verifyResult");
        Console.WriteLine($"Liveness detection decision: {decision}");
        Console.WriteLine($"Verify isIdentical: {verify.GetProperty("isIdentical").GetBoolean()}");
        Console.WriteLine($"Verify matchConfidence: {verify.GetProperty("matchConfidence").GetDouble()}");
    }
    else
    {
        var err = latestAttempt.GetProperty("error");
        Console.WriteLine($"Error: {err.GetProperty("code").GetString()} - {err.GetProperty("message").GetString()}");
    }
    

    مثال على نص الاستجابة:

    {
        "sessionId": "b12e033e-bda7-4b83-a211-e721c661f30e",
        "authToken": "eyJhbGciOiJFUzI1NiIsIm",
        "status": "NotStarted",
        "modelVersion": "2024-11-15",
        "results": {
            "attempts": [
            {
                "attemptId": 2,
                "attemptStatus": "Succeeded",
                "result": {
                "livenessDecision": "realface",
                "targets": {
                    "color": {
                    "faceRectangle": {
                        "top": 669,
                        "left": 203,
                        "width": 646,
                        "height": 724
                    }
                    }
                },
                "verifyResult": {
                    "matchConfidence": 0.08871888,
                    "isIdentical": false
                },
                "digest": "B0A803BB7B26F3C8F29CD36030F8E63ED3FAF955FEEF8E01C88AB8FD89CCF761",
                "sessionImageId": "Ae3PVWlXAmVAnXgkAFt1QSjGUWONKzWiSr2iPh9p9G4I",
                "verifyImageHash": "43B7D8E8769533C3290DBD37A84D821B2C28CB4381DF9C6784DBC4AAF7E45018"
                }
            },
            {
                "attemptId": 1,
                "attemptStatus": "Failed",
                "error": {
                    "code": "FaceWithMaskDetected",
                    "message": "Mask detected on face image.",
                    "targets": {
                        "color": {
                        "faceRectangle": {
                                "top": 669,
                                "left": 203,
                                "width": 646,
                                "height": 724
                            }
                        }
                    }
                }
            }
            ],
            "verifyReferences": [
                {
                    "referenceType": "image",
                    "faceRectangle": {
                    "top": 316,
                    "left": 131,
                    "width": 498,
                    "height": 677
                    },
                    "qualityForRecognition": "high"
                }
            ]
            }
        }
    
  3. يمكن لخادم التطبيق حذف الجلسة إذا لم تعد بحاجة إلى نتيجتها بعد الآن.

    using var client = new HttpClient();
    client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);
    
    await client.DeleteAsync($"{endpoint}/face/v1.2/livenessWithVerifySessions/{sessionId}");
    Console.WriteLine($"Liveness-with-Verify session deleted: {sessionId}");
    

إجراء عمليات الوجه الأخرى بعد الكشف عن الحياة

اختياريا، يمكنك إجراء عمليات إضافية للوجه بعد فحص الحيوية، مثل تحليل الوجوه (للحصول على سمات الوجه) وعمليات هوية الوجه.

  1. اضبط المعامل enableSessionImage على true خلال الخطوةSession-Creation.
  2. استخرج من sessionImageIdالجلسة -Get-Result خطوة.
  3. قم بتنزيل صورة الجلسة (المشار إليها في واجهة Liveness Get Session Image Operation API)، أو قدم في sessionImageId عملية Detect from Session Image ID API لمواصلة عمليات تحليل الوجوه أو عمليات الهوية الوجهية الأخرى. لمزيد من المعلومات حول هذه العمليات، راجع مفاهيم الكشف عن الوجهومفاهيم التعرف على الوجه.

خيارات الدعم

بالإضافة إلى استخدام خيارات دعم أدوات Foundry Tools الرئيسية، يمكنك أيضا نشر أسئلتك في قسم issues في مستودع SDK.

لتتعلم كيفية دمج حل الحيوية في تطبيقك الحالي، راجع مرجع حزمة تطوير البرمجيات Azure Vision.

لمعرفة المزيد حول الميزات المتوفرة لتنسيق حل الحياة، راجع مرجع واجهة برمجة تطبيقات REST للجلسة.