إنشاء تطبيق ويب مخصّص لرصد العناصر باستخدام MediaPipe

1. قبل البدء

تتيح لك MediaPipe Solutions تطبيق حلول تعلُّم الآلة (ML) على تطبيقاتك. توفّر هذه الأداة إطارًا يتيح لك إعداد مسارات معالجة مُعدَّة مسبقًا توفّر للمستخدمين نتائج فورية وجذّابة ومفيدة. ويمكنك تخصيص هذه الحلول باستخدام مصمم النماذج لتحديث النماذج التلقائية.

ميزة "رصد العناصر" هي إحدى مهام الرؤية المستندة إلى تعلُّم الآلة التي تقدّمها منصة MediaPipe Solutions. تتوفّر "مهام MediaPipe" لنظام التشغيل Android وPython والويب.

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

ما ستتعرَّف عليه

  • كيفية دمج مهمة رصد الكائنات في تطبيق ويب باستخدام MediaPipe Tasks

ما الذي ستقوم ببنائه

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

المتطلبات

  • حساب CodePen
  • جهاز مزوّد بمتصفّح ويب
  • معرفة أساسية بـ JavaScript وCSS وHTML

2. الإعداد

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

للإعداد، يُرجى اتّباع الخطوات التالية:

  1. في حسابك على CodePen، انتقِل إلى CodePen هذا. يمكنك استخدام هذا الرمز كقاعدة بداية لإنشاء أداة رصد الكائنات الخاصة بك.
  2. في أسفل CodePen في قائمة التنقل، انقر على Fork لإنشاء نسخة من رمز إجراء التفعيل.

قائمة التنقل في CodePen حيث يوجد زر Fork

  1. في علامة التبويب JS، انقر على سهم التوسيع b15acb07e6357dce.png، ثم اختَر تكبير محرِّر JavaScript. ما عليك سوى تعديل العمل في علامة التبويب JS الخاص بهذا الدرس التطبيقي حول الترميز، لذا لن تحتاج إلى رؤية علامة التبويب HTML أو CSS.

مراجعة تطبيق إجراء التفعيل

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

معاينة لتطبيق الويب من رمز إجراء التفعيل

  1. في علامة التبويب JavaScript، لاحظ وجود عدة تعليقات في الرمز البرمجي. على سبيل المثال، يمكنك العثور على التعليق التالي في السطر 15:
// Import the required package.

تشير هذه التعليقات إلى الموضع الذي يجب إدراج مقتطفات الرمز فيه.

3- قم باستيراد حزمة MediaPipe Tasks-vision وأضف المتغيرات المطلوبة

  1. في علامة التبويب JS، استورِد حزمة MediaPipe tasks-vision:
// Import the required package.
​​import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";

ويستخدم هذا الرمز شبكة توصيل المحتوى (CDN) في Skypack لاستيراد الحزمة. لمزيد من المعلومات حول كيفية استخدام Skypack مع CodePen، يُرجى الاطّلاع على Skypack + CodePen.

وفي مشاريعك، يمكنك استخدام Node.js مع npm أو مدير الحزمة أو شبكة توصيل المحتوى الذي تختاره. لمزيد من المعلومات حول الحزمة المطلوبة التي تحتاج إلى تثبيتها، يمكنك الاطّلاع على حزم JavaScript.

  1. تعريف المتغيّرات لأداة رصد الكائنات ووضع التشغيل:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";

المتغيّر runningMode هو سلسلة يتم ضبطها على قيمة "IMAGE" عند رصد عناصر في الصور أو على قيمة "VIDEO" عند رصد عناصر في الفيديو.

4. إعداد أداة رصد الكائنات

  • لإعداد أداة رصد الكائنات، أضِف الرمز التالي بعد التعليق ذي الصلة في علامة التبويب JS:
// Initialize the object detector.
async function initializeObjectDetector() {
  const visionFilesetResolver = await FilesetResolver.forVisionTasks(
    "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
  );
  objectDetector = await ObjectDetector.createFromOptions(visionFilesetResolver, {
    baseOptions: {
      modelAssetPath: "https://storage.googleapis.com/mediapipe-assets/dogs.tflite"
    },
    scoreThreshold: 0.3,
    runningMode: runningMode
  });
}
initializeObjectDetector();

تحدّد طريقة FilesetResolver.forVisionTasks() موقع البرنامج الثنائي WebAssembly (Wasm) الخاص بالمهمة.

تنشئ الطريقة ObjectDetector.createFromOptions() مثيلاً لأداة رصد الكائن. يجب توفير مسار للنموذج المستخدم في عملية الاكتشاف. في هذه الحالة، تتم استضافة نموذج "رصد الكلاب" على Cloud Storage.

تم ضبط السمة scoreThreshold على قيمة 0.3. وهذا يعني أنّ النموذج يعرض نتائج لأي كائن تم رصده بمستوى ثقة يبلغ 30% أو أعلى. يمكنك تعديل هذا الحدّ الأدنى بما يتناسب مع احتياجات تطبيقك.

يتم ضبط السمة runningMode عند إعداد الكائن ObjectDetector. يمكنك تغيير هذا الخيار وغيره من الخيارات حسب الحاجة لاحقًا.

5- تنفيذ التوقعات على الصور

  • لعرض عبارات بحث مقترحة على الصور، انتقِل إلى الدالة handleClick() ثم أضِف الرمز التالي إلى نص الدالة:
// Verify object detector is initialized and choose the correct running mode.
if (!objectDetector) {
    alert("Object Detector still loading. Please try again");
    return;
  }

  if (runningMode === "VIDEO") {
    runningMode = "IMAGE";
    await objectDetector.setOptions({ runningMode: runningMode });
  }

يحدّد هذا الرمز ما إذا كان قد تم إعداد أداة رصد الكائن أم لا، كما يضمن ضبط وضع التشغيل للصور.

رصد العناصر

  • لرصد العناصر في الصور، أضِف الرمز التالي إلى نص الدالة handleClick():
// Run object detection.
  const detections = objectDetector.detect(event.target);

يتضمن مقتطف الرمز التالي مثالاً على بيانات الإخراج من هذه المهمة:

ObjectDetectionResult:
 Detection #0:
  Box: (x: 355, y: 133, w: 190, h: 206)
  Categories:
   index       : 17
   score       : 0.73828
   class name  : aci
 Detection #1:
  Box: (x: 103, y: 15, w: 138, h: 369)
  Categories:
   index       : 17
   score       : 0.73047
   class name  : tikka

معالجة التوقعات وعرضها

  1. في نهاية نص الدالة handleClick()، استدعِ الدالة displayImageDetections():
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
  1. في نص الدالة displayImageDetections()، أضِف الرمز التالي لعرض نتائج اكتشاف الكائنات:
// Display object detection results.
  
  const ratio = resultElement.height / resultElement.naturalHeight;

  for (const detection of result.detections) {
    // Description text
    const p = document.createElement("p");
    p.setAttribute("class", "info");
    p.innerText =
      detection.categories[0].categoryName +
      " - with " +
      Math.round(parseFloat(detection.categories[0].score) * 100) +
      "% confidence.";
    // Positioned at the top-left of the bounding box.
    // Height is that of the text.
    // Width subtracts text padding in CSS so that it fits perfectly.
    p.style =
      "left: " +
      detection.boundingBox.originX * ratio +
      "px;" +
      "top: " +
      detection.boundingBox.originY * ratio +
      "px; " +
      "width: " +
      (detection.boundingBox.width * ratio - 10) +
      "px;";
    const highlighter = document.createElement("div");
    highlighter.setAttribute("class", "highlighter");
    highlighter.style =
      "left: " +
      detection.boundingBox.originX * ratio +
      "px;" +
      "top: " +
      detection.boundingBox.originY * ratio +
      "px;" +
      "width: " +
      detection.boundingBox.width * ratio +
      "px;" +
      "height: " +
      detection.boundingBox.height * ratio +
      "px;";

    resultElement.parentNode.appendChild(highlighter);
    resultElement.parentNode.appendChild(p);
  }

تعرض هذه الدالة مربّعات حدود فوق الأجسام التي يتم رصدها في الصور. وتعمل هذه الميزة على إزالة أي تمييز سابق، ثم إنشاء علامات <p> وعرضها لتمييز كل عنصر تم رصده.

اختبار التطبيق

عندما تجري تغييرات على الرمز في CodePen، يتم تحديث جزء المعاينة تلقائيًا عند الحفظ. إذا تم تفعيل الحفظ التلقائي، من المحتمل أن يكون قد تم تحديث تطبيقك مسبقًا، ولكن يُستحسن إعادة تحميل الصفحة مرة أخرى.

لاختبار التطبيق، اتّبِع الخطوات التالية:

  1. في جزء المعاينة، انقر على كل صورة لعرض التوقعات. يعرض المربّع المحيط اسم الكلب مع مستوى ثقة النموذج.
  2. إذا لم يكن هناك مربّع إحاطة، افتح "أدوات مطوري البرامج في Chrome" ثم تحقَّق من لوحة وحدة التحكّم بحثًا عن الأخطاء أو راجِع الخطوات السابقة لضمان ألا يفوتك أي شيء.

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

6- عرض التوقعات في فيديو مباشر على كاميرا الويب

رصد العناصر

  • لرصد الكائنات في فيديو مباشر على كاميرا الويب، انتقِل إلى الدالة predictWebcam()، ثم أضِف الرمز التالي إلى نص الدالة:
// Run video object detection.
  // If image mode is initialized, create a classifier with video runningMode.
  if (runningMode === "IMAGE") {
    runningMode = "VIDEO";
    await objectDetector.setOptions({ runningMode: runningMode });
  }
  let nowInMs = performance.now();

  // Detect objects with the detectForVideo() method.
  const result = await objectDetector.detectForVideo(video, nowInMs);

  displayVideoDetections(result.detections);

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

معالجة التوقعات وعرضها

  • لمعالجة نتائج الرصد وعرضها، انتقِل إلى الدالة displayVideoDetections()، ثم أضِف الرمز التالي إلى نص الدالة:
//  Display video object detection results.
  for (let child of children) {
    liveView.removeChild(child);
  }
  children.splice(0);

  // Iterate through predictions and draw them to the live view.
  for (const detection of result.detections) {
    const p = document.createElement("p");
    p.innerText =
      detection.categories[0].categoryName +
      " - with " +
      Math.round(parseFloat(detection.categories[0].score) * 100) +
      "% confidence.";
    p.style =
      "left: " +
      (video.offsetWidth -
        detection.boundingBox.width -
        detection.boundingBox.originX) +
      "px;" +
      "top: " +
      detection.boundingBox.originY +
      "px; " +
      "width: " +
      (detection.boundingBox.width - 10) +
      "px;";

    const highlighter = document.createElement("div");
    highlighter.setAttribute("class", "highlighter");
    highlighter.style =
      "left: " +
      (video.offsetWidth -
        detection.boundingBox.width -
        detection.boundingBox.originX) +
      "px;" +
      "top: " +
      detection.boundingBox.originY +
      "px;" +
      "width: " +
      (detection.boundingBox.width - 10) +
      "px;" +
      "height: " +
      detection.boundingBox.height +
      "px;";

    liveView.appendChild(highlighter);
    liveView.appendChild(p);

    // Store drawn objects in memory so that they're queued to delete at next call.
    children.push(highlighter);
    children.push(p);
  }
}

يزيل هذا الرمز أي تمييز سابق، ثم ينشئ علامات <p> ويعرضها لتمييز كل عنصر تم رصده.

اختبار التطبيق

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

لاختبار التطبيق، اتّبِع الخطوات التالية:

  1. نزِّل إحدى صور الكلب على هاتفك.
  2. في جزء المعاينة، انقر على تفعيل كاميرا الويب.
  3. إذا عرض المتصفح مربع حوار يطلب منك منح الإذن بالوصول إلى كاميرا الويب، فامنح الإذن بذلك.
  4. احمل صورة الكلب على هاتفك أمام كاميرا الويب. يعرض المربّع المحيط اسم الكلب ومستوى ثقة النموذج.
  5. إذا لم يكن هناك مربّع إحاطة، افتح "أدوات مطوري البرامج في Chrome" ثم تحقَّق من لوحة وحدة التحكّم بحثًا عن الأخطاء أو راجِع الخطوات السابقة لضمان ألا يفوتك أي شيء.

مربع إحاطة فوق صورة كلب مُمسك بكاميرا ويب مباشرة

7. تهانينا

تهانينا! لقد أنشأت تطبيق ويب يكتشف الكائنات في الصور. لمعرفة المزيد من المعلومات، يمكنك الاطّلاع على إصدار مكتمل من التطبيق على CodePen.

مزيد من المعلومات