دليل "التعرّف على الوجوه" على أجهزة Android

تتيح لك مهمة "مُعترِف الوجوه" من MediaPipe رصد الوجوه في صورة أو فيديو. يمكنك استخدام هذه المهمة لتحديد موقع الوجوه وملامح الوجه في إطار معيّن. تستخدِم هذه المهمة نموذجًا لتعلُّم الآلة يعمل مع صور فردية أو مجرى متواصل من الصور. تُخرج المهمة مواقع الوجوه، بالإضافة إلى النقاط الرئيسية التالية للوجه: العين اليسرى والعين اليمنى وطرف الأنف والفم ونقطة تراجيديون للعين اليسرى ونقطة تراجيديون للعين اليمنى.

يتوفّر نموذج الرمز البرمجي الموضّح في هذه التعليمات على GitHub. لمزيد من المعلومات عن الإمكانات والنماذج وخيارات الإعداد لهذه المهمة، اطّلِع على نظرة عامة.

مثال على الرمز البرمجي

مثال التعليمات البرمجية لمهام MediaPipe هو تطبيق بسيط لنظام التشغيل Android يتضمّن ميزة "كاشف الوجوه". يستخدم المثال الكاميرا على جهاز Android مادي لرصد الوجوه في بث فيديو مستمر. يمكن للتطبيق أيضًا رصد الوجوه في الصور والفيديوهات من معرض الصور على الجهاز.

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

تنزيل الرمز

توضِّح لك التعليمات التالية كيفية إنشاء نسخة محلية من مثال الرمز البرمجي باستخدام أداة سطر الأوامر git.

لتنزيل نموذج الرمز البرمجي:

  1. استنسِخ مستودع git باستخدام الأمر التالي:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. يمكنك اختياريًا ضبط مثيل git لاستخدام ميزة "الفحص الخفيف"، لكي لا يتوفّر لديك سوى ملفات مثال تطبيق "مُعترِف الوجوه":
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/face_detector/android
    

بعد إنشاء نسخة محلية من رمز المثال، يمكنك استيراد المشروع إلى "استوديو Android" وتشغيل التطبيق. للحصول على التعليمات، اطّلِع على دليل الإعداد لنظام التشغيل Android.

المكونات الرئيسية

تحتوي الملفات التالية على الرمز البرمجي المهم لهذا المثال على تطبيق "اكتشاف الوجوه":

  • FaceDetectorHelper.kt: تُستخدَم هذه الفئة لإعداد أداة رصد الوجوه ومعالجة النموذج وتحديد المهام المفوَّضة.
  • CameraFragment.kt: تعالج كاميرا الجهاز وبيانات إدخال الصور والفيديوهات.
  • GalleryFragment.kt: تتفاعل مع OverlayView لعرض الصورة أو الفيديو الناتج.
  • OverlayView.kt: تنفِّذ هذه الفئة العرض باستخدام مربّعات حدودية للوجوه التي تم رصدها.

ضبط إعدادات الجهاز

يوضّح هذا القسم الخطوات الرئيسية لإعداد بيئة التطوير و مشاريع الرموز البرمجية لاستخدام ميزة "مُعترِف الوجوه" على وجه التحديد. للحصول على معلومات عامة عن إعداد بيئة التطوير لاستخدام مهام MediaPipe، بما في ذلك متطلبات إصدار النظام الأساسي، يُرجى الاطّلاع على دليل الإعداد لنظام التشغيل Android.

التبعيات

تستخدِم مهمة "كاشف الوجوه" مكتبة com.google.mediapipe:tasks-vision. أضِف هذه التبعية إلى ملف build.gradle لتطبيق Android:

dependencies {
    implementation 'com.google.mediapipe:tasks-vision:latest.release'
}

الطراز

تتطلّب مهمة "كاشف الوجوه" من MediaPipe حِزمة نموذج مدرَّب متوافقة مع هذه المهمة. لمزيد من المعلومات عن النماذج المدربة المتاحة لـ "كاشف الوجوه"، اطّلِع على النظرة العامة على المهمة في قسم "النماذج".

اختَر النموذج ونزِّله واحفظه في دليل مشروعك:

<dev-project-root>/src/main/assets

حدِّد مسار النموذج ضمن المَعلمة ModelAssetPath. في المثال التالي على الرمز، يتم تحديد التصميم في ملف FaceDetectorHelper.kt:

val modelName = "face_detection_short_range.tflite"
baseOptionsBuilder.setModelAssetPath(modelName)

إنشاء المهمة

تستخدِم مهمة "كاشف الوجوه" من MediaPipe الدالة createFromOptions() لإعداد المهمة. تقبل الدالة createFromOptions() قيمًا لإعدادات options. لمزيد من المعلومات حول خيارات الضبط، يُرجى الاطّلاع على خيارات الضبط.

يتيح "أداة رصد الوجوه" أنواع بيانات الإدخال التالية: الصور الثابتة وملفات الفيديو و عمليات بث الفيديو المباشر. يجب تحديد وضع التشغيل المقابل لنوع data input عند إنشاء المهمة. اختَر علامة التبويب التي تتوافق مع نوع بيانات الإدخال للاطّلاع على كيفية إنشاء المهمة وتنفيذ الاستنتاج.

صورة

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setRunningMode(RunningMode.IMAGE)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

فيديو

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setRunningMode(RunningMode.VIDEO)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

بث مباشر

val baseOptionsBuilder = BaseOptions.builder().setModelAssetPath(modelName)
val baseOptions = baseOptionBuilder.build()

val optionsBuilder =
    FaceDetector.FaceDetectorOptions.builder()
        .setBaseOptions(baseOptionsBuilder.build())
        .setMinDetectionConfidence(threshold)
        .setResultListener(this::returnLivestreamResult)
        .setErrorListener(this::returnLivestreamError)
        .setRunningMode(RunningMode.LIVE_STREAM)

val options = optionsBuilder.build()

FaceDetector =
    FaceDetector.createFromOptions(context, options)
    

يتيح مثال تنفيذ رمز "كاشف الوجوه" للمستخدم التبديل بين أوضاع المعالجة. تؤدي هذه الطريقة إلى جعل رمز إنشاء المهام أكثر تعقيدًا، وقد لا يكون مناسبًا لحالة الاستخدام. يمكنك الاطّلاع على هذا الرمز في دالة setupFaceDetector() في ملف FaceDetectorHelper.kt.

خيارات الضبط

تتضمّن هذه المهمة خيارات الضبط التالية لتطبيقات Android:

اسم الخيار الوصف نطاق القيمة القيمة التلقائية
runningMode لضبط وضع التشغيل للمهمة هناك ثلاثة أوضاع:

IMAGE: وضع الإدخالات باستخدام صورة واحدة.

‫VIDEO: وضع الإطارات التي تم فك ترميزها في الفيديو

LIVE_STREAM: وضع البث المباشر لبيانات الإدخال ، مثل بيانات الكاميرا في هذا الوضع، يجب استدعاء resultListener لإعداد مستمع لتلقّي النتائج بشكل غير متزامن.
{IMAGE, VIDEO, LIVE_STREAM} IMAGE
minDetectionConfidence الحد الأدنى لنتيجة الثقة ليعتبر رصد الوجه ناجحًا Float [0,1] 0.5
minSuppressionThreshold الحد الأدنى لمستوى عدم قمع الحد الأقصى لميزة "اكتشاف الوجه" التي يتم اعتبارها متداخلة Float [0,1] 0.3
resultListener يضبط مستمع النتائج لتلقّي نتائج الكشف بشكل غير متزامن عندما يكون "مُعترِف الوجوه" في وضع البث المباشر. لا يمكن استخدامها إلا عند ضبط وضع التشغيل على LIVE_STREAM. N/A Not set
errorListener تُستخدَم لضبط مستمع أخطاء اختياري. N/A Not set

إعداد البيانات

تعمل ميزة "كاشف الوجوه" مع الصور وملفات الفيديو وأحداث البث المباشر للفيديوهات. تعالج المهمة المعالجة المُسبَقة لإدخال البيانات، بما في ذلك تغيير الحجم والدوران ومعالجة قيم البيانات.

يوضّح الرمز البرمجي التالي كيفية تسليم البيانات لمعالجتها. تتضمّن هذه النماذج تفاصيل عن كيفية التعامل مع البيانات من الصور وملفات الفيديو وعمليات البث المباشر للفيديو.

صورة

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(image).build()
    

فيديو

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

val argb8888Frame =
    if (frame.config == Bitmap.Config.ARGB_8888) frame
    else frame.copy(Bitmap.Config.ARGB_8888, false)

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(argb8888Frame).build()
    

بث مباشر

import com.google.mediapipe.framework.image.BitmapImageBuilder
import com.google.mediapipe.framework.image.MPImage

// Convert the input Bitmap object to an MPImage object to run inference
val mpImage = BitmapImageBuilder(rotatedBitmap).build()
    

في مثال رمز برمجي لبرنامج "كاشف الوجوه"، تتم معالجة إعداد البيانات في ملف FaceDetectorHelper.kt.

تنفيذ المهمة

استنادًا إلى نوع البيانات التي تعمل معها، استخدِم طريقة faceDetector.detect...() الخاصة بهذا النوع من البيانات. استخدِم ‎ detect() للصور الفردية و‎ detectForVideo() للإطارات في ملفات الفيديو و‎ detectAsync() لأحداث بث الفيديو. عند إجراء عمليات رصد في مجرى فيديو، تأكَّد من تشغيل عمليات الرصد في سلسلة محادثات منفصلة لتجنُّب حظر سلسلة محادثات واجهة المستخدم.

تعرض عيّنات الرموز البرمجية التالية أمثلة بسيطة على كيفية تشغيل "كاشف الوجوه" في أوضاع البيانات المختلفة التالية:

صورة

val result = faceDetector.detect(mpImage)
    

فيديو

val timestampMs = i * inferenceIntervalMs

faceDetector.detectForVideo(mpImage, timestampMs)
    .let { detectionResult ->
        resultList.add(detectionResult)
    }
    

بث مباشر

val mpImage = BitmapImageBuilder(rotatedBitmap).build()
val frameTime = SystemClock.uptimeMillis()

faceDetector.detectAsync(mpImage, frameTime)
    

يُرجى ملاحظة ما يلي:

  • عند التشغيل في وضع الفيديو أو وضع البث المباشر، يجب تقديم الطابع الزمني لإطار الإدخال إلى مهمة "كاشف الوجوه".
  • عند التشغيل في وضع الصورة أو الفيديو، تحظر مهمة "كاشف الوجوه" السلسلة المُشغّلة الحالية إلى أن تنتهي من معالجة الصورة أو الإطار المُدخل. لتجنّب حظر واجهة المستخدم، نفِّذ المعالجة في سلسلسة مهام في الخلفية.
  • عند التشغيل في وضع البث المباشر، تُعرِض مهمة "كاشف الوجوه" نتيجةً فورية ولا تحظر سلسلة المحادثات الحالية. سيستدعي المُستمع للنتائج نتيجة الكشف في كل مرة تنتهي فيها عملية معالجة إطار الإدخال. إذا تم استدعاء دالة الكشف عندما تكون مهمة "كاشف الوجوه" مشغولة في معالجة إطار آخر، ستتجاهل المهمة إطار الإدخال الجديد.

في المثال على رمز برمجي لبرنامج "كاشف الوجوه"، تم تعريف الدوال detect وdetectForVideo و detectAsync في ملف FaceDetectorHelper.kt.

معالجة النتائج وعرضها

يعرض "كاشف الوجوه" عنصرًا من النوع FaceDetectorResult لكل عملية رصد تتم. يحتوي عنصر النتيجة على مربّعات حدود للوجوه التي تم رصدها و درجة ثقة لكل وجه تم رصده.

في ما يلي مثال على بيانات الإخراج من هذه المهمة:

FaceDetectionResult:
  Detections:
    Detection #0:
      BoundingBox:
        origin_x: 126
        origin_y: 100
        width: 463
        height: 463
      Categories:
        Category #0:
          index: 0
          score: 0.9729152917861938
      NormalizedKeypoints:
        NormalizedKeypoint #0:
          x: 0.18298381567001343
          y: 0.2961040139198303
        NormalizedKeypoint #1:
          x: 0.3302789330482483
          y: 0.29289937019348145
        ... (6 keypoints for each face)
    Detection #1:
      BoundingBox:
        origin_x: 616
        origin_y: 193
        width: 430
        height: 430
      Categories:
        Category #0:
          index: 0
          score: 0.9251380562782288
      NormalizedKeypoints:
        NormalizedKeypoint #0:
          x: 0.6151331663131714
          y: 0.3713381886482239
        NormalizedKeypoint #1:
          x: 0.7460576295852661
          y: 0.38825345039367676
        ... (6 keypoints for each face)

تعرض الصورة التالية عرضًا مرئيًا لمعدّل تكرار المهمة:

طفلان مع مربّعات حدودية حول وجهيهما

للاطّلاع على الصورة بدون مربّعات الحدود، راجِع الصورة الأصلية.

يوضّح مثال رمز "كاشف الوجوه" كيفية عرض النتائج التي تم عرضها من المهمة، اطّلِع على فئة OverlayView لمزيد من التفاصيل.