זיהוי אובייקטים בתמונות כדי ליצור חיפוש חזותי של מוצרים באמצעות ערכת ML: Android

1. לפני שמתחילים

727608486a28395d.png

ראיתי את הדגמה של Google Lens, שבה אפשר להפנות את מצלמת הטלפון לאובייקט ולמצוא איפה אפשר לקנות אותו באינטרנט. אם אתם רוצים ללמוד איך להוסיף את אותה תכונה לאפליקציה שלכם, סדנת הקוד הזו היא בשבילכם. הוא חלק ממסלול למידה שמלמד איך להטמיע תכונה של חיפוש תמונות של מוצרים באפליקציה לנייד.

ב-codelab הזה תלמדו את השלב הראשון בתכנון תכונה לחיפוש תמונות של מוצרים: איך לזהות אובייקטים בתמונות ולאפשר למשתמש לבחור את האובייקטים שהוא רוצה לחפש. כדי ליצור את התכונה הזו, תשתמשו ב-ML Kit Object Detection and Tracking.

במסלול הלמידה מוסבר איך לבנות קצה עורפי לחיפוש מוצרים באמצעות Vision API Product Search, וגם איך לבצע את השלבים הנותרים.

מה תפַתחו

  • בקודלאב הזה תלמדו ליצור אפליקציה ל-Android באמצעות ML Kit. האפליקציה תשתמש ב-ML Kit Object Detection and Tracking API כדי לזהות אובייקטים בתמונה נתונה. לאחר מכן, המשתמש יבחר אובייקט שהוא רוצה לחפש במסד הנתונים של המוצרים שלנו.
  • בסוף, אמור להופיע משהו שדומה לתמונה שבצד שמאל.

מה תלמדו

  • איך משלבים את ML Kit SDK באפליקציה ל-Android
  • ML Kit Object Detection and Tracking API

מה צריך להכין

  • גרסה עדכנית של Android Studio (גרסה 4.1.2 ואילך)
  • Android Studio Emulator או מכשיר Android פיזי
  • הקוד לדוגמה
  • ידע בסיסי בפיתוח Android ב-Kotlin

סדנת הקוד הזו מתמקדת ב-ML Kit. מושגים אחרים וקטעי קוד לא נלמדים, והם פשוט מוצגים כדי שתוכלו להעתיק ולהדביק אותם.

2. להגדרה

הורדת הקוד

כדי להוריד את כל הקוד של סדנת הקוד הזו, לוחצים על הקישור הבא:

פותחים את קובץ ה-ZIP שהורדתם. הפקודה הזו תבצע ביטול אריזה של תיקיית root (odml-pathways-main) עם כל המשאבים הנדרשים. בסדנת הקוד הזו, תצטרכו רק את המקורות שבספריית המשנה product-search/codelab1/android.

ספריית המשנה object-detection במאגר mlkit-android מכילה שתי ספריות:

  • android_studio_folder.pngstarter – קוד לתחילת הדרך שעליו תבנו את הקוד ב-Codelab הזה.
  • android_studio_folder.pngfinal – קוד מלא של אפליקציית הדוגמה המוגמרת.

3. הוספת ML Kit Object Detection and Tracking API לפרויקט

ייבוא האפליקציה ל-Android Studio

מתחילים בייבוא האפליקציה starter ל-Android Studio.

עוברים אל Android Studio, בוחרים באפשרות Import Project (ייבוא פרויקט) (Gradle,‏ Eclipse ADT וכו') ובוחרים את התיקייה starter מקוד המקור שהורדתם מקודם.

7c0f27882a2698ac.png

הוספת יחסי התלות לזיהוי אובייקטים ומעקב אחריהם ב-ML Kit

יחסי התלות של ML Kit מאפשרים לכם לשלב את ML Kit ODT SDK באפליקציה.

עוברים לקובץ app/build.gradle של הפרויקט ומוודאים שהתלות כבר קיימת:

build.gradle

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

סנכרון הפרויקט עם קובצי Gradle

כדי לוודא שכל יחסי התלות זמינים לאפליקציה, צריך לסנכרן את הפרויקט עם קובצי Gradle בשלב הזה.

בוחרים באפשרות סנכרון הפרויקט עם קובצי Gradle ( b451ab2d04d835f9.png) בסרגל הכלים של Android Studio.

(אם הלחצן הזה מושבת, חשוב לייבא רק את starter/app/build.gradle ולא את המאגר כולו).

4. הפעלת האפליקציה למתחילים

אחרי שמייבאים את הפרויקט ל-Android Studio ומוסיפים את יחסי התלות לזיהוי אובייקטים ולמעקב אחר אובייקטים ב-ML Kit, אפשר להריץ את האפליקציה בפעם הראשונה.

מחברים את מכשיר Android למארח באמצעות USB או מפעילים את הסימולטור של Android Studio ולוחצים על הפעלה ( execute.png) בסרגל הכלים של Android Studio.

הפעלה של האפליקציה וסקירתה

האפליקציה אמורה להיפתח במכשיר Android. הוא מכיל קוד סטנדרטי שמאפשר לצלם תמונה או לבחור תמונה מוגדרת מראש, ולהעביר אותה לצינור עיבוד נתונים לזיהוי ולמעקב אחר אובייקטים שתבנו ב-codelab הזה. כדאי לבדוק את האפליקציה קצת לפני שכותבים קוד:

קודם כול, יש לחצן ( c6d965d639c3646.png) בתחתית המסך שמאפשר

  • מפעילים את אפליקציית המצלמה המשולבת במכשיר או במהדמ.
  • מצלמים תמונה באפליקציית המצלמה
  • לקבל את התמונה שצולמה באפליקציית ההתחלה
  • הצגת התמונה

כדאי לנסות את הלחצן צילום תמונה. פועלים לפי ההנחיות לצילום תמונה, מאשרים את התמונה ומעיינים בה באפליקציית ההתחלה.

שנית, יש 3 תמונות מוגדרות מראש שאפשר לבחור מתוכן. אם אתם משתמשים במהדר של Android, תוכלו להשתמש בתמונות האלה מאוחר יותר כדי לבדוק את קוד זיהוי האובייקטים.

  1. בוחרים תמונה מתוך 3 התמונות הקבועות מראש.
  2. בודקים שהתמונה מופיעה בתצוגה המוגדלת.

1290481786af21b9.png

5. הוספת זיהוי אובייקטים במכשיר

בשלב הזה תוסיפו לאפליקציית ההתחלה את הפונקציונליות לזיהוי אובייקטים בתמונות. כפי שראיתם בשלב הקודם, אפליקציית ה-starter מכילה קוד לדוגמה לצילום תמונות באמצעות אפליקציית המצלמה במכשיר. אם אתם מריצים את הקודלה במהדמנת Android, יש באפליקציה גם 3 תמונות מוגדרות מראש שתוכלו לנסות לזהות בהן אובייקטים.

כשבוחרים תמונה, מתוך התמונות המוגדרות מראש או על ידי צילום תמונה באפליקציית המצלמה, קוד ה-boilerplate מפענח את התמונה הזו למכונה של Bitmap, מציג אותה במסך וקורא ל-method‏ runObjectDetection עם התמונה.

בשלב הזה, תוסיפו קוד לשיטה runObjectDetection כדי לבצע זיהוי אובייקטים.

הגדרה והפעלה של זיהוי אובייקטים במכשיר בתמונה

יש רק 3 שלבים פשוטים עם 3 ממשקי API להגדרת ML Kit ODT

  • הכנת תמונה: InputImage
  • יוצרים אובייקט של גלאי: ObjectDetection.getClient(options)
  • מחברים את שני האובייקטים שלמעלה: process(image)

כדי לעשות זאת, צריך להשתמש בפונקציה **runObjectDetection(bitmap: Bitmap)**בקובץ MainActivity.kt.

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

כרגע הפונקציה ריקה. כדי לשלב את ML Kit ODT, ממשיכים לשלבים הבאים. לאורך הדרך, תופיע ב-Android Studio בקשה להוסיף את ייבוא הנתונים הנדרש.

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

שלב 1: יוצרים את InputImage

ב-ML Kit יש ממשק API פשוט ליצירת InputImage מ-Bitmap. לאחר מכן תוכלו להזין InputImage לממשקי ה-API של ML Kit.

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

מוסיפים את הקוד שלמעלה לחלק העליון של runObjectDetection(bitmap:Bitmap).

שלב 2: יוצרים מכשיר גלאי

ML Kit פועל לפי תבנית העיצוב של ה-Builder. מעבירים את ההגדרות ל-builder, ואז מקבלים ממנו גלאי. יש 3 אפשרויות להגדרה (האפשרות שמודגשת בכתב מודגש משמשת ב-codelab):

  • מצב הגלאי (תמונה אחת או שידור)
  • מצב זיהוי (זיהוי אובייקט יחיד או מרובים)
  • מצב הסיווג (מופעל או מושבת)

סדנת הקוד הזו מיועדת לזיהוי ולסיווג של מספר אובייקטים בתמונה אחת. נתחיל:

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

שלב 3: מעבירים תמונות לגלאי

זיהוי אובייקטים וסיווג שלהם מתבצע בעיבוד אסינכרוני:

  • שולחים תמונה למזהה (דרך process())
  • הגלאי עובד קשה מאוד על זה
  • הגלאי מדווח לכם על התוצאה באמצעות קריאה חוזרת (callback).

הקוד הבא עושה בדיוק את זה (מעתיקים ומצרפים אותו לקוד הקיים בתוך 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())
   }

בסיום, הגלאי מודיע לכם על כך באמצעות

  1. המספר הכולל של האובייקטים שזוהו
  2. כל אובייקט שזוהה מתואר באמצעות
  • trackingId: מספר שלם שמשמש למעקב אחריו בין המסגרות (לא נעשה בו שימוש בקודלאב הזה)
  • boundingBox: התיבה התוחמת של האובייקט
  • labels: רשימת תוויות של האובייקט שזוהה (רק כשהסיווג מופעל)
  • index (אחזור המדד של התווית הזו)
  • text (קבלת הטקסט של התווית הזו, כולל 'מוצרי אופנה', 'מזון', 'מוצרי בית', 'מקום', 'צמח')
  • confidence (מספר ממשי (float) בין 0.0 ל-1.0, כאשר הערך 1.0 מייצג 100%)

כנראה שמתם לב שהקוד מדפיס את התוצאות שזוהו ב-Logcat באמצעות 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 Studio. נסו לבחור תמונה מוגדרת מראש או לצלם תמונה, ואז לבדוק את חלון 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: Fashion good
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 אובייקטים מהסוגים הבאים:

  • Fashion good ו-Home good.
  • לא מוחזרת קטגוריה עבור האפשרות השנייה כי זוהי כיתה לא ידועה.
  • לא trackingId (כי זהו מצב זיהוי של תמונה אחת)
  • המיקום בתוך המלבן boundingBox (למשל, (481, 2021) – (2426, 3376))
  • הגלאי די בטוח שהתמונה הראשונה היא פריט אופנה (90%) (מדובר בשמלה)

טכנית, זה כל מה שצריך כדי להפעיל את זיהוי האובייקטים ב-ML Kit – כל מה שדרוש לכם כבר קיים! מזל טוב!

כן, מבחינת ממשק המשתמש, עדיין נמצאים בשלב שבו התחלתם, אבל אפשר להשתמש בתוצאות שזוהו בממשק המשתמש, למשל לצייר את תיבת הגבול כדי ליצור חוויה טובה יותר. השלב הבא הוא להציג גרפית את התוצאות שזוהו.

6. עיבוד פוסט-פרודקשן של תוצאות הזיהוי

בשלבים הקודמים הדפסתם את התוצאה שזוהתה ב-logcat: פשוט ומהיר.

בקטע הזה תשתמשו בתוצאה בתמונה:

  • ציור התיבה התוחמת (bounding box) בתמונה
  • ציור שם הקטגוריה ודרגת האמון בתוך תיבת הסימון

הסבר על הכלים להצגה חזותית

ב-codelab יש קוד לדוגמה שיעזור לכם להמחיש את תוצאת הזיהוי. אתם יכולים להשתמש בכלים האלה כדי לפשט את הקוד של התצוגה החזותית:

  • class ImageClickableView זוהי סוג תצוגה של תמונה שמספק כמה פונקציות שימושיות להצגה חזותית ולאינטראקציה עם תוצאת הזיהוי.
  • fun drawDetectionResults(results: List<DetectedObject>) בשיטה הזו מצוירים עיגולים לבנים במרכז של כל אובייקט שזוהה.
  • fun setOnObjectClickListener(listener: ((objectImage: Bitmap) -> Unit)) זוהי קריאה חוזרת כדי לקבל את התמונה החתוכה שמכילה רק את האובייקט שהמשתמש הקיש עליו. בשלב מאוחר יותר ב-Codelab, תשלחו את התמונה החתוכה הזו לקצה העורפי של חיפוש התמונות כדי לקבל תוצאה דומה מבחינה ויזואלית. עדיין לא נשתמש בשיטה הזו ב-codelab הזה.

הצגת תוצאת הזיהוי של ML Kit

משתמשים בכלי הוויזואליזציה כדי להציג את תוצאת זיהוי האובייקטים של ML Kit מעל לתמונה שהוזנה.

עוברים למיקום שבו קוראים ל-debugPrint() ומוסיפים את קטע הקוד הבא מתחתיו:

runOnUiThread {
    viewBinding.ivPreview.drawDetectionResults(it)
}

הפעלה

עכשיו לוחצים על הפעלה ( execute.png) בסרגל הכלים של Android Studio.

אחרי שהאפליקציה נטענת, לוחצים על הלחצן עם סמל המצלמה, מכוונים את המצלמה לאובייקט, מצלמים תמונה, מאשרים את התמונה (באפליקציית המצלמה) או מקישים בקלות על תמונות מוגדרות מראש. תראו את תוצאת הזיהוי. לחצו שוב על הלחצן או בחרו תמונה אחרת כדי לחזור על הפעולה כמה פעמים וליהנות מ-ML Kit ODT העדכני ביותר.

5027148750dc0748.png

7. מעולה!

השתמשתם ב-ML Kit כדי להוסיף לאפליקציה יכולות של זיהוי אובייקטים:

  • 3 שלבים עם 3 ממשקי API
  • יצירת תמונת קלט
  • יצירת גלאי
  • שליחת תמונה לזיהוי

זה כל מה שצריך כדי להפעיל את השירות.

מה עסקנו בו

  • איך מוסיפים את התכונות 'זיהוי אובייקטים' ו'מעקב אחר אובייקטים' של ML Kit לאפליקציה ל-Android
  • איך משתמשים ב-ML Kit לזיהוי אובייקטים במכשיר ולמעקב אחריהם כדי לזהות אובייקטים בתמונות

השלבים הבאים

  • כדאי לנסות את codelab הזה, שבו מוסבר איך לשלוח את האובייקט שזוהה לקצה העורפי של חיפוש מוצרים ולהציג את תוצאות החיפוש.
  • אפשר להרחיב את הבדיקה באמצעות ML Kit ODT עם תמונות וסרטונים חיים נוספים כדי לבדוק את הדיוק והביצועים של הזיהוי והסיווג
  • מומלץ לעיין במסלול הלמידה המשך למידה בנושא זיהוי אובייקטים כדי ללמוד איך לאמן מודל מותאם אישית.
  • כדאי לקרוא את ההמלצות של Material Design לזיהוי אובייקטים ב-מצלמה בשידור חי וב-תמונה סטטית
  • שימוש ב-ML Kit ODT באפליקציה ל-Android

מידע נוסף