رصد العناصر في الصور باستخدام حزمة تعلُّم الآلة: Android

1. قبل البدء

‫حزمة تعلّم الآلة (ML Kit) هي حزمة تطوير برامج (SDK) للأجهزة الجوّالة تتيح الاستفادة من خبرة Google في مجال تعلُّم الآلة على الجهاز فقط في تطبيقات Android وiOS. يمكنك استخدام واجهات برمجة التطبيقات Vision وNatural Language القوية والسهلة الاستخدام لحل التحديات الشائعة في تطبيقاتك أو إنشاء تجارب مستخدم جديدة تمامًا. وكلّها تستند إلى أفضل نماذج تعلُّم الآلة في المجال من Google، وهي متاحة لك بدون أي تكلفة.

تعمل جميع واجهات برمجة التطبيقات في ML Kit على الجهاز فقط، ما يتيح حالات استخدام في الوقت الفعلي حيث تريد معالجة بث كاميرا مباشر، على سبيل المثال. ويعني هذا أيضًا أنّ الوظيفة متاحة بلا إنترنت.

سيرشدك هذا الدرس التطبيقي حول الترميز خلال خطوات بسيطة لإضافة ميزة "رصد العناصر وتتبُّعها" (ODT) لصورة معيّنة إلى تطبيق Android الحالي. يُرجى العِلم أنّ هذا الدرس التطبيقي حول الترميز يتضمّن بعض الاختصارات لتسليط الضوء على استخدام ميزة "رصد العناصر وتتبُّعها" في حزمة تعلّم الآلة.

ما ستنشئه

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

ما ستتعلمه

  • كيفية دمج حزمة تعلّم الآلة في تطبيق Android
  • ‫واجهة برمجة تطبيقات اكتشاف وتتبّع العناصر في حزمة تعلّم الآلة

المتطلبات

  • إصدار حديث من "استوديو Android" (الإصدار 4.1.2 أو إصدار أحدث)
  • محاكي استوديو Android أو جهاز Android فعلي
  • الرمز النموذجي
  • معرفة أساسية بتطوير تطبيقات Android باستخدام لغة Kotlin

يركّز هذا الدرس التطبيقي حول الترميز على حزمة تعلّم الآلة. يتم تجاهل المفاهيم ومجموعات الرموز غير ذات الصلة، ويتم توفيرها لك لنسخها ولصقها ببساطة.

2. طريقة الإعداد

تنزيل الرمز

انقر على الرابط التالي لتنزيل كل الرموز البرمجية لهذا الدرس التطبيقي حول الترميز:

فكّ ضغط ملف ZIP الذي تم تنزيله. سيؤدي ذلك إلى فك حزمة مجلد رئيسي (mlkit-android-main) يحتوي على جميع الموارد التي ستحتاج إليها. في هذا الدرس التطبيقي، لن تحتاج إلا إلى المصادر الموجودة في الدليل الفرعي object-detection.

يحتوي الدليل الفرعي لتحديد العناصر في مستودع mlkit-android على دليلَين:

  • android_studio_folder.pngالرمز الأوّلي: الرمز الأوّلي الذي ستستند إليه في هذا الدرس التطبيقي حول الترميز.
  • android_studio_folder.pngfinal: رمز مكتمل لنموذج التطبيق النهائي.

3- إضافة واجهة برمجة التطبيقات "رصد الأجسام وتتبُّعها" في حزمة تعلّم الآلة إلى المشروع

استيراد التطبيق إلى "استوديو Android"

لنبدأ باستيراد تطبيق البداية إلى استوديو Android.

افتح "استوديو Android"، وانقر على استيراد مشروع (Gradle وEclipse ADT وما إلى ذلك)، ثم اختَر مجلد starter من الرمز المصدري الذي نزّلته سابقًا.

7c0f27882a2698ac.png

إضافة التبعيات الخاصة بميزة "رصد العناصر وتتبُّعها" في ML Kit

تتيح لك مراجع حزمة تعلّم الآلة دمج حزمة تطوير البرامج (SDK) الخاصة بميزة "التعرّف على العناصر" في تطبيقك. أضِف الأسطر التالية إلى نهاية ملف app/build.gradle في مشروعك:

build.gradle

dependencies {
  // ...
  implementation 'com.google.mlkit:object-detection:16.2.4'
}

مزامنة مشروعك مع ملفات Gradle

للتأكّد من توفّر جميع التبعيات لتطبيقك، عليك مزامنة مشروعك مع ملفات Gradle في هذه المرحلة.

انقر على مزامنة المشروع مع ملفات Gradle ( b451ab2d04d835f9.png) من شريط أدوات "استوديو Android".

(إذا كان هذا الزر غير مفعّل، احرص على استيراد starter/app/build.gradle فقط، وليس المستودع بأكمله.)

4. تشغيل التطبيق النموذجي

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

وصِّل جهاز Android بجهازك المضيف عبر USB أو ابدأ محاكي "استوديو Android"، ثم انقر على تشغيل ( execute.png) في شريط أدوات "استوديو Android".

تشغيل التطبيق واستكشافه

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

أولاً، هناك زر ( c6d965d639c3646.png) في أسفل الشاشة لتنفيذ ما يلي:

  • افتح تطبيق الكاميرا المدمج في جهازك أو المحاكي.
  • التقاط صورة داخل تطبيق الكاميرا
  • تلقّي الصورة التي تم التقاطها في التطبيق الأولي
  • عرض الصورة

جرِّب الزر التقاط صورة واتّبِع التعليمات لالتقاط صورة، ثم اقبل الصورة ولاحظ عرضها داخل تطبيق البداية.

كرِّر هذا الإجراء بضع مرات لمعرفة طريقة عمله:

9ec541980dbe2d31.png 8312dde41425ba4b.png fa8492bfc1914ff0.png

ثانيًا، هناك 3 صور مُعدّة مسبقًا يمكنك الاختيار من بينها. يمكنك استخدام هذه الصور لاحقًا لاختبار رمز رصد العناصر إذا كنت تستخدم محاكي Android.

اختَر صورة من بين الصور الثلاث المُعدّة مسبقًا. تأكَّد من ظهور الصورة في العرض الأكبر:

1dd41b3ec978f1d9.png

5- إضافة ميزة "رصد الأجسام على الجهاز فقط"

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

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

في هذه الخطوة، ستضيف رمزًا إلى طريقة runObjectDetection لتنفيذ عملية رصد العناصر.

إعداد ميزة "رصد العناصر على الجهاز فقط" وتشغيلها على صورة

ما عليك سوى اتّباع 3 خطوات بسيطة باستخدام 3 واجهات برمجة تطبيقات لإعداد ميزة "الرصد والتتبّع" في حزمة تعلّم الآلة:

  • تحضير صورة: InputImage
  • أنشئ عنصر أداة رصد: ObjectDetection.getClient(options)
  • اربط بين العنصرَين أعلاه: process(image)

يمكنك تحقيق ذلك داخل الدالة runObjectDetection(bitmap: Bitmap) في الملف MainActivity.kt.

/**
 * ML Kit Object Detection Function
 */
private fun runObjectDetection(bitmap: Bitmap) {
}

في الوقت الحالي، الدالة فارغة. انتقِل إلى الخطوات التالية لتنفيذ ميزة "التعرّف على العناصر" في حزمة تعلّم الآلة. أثناء ذلك، سيطلب منك "استوديو Android" إضافة عمليات الاستيراد اللازمة:

  • com.google.mlkit.vision.common.InputImage
  • com.google.mlkit.vision.objects.ObjectDetection
  • com.google.mlkit.vision.objects.defaults.ObjectDetectorOptions

الخطوة 1: إنشاء InputImage

توفّر حزمة تعلُّم الآلة واجهة برمجة تطبيقات بسيطة لإنشاء InputImage من Bitmap. بعد ذلك، يمكنك إدخال InputImage في واجهات برمجة التطبيقات الخاصة بحزمة تعلُّم الآلة.

// Step 1: create ML Kit's InputImage object
val image = InputImage.fromBitmap(bitmap, 0)

أضِف الرمز أعلاه إلى أعلى runObjectDetection(bitmap:Bitmap).

الخطوة 2: إنشاء مثيل لأداة الرصد

تتّبع حزمة تعلُّم الآلة نمط تصميم أداة الإنشاء. ستمرِّر إعدادات الضبط إلى أداة الإنشاء، ثم ستحصل على أداة رصد منها. تتوفّر 3 خيارات للإعداد (الخيارات بالخط العريض مستخدَمة في هذا الدرس العملي):

  • وضع أداة الرصد (صورة واحدة أو بث)
  • وضع الرصد (رصد جسم واحد أو متعدّد)
  • وضع التصنيف (مفعّل أو غير مفعّل)

هذا الدرس التعليمي المبرمَج مخصّص لرصد وتصنيف عناصر متعددة في صورة واحدة. أضِف ذلك الآن:

// Step 2: acquire detector object
val options = ObjectDetectorOptions.Builder()
   .setDetectorMode(ObjectDetectorOptions.SINGLE_IMAGE_MODE)
   .enableMultipleObjects()
   .enableClassification()
   .build()
val objectDetector = ObjectDetection.getClient(options)

الخطوة 3: إدخال الصور إلى أداة الكشف

رصد الأجسام وتصنيفها هو معالجة غير متزامنة:

  • ترسل صورة إلى أداة الكشف (عبر process()).
  • ويعمل "الكاشف" بجدّ للعثور على هذه المعلومات.
  • يرسل "أداة الكشف" النتيجة إليك من خلال دالة رد الاتصال.

ينفّذ الرمز التالي ذلك بالضبط (نسخه وإلحاقه بالرمز الحالي داخل fun runObjectDetection(bitmap:Bitmap)):

// Step 3: feed given image to detector and setup callback
objectDetector.process(image)
   .addOnSuccessListener {
       // Task completed successfully
        debugPrint(it)
   }
   .addOnFailureListener {
       // Task failed with an exception
       Log.e(TAG, it.message.toString())
   }

عند اكتمال عملية الكشف، يرسل إليك تطبيق "الكاشف" إشعارًا يتضمّن ما يلي:

  • إجمالي عدد العناصر التي تم رصدها. يتم وصف كل كائن تم رصده باستخدام ما يلي:
  • trackingId: عدد صحيح تستخدمه لتتبُّع الإطار المتقاطع (لا يُستخدَم في هذا الدرس العملي).
  • boundingBox: المربّع المحيط بالعنصر
  • labels: قائمة بالتصنيفات الخاصة بالعنصر الذي تم رصده (فقط عند تفعيل التصنيف):
  • index (الحصول على فهرس هذا التصنيف)
  • text (الحصول على نص هذا التصنيف، بما في ذلك "السلع المتعلقة بالموضة" و"الطعام" و"السلع المنزلية" و"المكان" و"النبات")
  • confidence ( عدد عشري يتراوح بين 0.0 و1.0، حيث يشير 1.0 إلى %100)

من المحتمل أنّك لاحظت أنّ الرمز البرمجي ينفّذ عملية معالجة من نوع printf للنتيجة التي تم رصدها باستخدام debugPrint().

أضِفها إلى الصف MainActivity:

private fun debugPrint(detectedObjects: List<DetectedObject>) {
   detectedObjects.forEachIndexed { index, detectedObject ->
       val box = detectedObject.boundingBox

       Log.d(TAG, "Detected object: $index")
       Log.d(TAG, " trackingId: ${detectedObject.trackingId}")
       Log.d(TAG, " boundingBox: (${box.left}, ${box.top}) - (${box.right},${box.bottom})")
       detectedObject.labels.forEach {
           Log.d(TAG, " categories: ${it.text}")
           Log.d(TAG, " confidence: ${it.confidence}")
       }
   }
}

أنت الآن جاهز لقبول الصور بغرض رصدها.

لننفّذ الآن الدرس العملي من خلال النقر على تشغيل ( execute.png) في شريط أدوات "استوديو Android". جرِّب اختيار صورة مُعدّة مسبقًا أو التقاط صورة، ثم اطّلِع على نافذة logcat( 16bd6ea224cf8cf1.png) داخل بيئة التطوير المتكاملة.

من المفترض أن يظهر لك ما يلي:

D/MLKit Object Detection: Detected object: 0
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (481, 2021) - (2426,3376)
D/MLKit Object Detection:  categories: Food
D/MLKit Object Detection:  confidence: 0.90234375
D/MLKit Object Detection: Detected object: 1
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (2639, 2633) - (3058,3577)
D/MLKit Object Detection: Detected object: 2
D/MLKit Object Detection:  trackingId: null
D/MLKit Object Detection:  boundingBox: (3, 1816) - (615,2597)
D/MLKit Object Detection:  categories: Home good
D/MLKit Object Detection:  confidence: 0.75390625

...ما يعني أنّ أداة الرصد رصدت 3 عناصر:

  • الفئتان هما الطعام والسلع المنزلية.
  • لم يتم عرض أي فئة للنتيجة الثانية لأنّها فئة غير معروفة.
  • لا يوجد trackingId (لأنّ هذا هو وضع رصد الصور الفردية).
  • الموضع داخل المستطيل boundingBox (مثلاً (481, 2021) – (2426, 3376))
  • يُظهر جهاز الرصد ثقة كبيرة في أنّ الصورة الأولى هي طعام (بنسبة ثقة تبلغ% 90، وهو سلطة).

هذا كل ما تحتاج إليه من الناحية الفنية لتفعيل ميزة "رصد العناصر" في حزمة تعلّم الآلة، إذ إنّ كل ما ذكرناه متوفّر لك في الوقت الحالي. تهانينا!

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

6. المعالجة اللاحقة لنتائج الرصد

في الخطوات السابقة، يمكنك طباعة النتيجة التي تم رصدها في logcat: عملية بسيطة وسريعة.

في هذا القسم، ستستفيد من النتيجة في الصورة:

  • رسم مربّع الحدود على الصورة
  • رسم اسم الفئة ومستوى الثقة داخل المربّع المحيط

التعرّف على أدوات التصوّر

يتضمّن الدرس التطبيقي حول الترميز بعض رمز النص النموذجي لمساعدتك في عرض نتيجة الاكتشاف بشكل مرئي. استخدِم هذه الأدوات المساعدة لتبسيط رمز التصور:

  • data class BoxWithText(val box: Rect, val text: String) هذا هو فئة البيانات لتخزين نتيجة رصد العناصر من أجل عرضها. box هو المربّع المحيط الذي يظهر فيه العنصر، وtext هو سلسلة نتيجة الرصد التي سيتم عرضها مع المربّع المحيط بالعنصر.
  • fun drawDetectionResult(bitmap: Bitmap, detectionResults: List<BoxWithText>): Bitmap يرسم هذا الإجراء نتائج رصد العناصر في detectionResults على bitmap المُدخَل ويعرض النسخة المعدَّلة منه.

في ما يلي مثال على ناتج طريقة الأداة المساعدة drawDetectionResult:

58c6f1d4ddb00dfa.png

عرض نتيجة الرصد في حزمة تعلّم الآلة

استخدِم أدوات العرض المرئي لرسم نتيجة رصد العناصر في حزمة تعلّم الآلة فوق الصورة المدخلة.

انتقِل إلى المكان الذي تستدعي فيه debugPrint() وأضِف مقتطف الرمز التالي أدناه:

// Parse ML Kit's DetectedObject and create corresponding visualization data
val detectedObjects = it.map { obj ->
    var text = "Unknown"

    // We will show the top confident detection result if it exist
    if (obj.labels.isNotEmpty()) {
        val firstLabel = obj.labels.first()
        text = "${firstLabel.text}, ${firstLabel.confidence.times(100).toInt()}%"
    }
    BoxWithText(obj.boundingBox, text)
}

// Draw the detection result on the input bitmap
val visualizedResult = drawDetectionResult(bitmap, detectedObjects)

// Show the detection result on the app screen
runOnUiThread {
    inputImageView.setImageBitmap(visualizedResult)
}
  • تبدأ بتحليل DetectedObject في ML Kit وإنشاء قائمة بعناصر BoxWithText لعرض نتيجة التصوّر.
  • بعد ذلك، ارسم نتيجة الرصد فوق صورة الإدخال باستخدام طريقة الأداة المساعدة drawDetectionResult، واعرضها على الشاشة.

تشغيلها

انقر الآن على تشغيل ( execute.png) في شريط أدوات "استوديو Android".

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

a03109cb30d5014d.png

7. تهانينا!

استخدام حزمة تعلّم الآلة لإضافة إمكانات "رصد العناصر" إلى تطبيقك:

  • 3 خطوات باستخدام 3 واجهات برمجة تطبيقات
  • إنشاء صورة إدخال
  • إنشاء أداة رصد
  • إرسال الصورة إلى أداة الرصد

هذا كل ما عليك فعله لتشغيلها.

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

المواضيع التي تناولناها

  • كيفية إضافة ميزة "رصد العناصر وتتبُّعها" في حزمة تعلّم الآلة إلى تطبيق Android
  • كيفية استخدام ميزة رصد العناصر وتتبُّعها على الجهاز فقط في حزمة تعلّم الآلة لرصد العناصر في الصور

الخطوات التالية

  • استكشاف المزيد باستخدام ميزة "رصد العناصر وتصنيفها" في حزمة تعلّم الآلة مع المزيد من الصور والفيديوهات المباشرة لتجربة دقة الرصد والتصنيف والأداء
  • يمكنك الاطّلاع على مسار التعلّم الخاص بميزة "رصد الأجسام" في "تعلُّم الآلة على الجهاز" لمعرفة كيفية تدريب نموذج مخصّص.
  • تطبيق ميزة "التعرّف على العناصر" من حزمة تعلّم الآلة في تطبيق Android الخاص بك

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