Google I/O הוא עטיפה! התעדכן בהפעלות של TensorFlow. צפה בהפעלות

התחלה מהירה עבור אנדרואיד

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

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

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

דוגמה להגדרה והרצה

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

  • Android Studio 4.2.2 ומעלה
  • Android SDK גרסה 31 ומעלה

קבל את הקוד לדוגמה

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

כדי לשכפל ולהגדיר את הקוד לדוגמה:

  1. שכפל את מאגר git
    git clone https://github.com/android/camera-samples.git
    
  2. הגדר את מופע ה-git שלך לשימוש בקופה דלילה, כך שיש לך רק את הקבצים עבור האפליקציה לדוגמה לזיהוי אובייקטים:

    cd camera-samples
    git sparse-checkout init --cone
    git sparse-checkout set CameraXAdvanced
    

ייבוא ​​והפעל את הפרויקט

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

כדי לייבא ולבנות את פרויקט הקוד לדוגמה:

  1. הפעל את Android Studio .
  2. מדף הפתיחה של Android Studio, בחר ייבוא ​​פרויקט , או בחר קובץ > חדש > ייבוא ​​פרויקט .
  3. נווט אל ספריית הקוד לדוגמה המכילה את הקובץ build.gradle ( .../android/camera-samples/CameraXAdvanced/build.gradle ) ובחר את הספרייה הזו.

אם תבחר את הספרייה הנכונה, Android Studio יוצר פרויקט חדש ובונה אותו. תהליך זה עשוי להימשך מספר דקות, בהתאם למהירות המחשב שלך ואם השתמשת ב-Android Studio עבור פרויקטים אחרים. כאשר הבנייה מסתיימת, ה-Android Studio מציג הודעת BUILD SUCCESSFUL בחלונית סטטוס Build Output .

אופציונלי: כדי לתקן שגיאות בנייה על ידי עדכון גרסת הפלאגין של Android:

  1. פתח את הקובץ build.gradle בספריית הפרויקט.
  2. שנה את גרסת כלי אנדרואיד באופן הבא:

    // from:
    classpath 'com.android.tools.build:gradle:4.2.2'
    // to:
    classpath 'com.android.tools.build:gradle:4.1.2'
    
  3. סנכרן את הפרויקט על ידי בחירה: קובץ > סנכרן פרויקט עם קבצי Gradle .

להפעלת הפרויקט:

  1. מ-Android Studio, הפעל את הפרויקט על ידי בחירה בהפעלה > הפעלה... ו- CameraActivity .
  2. בחר מכשיר אנדרואיד מחובר עם מצלמה כדי לבדוק את האפליקציה.

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

הוסף תלות בפרויקט

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

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

  • הספרייה הראשית של TensorFlow Lite - מספקת את מחלקות קלט הנתונים הנדרשות, ביצוע של מודל למידת מכונה ופלט תוצאות מעיבוד המודל.
  • ספריית תמיכה של TensorFlow Lite - ספרייה זו מספקת כיתת עוזר לתרגום תמונות מהמצלמה לאובייקט נתונים של TensorImage שניתן לעבד על ידי מודל למידת המכונה.
  • ספריית GPU TensorFlow Lite - ספרייה זו מספקת תמיכה להאצת ביצוע מודלים באמצעות מעבדי GPU במכשיר, אם הם זמינים.

ההוראות הבאות מסבירות כיצד להוסיף את התלות הנדרשת בפרויקט ובמודול לפרויקט אפליקציית Android משלך.

כדי להוסיף תלות במודול:

  1. במודול המשתמש ב-TensorFlow Lite, עדכן את קובץ ה- build.gradle של המודול כך שיכלול את התלות הבאה. בקוד לדוגמה, קובץ זה נמצא כאן: .../android/camera-samples/CameraXAdvanced/tflite/build.gradle ( הפניה לקוד )

    ...
    dependencies {
    ...
        // Tensorflow lite dependencies
        implementation 'org.tensorflow:tensorflow-lite:2.8.0'
        implementation 'org.tensorflow:tensorflow-lite-gpu:2.8.0'
        implementation 'org.tensorflow:tensorflow-lite-support:2.8.0'
    ...
    }
    
  2. ב-Android Studio, סנכרן את התלות בפרויקט על ידי בחירה: קובץ > סנכרן פרויקט עם קבצי Gradle .

אתחול מתורגמן מודל ML

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

מודל TensorFlow Lite כולל קובץ .tflite המכיל את קוד הדגם ולעיתים קרובות כולל קובץ תוויות המכיל את שמות המחלקות החזויות על ידי המודל. במקרה של זיהוי עצמים, מחלקות הן חפצים כגון אדם, כלב, חתול או מכונית. מודלים מאוחסנים בדרך כלל בספריית src/main/assets של המודול הראשי, כמו בדוגמה של הקוד:

  • CameraXAdvanced/tflite/src/main/assets/coco_ssd_mobilenet_v1_1.0_quant.tflite
  • CameraXAdvanced/tflite/src/main/assets/coco_ssd_mobilenet_v1_1.0_labels.txt

מטעמי נוחות וקריאות קוד, הדוגמה מצהירה על אובייקט נלווה המגדיר את ההגדרות עבור המודל.

כדי לאתחל את הדגם באפליקציה שלך:

  1. צור אובייקט נלווה כדי להגדיר את ההגדרות עבור המודל: ( הפניה לקוד )

    companion object {
       private val TAG = CameraActivity::class.java.simpleName
    
       private const val ACCURACY_THRESHOLD = 0.5f
       private const val MODEL_PATH = "coco_ssd_mobilenet_v1_1.0_quant.tflite"
       private const val LABELS_PATH = "coco_ssd_mobilenet_v1_1.0_labels.txt"
    }
    
  2. השתמש בהגדרות מאובייקט זה כדי לבנות אובייקט TensorFlow Lite Interpreter המכיל את המודל: ( הפניה לקוד )

    private val tflite by lazy {
       Interpreter(
           FileUtil.loadMappedFile(this, MODEL_PATH),
           Interpreter.Options().addDelegate(nnApiDelegate))
    }
    

הגדר את מאיץ החומרה

בעת אתחול מודל TensorFlow Lite ביישום שלך, אתה יכול להשתמש בתכונות האצת חומרה כדי להאיץ את חישובי החיזוי של המודל. דוגמת הקוד שלמעלה משתמשת ב-NNAPI Delegate כדי לטפל בהאצת החומרה של ביצוע המודל:

Interpreter.Options().addDelegate(nnApiDelegate)

נציגי TensorFlow Lite הם מודולי תוכנה שמאיצים את הביצוע של מודלים של למידת מכונה באמצעות חומרת עיבוד מיוחדת במכשיר נייד, כגון GPUs, TPUs או DSPs. מומלץ להשתמש בנציגים להפעלת דגמי TensorFlow Lite, אך לא חובה.

למידע נוסף על שימוש בנציגים עם TensorFlow Lite, ראה TensorFlow Lite Delegates .

ספק נתונים למודל

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

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

  • השתמש באובייקט המתורגמן המאותחל כדי לקבוע את צורת הטנזור המשמש את המודל שלך, כפי שמוצג בקטע הקוד שלהלן: ( הפניה לקוד )

    private val tfInputSize by lazy {
       val inputIndex = 0
       val inputShape = tflite.getInputTensor(inputIndex).shape()
       Size(inputShape[2], inputShape[1]) // Order of axis is: {1, height, width, 3}
    }
    

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

לפני שתוכל לספק תמונות מהמצלמה, האפליקציה שלך חייבת לצלם את התמונה, לגרום לה להתאים לגודל הצפוי, להתאים את הסיבוב שלה ולנרמל את נתוני התמונה. בעת עיבוד תמונות עם מודל TensorFlow Lite, אתה יכול להשתמש במחלקת TensorFlow Lite Support Library ImageProcessor כדי לטפל בעיבוד מקדים של נתונים זה, כפי שמוצג להלן.

כדי להפוך נתוני תמונה עבור דגם:

  1. השתמש בספריית התמיכה ImageProcessor כדי ליצור אובייקט להפיכת נתוני תמונה לפורמט שבו המודל שלך יכול להשתמש כדי להפעיל תחזיות: ( הפניה לקוד )

    private val tfImageProcessor by lazy {
       val cropSize = minOf(bitmapBuffer.width, bitmapBuffer.height)
       ImageProcessor.Builder()
           .add(ResizeWithCropOrPadOp(cropSize, cropSize))
           .add(ResizeOp(
               tfInputSize.height, tfInputSize.width, ResizeOp.ResizeMethod.NEAREST_NEIGHBOR))
           .add(Rot90Op(-imageRotationDegrees / 90))
           .add(NormalizeOp(0f, 1f))
           .build()
    }
    
  2. העתק את נתוני התמונה ממערכת מצלמות אנדרואיד והכן אותם לניתוח עם אובייקט ImageProcessor שלך: ( הפניה לקוד )

    // Copy out RGB bits to the shared buffer
    image.use { bitmapBuffer.copyPixelsFromBuffer(image.planes[0].buffer)  }
    
    // Process the image in Tensorflow
    val tfImage =  tfImageProcessor.process(tfImageBuffer.apply { load(bitmapBuffer) })
    

הפעל תחזיות

באפליקציית האנדרואיד שלך, ברגע שאתה יוצר אובייקט TensorImage עם נתוני תמונה בפורמט הנכון, אתה יכול להפעיל את המודל מול הנתונים האלה כדי לייצר חיזוי, או מסקנות . הקוד לדוגמה עבור מדריך זה משתמש במחלקה ObjectDetectionHelper המקופלת את הקוד הזה בשיטת predict predict() .

כדי להפעיל חיזוי על קבוצה של נתוני תמונה:

  1. הפעל את החיזוי על ידי העברת נתוני התמונה לפונקציית החיזוי שלך: ( הפניה לקוד )

    // Perform the object detection for the current frame
    val predictions = detector.predict(tfImage)
    
  2. קרא לשיטת הריצה במופע האובייקט tflite שלך ​​עם נתוני התמונה כדי ליצור תחזיות: ( הפניה לקוד )

    fun predict(image: TensorImage): List<ObjectPrediction> {
       tflite.runForMultipleInputsOutputs(arrayOf(image.buffer), outputBuffer)
       return predictions
    }
    

האובייקט TensorFlow Lite Interpreter מקבל נתונים אלה, מריץ אותם כנגד המודל ומפיק רשימה של תחזיות. לעיבוד רציף של נתונים על ידי המודל, השתמש בשיטת runForMultipleInputsOutputs() כך שאובייקטי Interpreter לא ייווצרו ולאחר מכן יוסרו על ידי המערכת עבור כל ריצת חיזוי.

ידית פלט דגם

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

הפלט של כל מודל נתון של TensorFlow Lite משתנה במונחים של מספר התחזיות שהוא מייצר (אחת או רבות), והמידע התיאורי עבור כל חיזוי. במקרה של מודל זיהוי אובייקט, חיזויים כוללים בדרך כלל נתונים עבור תיבה תוחמת המציינת היכן מזוהה אובייקט בתמונה. בקוד לדוגמה, הנתונים המוחזרים מעוצבים כרשימה של אובייקטי ObjectPrediction , כפי שמוצג להלן: ( הפניה לקוד )

val predictions get() = (0 until OBJECT_COUNT).map {
   ObjectPrediction(

       // The locations are an array of [0, 1] floats for [top, left, bottom, right]
       location = locations[0][it].let {
           RectF(it[1], it[0], it[3], it[2])
       },

       // SSD Mobilenet V1 Model assumes class 0 is background class
       // in label file and class labels start from 1 to number_of_classes + 1,
       // while outputClasses correspond to class index from 0 to number_of_classes
       label = labels[1 + labelIndices[0][it].toInt()],

       // Score is a single value of [0, 1]
       score = scores[0][it]
   )
}

צילום מסך לזיהוי אובייקט עבור המודל המשמש בדוגמה זו, כל חיזוי כולל מיקום תיבה תוחמת עבור האובייקט, תווית עבור האובייקט וציון חיזוי בין 0 ל-1 כצף המייצג את הביטחון של החיזוי, כאשר 1 הוא דירוג הביטחון הגבוה ביותר . באופן כללי, תחזיות עם ציון מתחת ל-50% (0.5) נחשבות לא חד משמעיות. עם זאת, אופן הטיפול בתוצאות חיזוי בעלות ערך נמוך תלוי בך ובצרכים של היישום שלך.

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

הצעדים הבאים