הפעלה מהירה ב-Android

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

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

הגדר והפעל את הדוגמה

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

  • Android Studio 4.2 ומעלה
  • Android SDK גרסה 21 ומעלה

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

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

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

  1. שכפל את מאגר git
    git clone https://github.com/tensorflow/examples.git
    
  2. הגדר את מופע ה-git שלך לשימוש בקופה דלילה, כך שיש לך רק את הקבצים עבור האפליקציה לדוגמה לזיהוי אובייקטים:
    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/object_detection/android_play_services
    

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

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

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

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

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

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

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

כיצד פועלת האפליקציה לדוגמה

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

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

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

בנה את האפליקציה

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

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

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

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

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

  1. במודול אפליקציית אנדרואיד המשתמש ב-TensorFlow Lite, עדכן את קובץ ה- build.gradle של המודול כך שיכלול את התלות הבאה. בקוד לדוגמה, הקובץ הזה נמצא כאן: ...examples/lite/examples/object_detection/android_play_services/app/build.gradle

    ...
    dependencies {
    ...
        // Tensorflow Lite dependencies
        implementation 'org.tensorflow:tensorflow-lite-task-vision-play-services:0.4.2'
        implementation 'com.google.android.gms:play-services-tflite-gpu:16.1.0'
    ...
    }
    
  2. ב-Android Studio, סנכרן את התלות בפרויקט על ידי בחירה: קובץ > סנכרן פרויקט עם קבצי Gradle .

אתחול שירותי Google Play

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

כדי לאתחל את TensorFlow Lite עם שירותי Google Play:

  1. צור אובייקט TfLiteInitializationOptions ושנה אותו כדי לאפשר תמיכה ב-GPU:

    val options = TfLiteInitializationOptions.builder()
        .setEnableGpuDelegateSupport(true)
        .build()
    
  2. השתמש בשיטת TfLiteVision.initialize() כדי לאפשר שימוש בזמן הריצה של שירותי Play, והגדר מאזין כדי לוודא שהוא נטען בהצלחה:

    TfLiteVision.initialize(context, options).addOnSuccessListener {
        objectDetectorListener.onInitialized()
    }.addOnFailureListener {
        // Called if the GPU Delegate is not supported on the device
        TfLiteVision.initialize(context).addOnSuccessListener {
            objectDetectorListener.onInitialized()
        }.addOnFailureListener{
            objectDetectorListener.onError("TfLiteVision failed to initialize: "
                    + it.message)
        }
    }
    

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

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

.../src/main/assets/mobilenetv1.tflite`

כדי לאתחל את הדגם:

  1. הוסף קובץ מודל .tflite לספריית src/main/assets של פרויקט הפיתוח שלך, כגון ssd_mobilenet_v1 .
  2. הגדר את המשתנה modelName כדי לציין את שם הקובץ של דגם ה-ML שלך:

    val modelName = "mobilenetv1.tflite"
    
  3. הגדר את האפשרויות עבור המודל, כגון סף החיזוי וגודל ערכת התוצאות:

    val optionsBuilder =
        ObjectDetector.ObjectDetectorOptions.builder()
            .setScoreThreshold(threshold)
            .setMaxResults(maxResults)
    
  4. אפשר האצת GPU עם האפשרויות ואפשר לקוד להיכשל בחן אם האצה אינה נתמכת במכשיר:

    try {
        optionsBuilder.useGpu()
    } catch(e: Exception) {
        objectDetectorListener.onError("GPU is not supported on this device")
    }
    
    
  5. השתמש בהגדרות מאובייקט זה כדי לבנות אובייקט TensorFlow Lite ObjectDetector המכיל את המודל:

    objectDetector =
        ObjectDetector.createFromFileAndOptions(
            context, modelName, optionsBuilder.build())
    

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

הכן נתונים עבור המודל

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

כדי להכין נתונים לעיבוד על ידי המודל:

  1. בנו אובייקט ImageAnalysis כדי לחלץ תמונות בפורמט הנדרש:

    imageAnalyzer =
        ImageAnalysis.Builder()
            .setTargetAspectRatio(AspectRatio.RATIO_4_3)
            .setTargetRotation(fragmentCameraBinding.viewFinder.display.rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setOutputImageFormat(OUTPUT_IMAGE_FORMAT_RGBA_8888)
            .build()
            ...
    
  2. חבר את המנתח למערכת המשנה של המצלמה וצור מאגר סיביות שיכיל את הנתונים שהתקבלו מהמצלמה:

            .also {
            it.setAnalyzer(cameraExecutor) { image ->
                if (!::bitmapBuffer.isInitialized) {
                    bitmapBuffer = Bitmap.createBitmap(
                        image.width,
                        image.height,
                        Bitmap.Config.ARGB_8888
                    )
                }
                detectObjects(image)
            }
        }
    
  3. חלץ את נתוני התמונה הספציפיים הדרושים למודל, והעביר את המידע על סיבוב התמונה:

    private fun detectObjects(image: ImageProxy) {
        // Copy out RGB bits to the shared bitmap buffer
        image.use { bitmapBuffer.copyPixelsFromBuffer(image.planes[0].buffer) }
        val imageRotation = image.imageInfo.rotationDegrees
        objectDetectorHelper.detect(bitmapBuffer, imageRotation)
    }    
    
  4. השלם את כל שינויי הנתונים הסופיים והוסף את נתוני התמונה לאובייקט TensorImage , כפי שמוצג בשיטת ObjectDetectorHelper.detect() של האפליקציה לדוגמה:

    val imageProcessor = ImageProcessor.Builder().add(Rot90Op(-imageRotation / 90)).build()
    
    // Preprocess the image and convert it into a TensorImage for detection.
    val tensorImage = imageProcessor.process(TensorImage.fromBitmap(image))
    

הפעל תחזיות

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

כדי להפעיל את המודל וליצור תחזיות מנתוני תמונה:

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

    val results = objectDetector?.detect(tensorImage)
    

ידית פלט דגם

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

כדי לטפל בתוצאות חיזוי מודל:

  1. השתמש בתבנית מאזינים כדי להעביר תוצאות לקוד האפליקציה או לאובייקטים של ממשק המשתמש שלך. האפליקציה לדוגמה משתמשת בדפוס זה כדי להעביר תוצאות זיהוי מהאובייקט ObjectDetectorHelper לאובייקט CameraFragment :

    objectDetectorListener.onResults( // instance of CameraFragment
        results,
        inferenceTime,
        tensorImage.height,
        tensorImage.width)
    
  2. פעל בהתאם לתוצאות, כגון הצגת התחזית למשתמש. האפליקציה לדוגמה מציירת שכבת-על על האובייקט CameraPreview כדי להציג את התוצאה:

    override fun onResults(
      results: MutableList<Detection>?,
      inferenceTime: Long,
      imageHeight: Int,
      imageWidth: Int
    ) {
        activity?.runOnUiThread {
            fragmentCameraBinding.bottomSheetLayout.inferenceTimeVal.text =
                String.format("%d ms", inferenceTime)
    
            // Pass necessary information to OverlayView for drawing on the canvas
            fragmentCameraBinding.overlay.setResults(
                results ?: LinkedList<Detection>(),
                imageHeight,
                imageWidth
            )
    
            // Force a redraw
            fragmentCameraBinding.overlay.invalidate()
        }
    }
    

הצעדים הבאים