Segmentasi Gambar yang Dipercepat secara Real-time di Android dengan LiteRT

1. Sebelum memulai

Mengetik kode adalah cara yang bagus untuk membangun memori otot dan memperdalam pemahaman Anda tentang materi. Meskipun salin tempel dapat menghemat waktu, berinvestasi dalam praktik ini dapat menghasilkan efisiensi yang lebih besar dan keterampilan coding yang lebih kuat dalam jangka panjang.

Dalam codelab ini, Anda akan mempelajari cara membuat aplikasi Android yang melakukan segmentasi gambar real-time pada feed kamera langsung menggunakan runtime baru Google untuk TensorFlow Lite, LiteRT. Anda akan menggunakan aplikasi Android awal dan menambahkan kemampuan segmentasi gambar ke aplikasi tersebut. Kita juga akan membahas langkah-langkah praproses, inferensi, dan pascaproses. Anda akan:

  • Bangun aplikasi Android yang menyegmentasikan gambar secara real-time.
  • Mengintegrasikan model segmentasi gambar LiteRT terlatih.
  • Memproses gambar input untuk model.
  • Gunakan runtime LiteRT untuk akselerasi CPU dan GPU.
  • Pahami cara memproses output model untuk menampilkan mask segmentasi.
  • Pahami cara menyesuaikan kamera depan.

Pada akhirnya, Anda akan membuat sesuatu yang mirip dengan gambar di bawah:

Aplikasi Selesai

Prasyarat

Codelab ini dirancang untuk developer seluler berpengalaman yang ingin mendapatkan pengalaman dengan Machine Learning. Anda harus memahami:

  • Pengembangan Android menggunakan Kotlin dan Android Studio
  • Konsep dasar pemrosesan gambar

Yang akan Anda pelajari

  • Cara mengintegrasikan dan menggunakan runtime LiteRT dalam aplikasi Android.
  • Cara melakukan segmentasi gambar menggunakan model LiteRT terlatih.
  • Cara memproses gambar input untuk model.
  • Cara menjalankan inferensi untuk model.
  • Cara memproses output model segmentasi untuk memvisualisasikan hasilnya.
  • Cara menggunakan CameraX untuk pemrosesan feed kamera real-time.

Yang Anda butuhkan

  • Versi terbaru Android Studio (diuji pada v2025.1.1).
  • Perangkat Android fisik. Fitur ini paling baik diuji di perangkat Galaxy dan Pixel.
  • Kode contoh (dari GitHub).
  • Pengetahuan dasar tentang pengembangan Android di Kotlin.

2. Segmentasi Gambar

Segmentasi gambar adalah tugas computer vision yang melibatkan pembagian gambar menjadi beberapa segmen atau region. Tidak seperti deteksi objek, yang menggambar kotak pembatas di sekitar objek, segmentasi gambar menetapkan kelas atau label tertentu ke setiap piksel dalam gambar. Hal ini memberikan pemahaman yang jauh lebih mendetail dan terperinci tentang isi gambar, sehingga Anda dapat mengetahui bentuk dan batas pasti setiap objek.

Misalnya, alih-alih hanya mengetahui bahwa 'seseorang' berada dalam kotak, Anda dapat mengetahui dengan tepat piksel mana yang termasuk orang tersebut. Tutorial ini menunjukkan cara melakukan segmentasi gambar real-time di perangkat Android menggunakan model machine learning terlatih.

Contoh Segmentasi

LiteRT: Mendorong Batas ML di Perangkat

Teknologi utama yang memungkinkan segmentasi real-time dan fidelitas tinggi di perangkat seluler adalah LiteRT. Sebagai runtime berperforma tinggi generasi berikutnya dari Google untuk TensorFlow Lite, LiteRT dirancang untuk mendapatkan performa terbaik dari hardware yang mendasarinya.

Hal ini dicapai melalui penggunaan akselerator hardware yang cerdas dan dioptimalkan seperti GPU (Unit Pemrosesan Grafis) dan NPU (Unit Pemrosesan Neural). Dengan meng-offload workload komputasi intensif model segmentasi dari CPU tujuan umum ke pemroses khusus ini, LiteRT secara drastis mengurangi waktu inferensi. Percepatan ini memungkinkan model yang kompleks berjalan lancar di feed kamera live, sehingga memperluas kemampuan yang dapat kita capai dengan machine learning langsung di ponsel Anda. Tanpa tingkat performa ini, segmentasi real-time akan terlalu lambat dan tidak lancar untuk memberikan pengalaman pengguna yang baik.

3. Memulai persiapan

Membuat clone repositori

Pertama, clone repositori untuk LiteRT:

git clone https://github.com/google-ai-edge/litert-samples.git

litert-samples/v2/image_segmentation adalah direktori dengan semua resource yang Anda butuhkan. Untuk codelab ini, Anda hanya memerlukan project kotlin_cpu_gpu/android_starter. Anda dapat meninjau project yang sudah selesai jika mengalami kesulitan: kotlin_cpu_gpu/android

Catatan tentang jalur file

Tutorial ini menentukan jalur file dalam format Linux/macOS. Jika menggunakan Windows, Anda harus menyesuaikan jalur yang sesuai.

Penting juga untuk mencatat perbedaan antara tampilan project Android Studio dan tampilan sistem file standar. Tampilan project Android Studio adalah representasi terstruktur dari file project Anda, yang disusun untuk pengembangan Android. Jalur file dalam tutorial ini mengacu pada jalur sistem file, bukan jalur dalam tampilan project Android Studio.

Mengimpor aplikasi awal

Mari kita mulai dengan mengimpor aplikasi awal ke Android Studio.

  1. Buka Android Studio dan pilih Open.

Membuka Android Studio

  1. Buka direktori kotlin_cpu_gpu/android_starter.

Android Starter

Untuk memastikan semua dependensi tersedia untuk aplikasi Anda, Anda harus menyinkronkan project dengan file gradle saat proses impor telah selesai.

  1. Pilih Sync Project with Gradle Files dari toolbar Android Studio.

Sinkronisasi Menu

  1. Jangan lewati langkah ini – jika tidak berhasil, tutorial selanjutnya tidak akan masuk akal.

Menjalankan aplikasi awal

Setelah mengimpor project ke Android Studio, Anda siap menjalankan aplikasi untuk pertama kalinya.

Hubungkan perangkat Android Anda melalui USB ke komputer, lalu klik Run di toolbar Android Studio.

Tombol Jalankan

Aplikasi akan diluncurkan di perangkat Anda. Anda akan melihat feed kamera live, tetapi segmentasi belum akan terjadi. Semua pengeditan file yang akan Anda lakukan dalam tutorial ini akan berada di direktori litert-samples/v2/image_segmentation/kotlin_cpu_gpu/android_starter/app/src/main/java/com/google/aiedge/examples/image_segmentation (sekarang Anda tahu mengapa Android Studio menyusun ulang ini 😃).

Project Dir

Anda juga akan melihat komentar TODO di file ImageSegmentationHelper.kt, MainViewModel.kt, dan view/SegmentationOverlay.kt. Pada langkah-langkah berikut, Anda akan menerapkan fungsi segmentasi gambar dengan mengisi TODO ini.

4. Memahami aplikasi awal

Aplikasi awal sudah memiliki UI dasar dan logika penanganan kamera. Berikut ringkasan singkat file utama:

  • app/src/main/java/com/google/aiedge/examples/image_segmentation/MainActivity.kt: Ini adalah titik entri utama aplikasi. Aplikasi ini menyiapkan UI menggunakan Jetpack Compose dan menangani izin kamera.
  • app/src/main/java/com/google/aiedge/examples/image_segmentation/MainViewModel.kt: ViewModel ini mengelola status UI dan mengatur proses segmentasi gambar.
  • app/src/main/java/com/google/aiedge/examples/image_segmentation/ImageSegmentationHelper.kt: Di sinilah kita akan menambahkan logika inti untuk segmentasi gambar. Class ini akan menangani pemuatan model, pemrosesan frame kamera, dan menjalankan inferensi.
  • app/src/main/java/com/google/aiedge/examples/image_segmentation/view/CameraScreen.kt: Fungsi Composable ini menampilkan pratinjau kamera dan overlay segmentasi.
  • app/src/main/assets/selfie_multiclass.tflite: Ini adalah model segmentasi gambar TensorFlow Lite terlatih yang akan kita gunakan.

5. Memahami LiteRT dan Menambahkan Dependensi

Sekarang, mari kita tambahkan fungsi segmentasi gambar ke aplikasi starter.

1. Menambahkan Dependensi LiteRT

Pertama, Anda harus menambahkan library LiteRT ke project Anda. Ini adalah langkah pertama yang penting untuk mengaktifkan machine learning di perangkat dengan runtime yang dioptimalkan Google.

Buka file app/build.gradle.kts dan tambahkan baris berikut ke blok dependencies:

// LiteRT for on-device ML
implementation(libs.litert)

Setelah menambahkan dependensi, sinkronkan project Anda dengan file Gradle dengan mengklik tombol Sync Now yang muncul di sudut kanan atas Android Studio.

Sinkronkan Sekarang

2. Memahami API Key LiteRT

Buka ImageSegmentationHelper.kt

Sebelum menulis kode implementasi, penting untuk memahami komponen inti LiteRT API yang akan Anda gunakan. Pastikan Anda mengimpor dari paket com.google.ai.edge.litert, tambahkan impor berikut ke bagian atas ImageSegmentationHelper.kt:

import com.google.ai.edge.litert.Accelerator
import com.google.ai.edge.litert.CompiledModel
  • CompiledModel: Ini adalah class pusat untuk berinteraksi dengan model TFLite Anda. Objek ini merepresentasikan model yang telah dikompilasi dan dioptimalkan sebelumnya untuk akselerator hardware tertentu (seperti CPU atau GPU). Pra-kompilasi ini adalah fitur utama LiteRT yang menghasilkan inferensi yang lebih cepat dan efisien.
  • CompiledModel.Options: Anda menggunakan class builder ini untuk mengonfigurasi CompiledModel. Setelan terpenting adalah menentukan akselerator hardware yang ingin Anda gunakan untuk menjalankan model.
  • Accelerator: Enum ini memungkinkan Anda memilih hardware untuk inferensi. Project awal sudah dikonfigurasi untuk menangani opsi ini:
    • Accelerator.CPU: Untuk menjalankan model di CPU perangkat. Ini adalah opsi yang paling kompatibel secara universal.
    • Accelerator.GPU: Untuk menjalankan model di GPU perangkat. Proses ini sering kali jauh lebih cepat daripada CPU untuk model berbasis gambar.
  • Buffer Input dan Output (TensorBuffer): LiteRT menggunakan TensorBuffer untuk input dan output model. Hal ini memberi Anda kontrol terperinci atas memori dan menghindari salinan data yang tidak perlu. Anda akan mendapatkan buffer ini langsung dari instance CompiledModel menggunakan model.createInputBuffers() dan model.createOutputBuffers(), lalu menulis data input ke buffer tersebut dan membaca hasilnya dari buffer tersebut.
  • model.run(): Ini adalah fungsi yang mengeksekusi inferensi. Anda meneruskan buffer input dan output ke LiteRT, dan LiteRT menangani tugas kompleks untuk menjalankan model pada akselerator hardware yang dipilih.

6. Menyelesaikan Penerapan ImageSegmentationHelper Awal

Sekarang saatnya menulis beberapa kode. Anda akan menyelesaikan penerapan awal ImageSegmentationHelper.kt. Hal ini melibatkan penyiapan class pribadi Segmenter untuk menyimpan model LiteRT dan penerapan fungsi cleanup() untuk melepaskannya dengan benar.

  1. Selesaikan class Segmenter dan fungsi cleanup(): Di file ImageSegmentationHelper.kt, Anda akan menemukan kerangka untuk class pribadi bernama Segmenter dan fungsi bernama cleanup(). Pertama, selesaikan class Segmenter dengan menentukan konstruktornya untuk menyimpan model, membuat properti untuk buffer input/output, dan menambahkan metode close() untuk melepaskan model. Kemudian, terapkan fungsi cleanup() untuk memanggil metode close() baru ini.Ganti class Segmenter dan fungsi cleanup() yang ada dengan kode berikut: (~baris 83)
    private class Segmenter(
        // Add this argument
        private val model: CompiledModel,
        private val coloredLabels: List<ColoredLabel>,
    ) {
        // Add these private vals
        private val inputBuffers = model.createInputBuffers()
        private val outputBuffers = model.createOutputBuffers()
    
        fun cleanup() {
          // cleanup buffers
          inputBuffers.forEach { it.close() }
          outputBuffers.forEach { it.close() }
          // cleanup model
          model.close()
        }
    }
    
  2. Tentukan Metode toAccelerator: Metode ini memetakan enum akselerator yang ditentukan dari menu akselerator ke enum akselerator yang khusus untuk modul LiteRT yang diimpor (~baris 225):
    fun toAccelerator(acceleratorEnum: AcceleratorEnum): Accelerator {
      return when (acceleratorEnum) {
        AcceleratorEnum.CPU -> Accelerator.CPU
        AcceleratorEnum.GPU -> Accelerator.GPU
      }
    }
    
  3. Lakukan inisialisasi CompiledModel: Sekarang temukan fungsi initSegmenter. Di sini Anda akan membuat instance CompiledModel dan menggunakannya untuk membuat instance class Segmenter yang kini telah ditentukan. Kode ini menyiapkan model dengan akselerator yang ditentukan (CPU atau GPU) dan menyiapkannya untuk inferensi. Ganti TODO di initSegmenter dengan implementasi berikut (Cmd/Ctrl+f ‘initSegmenter` atau ~baris 62):
    cleanup()
    try {
      withContext(singleThreadDispatcher) {
        val model =
          CompiledModel.create(
            context.assets,
            "selfie_multiclass.tflite",
            CompiledModel.Options(toAccelerator(acceleratorEnum)),
            null,
          )
        segmenter = Segmenter(model, coloredLabels)
        Log.d(TAG, "Created an image segmenter")
      }
    } catch (e: Exception) {
      Log.i(TAG, "Create LiteRT from selfie_multiclass is failed: ${e.message}")
      _error.emit(e)
    }
    

7. Mulai Segmentasi dan Pra-pemrosesan

Setelah memiliki model, kita perlu memicu proses segmentasi dan menyiapkan data input untuk model.

Pemicu Segmentasi

Proses segmentasi dimulai di MainViewModel.kt, yang menerima frame dari kamera.

Buka MainViewModel.kt

  1. Memicu Segmentasi dari Frame Kamera: Fungsi segment di MainViewModel adalah titik entri untuk tugas segmentasi kita. Fungsi ini dipanggil setiap kali gambar baru tersedia dari kamera atau dipilih dari galeri. Fungsi ini kemudian memanggil metode segment di ImageSegmentationHelper kita. Ganti TODO di kedua fungsi segment dengan yang berikut (baris ~107):
    // For ImageProxy (from CameraX)
    fun segment(imageProxy: ImageProxy) {
        segmentJob =
            viewModelScope.launch {
                imageSegmentationHelper.segment(imageProxy.toBitmap(), imageProxy.imageInfo.rotationDegrees)
                imageProxy.close()
            }
    }
    
    // For Bitmaps (from gallery)
    fun segment(bitmap: Bitmap, rotationDegrees: Int) {
        segmentJob =
            viewModelScope.launch {
                val argbBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
                imageSegmentationHelper.segment(argbBitmap, rotationDegrees)
            }
    }
    

Melakukan Prapemrosesan Gambar

Sekarang, mari kita kembali ke ImageSegmentationHelper.kt untuk menangani praproses gambar.

Buka ImageSegmentationHelper.kt

  1. Menerapkan Fungsi Publik segment: Fungsi ini berfungsi sebagai wrapper yang memanggil fungsi pribadi segment dalam class Segmenter. Ganti TODO dengan (~baris 95):
    try {
      withContext(singleThreadDispatcher) {
        segmenter?.segment(bitmap, rotationDegrees)?.let { if (isActive) _segmentation.emit(it) }
      }
    } catch (e: Exception) {
      Log.i(TAG, "Image segment error occurred: ${e.message}")
      _error.emit(e)
    }
    
  2. Menerapkan Pra-pemrosesan: Fungsi segment pribadi di dalam class Segmenter adalah tempat kita akan melakukan transformasi yang diperlukan pada gambar input untuk mempersiapkannya bagi model. Hal ini mencakup penskalaan, rotasi, dan normalisasi gambar. Fungsi ini kemudian akan memanggil fungsi segment pribadi lain untuk melakukan inferensi. Ganti TODO di fungsi segment(bitmap: Bitmap, ...) dengan (~baris 121):
    val totalStartTime = SystemClock.uptimeMillis()
    val rotation = -rotationDegrees / 90
    val (h, w) = Pair(256, 256)
    
    // Preprocessing
    val preprocessStartTime = SystemClock.uptimeMillis()
    var image = bitmap.scale(w, h, true)
    image = rot90Clockwise(image, rotation)
    val inputFloatArray = normalize(image, 127.5f, 127.5f)
    Log.d(TAG, "Preprocessing time: ${SystemClock.uptimeMillis() - preprocessStartTime} ms")
    
    // Inference
    val inferenceStartTime = SystemClock.uptimeMillis()
    val segmentResult = segment(inputFloatArray)
    Log.d(TAG, "Inference time: ${SystemClock.uptimeMillis() - inferenceStartTime} ms")
    
    Log.d(TAG, "Total segmentation time: ${SystemClock.uptimeMillis() - totalStartTime} ms")
    return SegmentationResult(segmentResult, SystemClock.uptimeMillis() - inferenceStartTime)
    

8. Inferensi Utama dengan LiteRT

Setelah data input diproses sebelumnya, kita dapat menjalankan inferensi inti menggunakan LiteRT.

Buka ImageSegmentationHelper.kt

  1. Menerapkan Eksekusi Model: Fungsi segment(inputFloatArray: FloatArray) pribadi adalah tempat kita berinteraksi langsung dengan metode run() LiteRT. Kita menulis data yang telah diproses sebelumnya ke buffer input, menjalankan model, dan membaca hasilnya dari buffer output. Ganti TODO dalam fungsi ini dengan (~baris 188):
    val (h, w, c) = Triple(256, 256, 6)
    
    // MODEL EXECUTION PHASE
    val modelExecStartTime = SystemClock.uptimeMillis()
    
    // Write input data - measure time
    val bufferWriteStartTime = SystemClock.uptimeMillis()
    inputBuffers[0].writeFloat(inputFloatArray)
    val bufferWriteTime = SystemClock.uptimeMillis() - bufferWriteStartTime
    Log.d(TAG, "Buffer write time: $bufferWriteTime ms")
    
    // Optional tensor inspection
    logTensorStats("Input tensor", inputFloatArray)
    
    // Run model inference - measure time
    val modelRunStartTime = SystemClock.uptimeMillis()
    model.run(inputBuffers, outputBuffers)
    val modelRunTime = SystemClock.uptimeMillis() - modelRunStartTime
    Log.d(TAG, "Model.run() time: $modelRunTime ms")
    
    // Read output data - measure time
    val bufferReadStartTime = SystemClock.uptimeMillis()
    val outputFloatArray = outputBuffers[0].readFloat()
    val outputBuffer = FloatBuffer.wrap(outputFloatArray)
    val bufferReadTime = SystemClock.uptimeMillis() - bufferReadStartTime
    Log.d(TAG, "Buffer read time: $bufferReadTime ms")
    
    val modelExecTime = SystemClock.uptimeMillis() - modelExecStartTime
    Log.d(TAG, "Total model execution time: $modelExecTime ms")
    
    // Optional tensor inspection
    logTensorStats("Output tensor", outputFloatArray)
    
    // POSTPROCESSING PHASE
    val postprocessStartTime = SystemClock.uptimeMillis()
    
    // Process mask from model output
    val inferenceData = InferenceData(width = w, height = h, channels = c, buffer = outputBuffer)
    val mask = processImage(inferenceData)
    
    val postprocessTime = SystemClock.uptimeMillis() - postprocessStartTime
    Log.d(TAG, "Postprocessing time (mask creation): $postprocessTime ms")
    
    return Segmentation(
      listOf(Mask(mask, inferenceData.width, inferenceData.height)),
      coloredLabels,
    )
    

9. Memproses dan Menampilkan Overlay

Setelah menjalankan inferensi, kita akan mendapatkan output mentah dari model. Kita perlu memproses output ini untuk membuat mask segmentasi visual, lalu menampilkannya di layar.

Buka ImageSegmentationHelper.kt

  1. Menerapkan Pemrosesan Output: Fungsi processImage mengonversi output floating-point mentah dari model menjadi ByteBuffer yang merepresentasikan mask segmentasi. Hal ini dilakukan dengan menemukan class dengan probabilitas tertinggi untuk setiap piksel. Ganti TODO dengan (~baris 238):
    val mask = ByteBuffer.allocateDirect(inferenceData.width * inferenceData.height)
    for (i in 0 until inferenceData.height) {
        for (j in 0 until inferenceData.width) {
            val offset = inferenceData.channels * (i * inferenceData.width + j)
    
            var maxIndex = 0
            var maxValue = inferenceData.buffer.get(offset)
    
            for (index in 1 until inferenceData.channels) {
                if (inferenceData.buffer.get(offset + index) > maxValue) {
                    maxValue = inferenceData.buffer.get(offset + index)
                    maxIndex = index
                }
            }
            mask.put(i * inferenceData.width + j, maxIndex.toByte())
        }
    }
    return mask
    

Buka MainViewModel.kt

  1. Mengumpulkan dan Memproses Hasil Segmentasi: Sekarang kita kembali ke MainViewModel untuk memproses hasil segmentasi dari ImageSegmentationHelper. segmentationUiShareFlow mengumpulkan SegmentationResult, mengonversi mask menjadi Bitmap berwarna, dan menyediakannya ke UI. Ganti TODO di properti segmentationUiShareFlow dengan (~baris 63) – jangan ganti kode yang sudah ada, cukup isi isi:
    viewModelScope.launch {
      imageSegmentationHelper.segmentation
        .filter { it.segmentation.masks.isNotEmpty() }
        .map {
          val segmentation = it.segmentation
          val mask = segmentation.masks[0]
          val maskArray = mask.data
          val width = mask.width
          val height = mask.height
          val pixelSize = width * height
          val pixels = IntArray(pixelSize)
    
          val colorLabels =
            segmentation.coloredLabels.mapIndexed { index, coloredLabel ->
              ColorLabel(index, coloredLabel.label, coloredLabel.argb)
            }
          // Set color for pixels
          for (i in 0 until pixelSize) {
            val colorLabel = colorLabels[maskArray[i].toInt()]
            val color = colorLabel.getColor()
            pixels[i] = color
          }
          // Get image info
          val overlayInfo = OverlayInfo(pixels = pixels, width = width, height = height)
    
          val inferenceTime = it.inferenceTime
          Pair(overlayInfo, inferenceTime)
        }
        .collect { flow.emit(it) }
    }
    

Buka view/SegmentationOverlay.kt

Bagian terakhir adalah mengarahkan overlay segmentasi dengan benar saat pengguna beralih ke kamera depan. Feed kamera secara alami dicerminkan untuk kamera depan, jadi kita perlu menerapkan flip horizontal yang sama ke overlay Bitmap untuk memastikan overlay tersebut selaras dengan benar dengan pratinjau kamera.

  1. Menangani Orientasi Overlay: Temukan TODO di file SegmentationOverlay.kt dan ganti dengan kode berikut. Kode ini memeriksa apakah kamera depan aktif dan, jika ya, menerapkan flip horizontal ke overlay Bitmap sebelum digambar di Canvas. (~baris 42):
    val orientedBitmap =
      if (lensFacing == CameraSelector.LENS_FACING_FRONT) {
        // Create a matrix for horizontal flipping
        val matrix = Matrix().apply { preScale(-1f, 1f) }
        Bitmap.createBitmap(image, 0, 0, image.width, image.height, matrix, false).also {
          image.recycle()
        }
      } else {
        image
      }
    

10. Menjalankan dan Menggunakan Aplikasi Akhir

Sekarang Anda telah menyelesaikan semua perubahan kode yang diperlukan. Sekarang saatnya menjalankan aplikasi dan melihat hasil kerja Anda.

  1. Jalankan Aplikasi: Hubungkan perangkat Android Anda dan klik Run di toolbar Android Studio.

Tombol Jalankan

  1. Menguji Fitur: Setelah aplikasi diluncurkan, Anda akan melihat feed kamera live dengan overlay segmentasi berwarna.
    • Ganti Kamera: Ketuk ikon balik kamera di bagian atas untuk beralih antara kamera depan dan belakang. Perhatikan bagaimana overlay memosisikan dirinya dengan benar.
    • Ubah Akselerator: Ketuk tombol "CPU" atau "GPU" di bagian bawah untuk mengganti akselerator hardware. Amati perubahan Waktu Inferensi yang ditampilkan di bagian bawah layar. GPU akan jauh lebih cepat.
    • Menggunakan Gambar Galeri: Ketuk tab "Galeri" di bagian atas untuk memilih gambar dari galeri foto perangkat Anda. Aplikasi akan menjalankan segmentasi pada gambar statis yang dipilih.

UI Lainnya

Anda kini memiliki aplikasi segmentasi gambar real-time yang berfungsi penuh dan didukung oleh LiteRT.

11. Lanjutan (Opsional): Menggunakan NPU

Repositori ini juga berisi versi aplikasi yang dioptimalkan untuk Neural Processing Unit (NPU). Versi NPU dapat memberikan peningkatan performa yang signifikan pada perangkat yang memiliki NPU yang kompatibel.

Untuk mencoba versi NPU, buka project kotlin_npu/android di Android Studio. Kodenya sangat mirip dengan versi CPU/GPU dan dikonfigurasi untuk menggunakan delegasi NPU.

Untuk menggunakan delegasi NPU, Anda harus mendaftar ke Program Akses Awal.

12. Selamat!

Anda telah berhasil membuat aplikasi Android yang melakukan segmentasi gambar real-time menggunakan LiteRT. Anda telah mempelajari cara:

  • Integrasikan runtime LiteRT ke dalam aplikasi Android.
  • Memuat dan menjalankan model segmentasi gambar TFLite.
  • Memproses input model.
  • Memproses output model untuk membuat mask segmentasi.
  • Gunakan CameraX untuk aplikasi kamera real-time.

Langkah Berikutnya

  • Coba model segmentasi gambar yang berbeda.
  • Bereksperimen dengan berbagai delegasi LiteRT (CPU, GPU, NPU).

Pelajari Lebih Lanjut