Pembuatan Gambar di Perangkat di Android dengan MediaPipe

1. Pengantar

Apa itu MediaPipe?

MediaPipe Solutions dapat Anda gunakan untuk menerapkan solusi machine learning (ML) ke aplikasi Anda. Solusi ini memberikan kerangka kerja untuk mengonfigurasi pipeline pemrosesan prebuilt yang memberikan output segera, menarik, dan bermanfaat bagi pengguna. Anda bahkan dapat menyesuaikan banyak solusi ini dengan MediaPipe Model Maker untuk mengupdate model default.

Pembuatan Gambar dari Teks adalah salah satu dari beberapa tugas ML yang ditawarkan MediaPipe Solutions.

Dalam Codelab ini, Anda akan memulai dengan aplikasi Android yang sebagian besar kosong, lalu melanjutkan melalui beberapa langkah hingga Anda dapat membuat gambar baru langsung di perangkat Android Anda.

Yang akan Anda pelajari

  • Cara menerapkan pembuatan teks ke gambar yang berjalan secara lokal di aplikasi Android dengan MediaPipe Tasks.

Yang Anda butuhkan

  • Versi Android Studio yang terinstal (codelab ini ditulis dan diuji dengan Android Studio Giraffe).
  • Perangkat Android dengan RAM minimal 8 GB.
  • Pengetahuan dasar tentang pengembangan Android dan kemampuan untuk menjalankan skrip Python yang telah ditulis sebelumnya.

2. Menambahkan MediaPipe Tasks ke aplikasi Android

Download aplikasi awal Android

Codelab ini akan dimulai dengan contoh buatan yang terdiri dari UI yang akan digunakan untuk versi dasar pembuatan gambar. Anda dapat menemukan aplikasi awal tersebut di repo Contoh MediaPipe resmi di sini. Clone repo atau download file ZIP dengan mengklik Code > Download ZIP.

Mengimpor aplikasi ke Android Studio

  1. Buka Android Studio.
  2. Dari layar Welcome to Android Studio, pilih Open di pojok kanan atas.

a0b5b070b802e4ea.png

  1. Buka tempat Anda meng-clone atau mendownload repositori, lalu buka codelabs/image_generation_basic/android/start directory.
  2. Pada tahap ini, aplikasi tidak boleh dikompilasi karena Anda belum menyertakan dependensi MediaPipe Tasks.

Anda akan memperbaiki aplikasi dan menjalankannya dengan membuka file build.gradle dan men-scroll ke bawah ke // Step 1 - Add dependency. Dari sana, sertakan baris berikut, lalu klik tombol Sync Now yang muncul di banner di bagian atas Android Studio.

// Step 1 - Add dependency
implementation 'com.google.mediapipe:tasks-vision-image-generator:latest.release'

Setelah sinkronisasi selesai, pastikan semuanya terbuka dan terinstal dengan benar dengan mengklik panah run hijau ( 7e15a9c9e1620fe7.png) di kanan atas Android Studio. Anda akan melihat aplikasi terbuka ke layar dengan dua tombol pilihan dan tombol berlabel INITIALIZE. Jika Anda mengklik tombol tersebut, Anda akan langsung diarahkan ke UI terpisah yang terdiri dari perintah teks dan opsi lain di samping tombol berlabel GENERATE.

83c31de8e8a320ee.png 78b8765e832024e3.png

Sayangnya, itulah batas aplikasi starter, jadi sekarang saatnya Anda mempelajari cara menyelesaikan aplikasi ini dan mulai membuat gambar baru di perangkat Anda.

3. Menyiapkan Pembuat Gambar

Untuk contoh ini, sebagian besar pekerjaan pembuatan gambar akan terjadi di file ImageGenerationHelper.kt. Saat membuka file ini, Anda akan melihat variabel di bagian atas class yang disebut imageGenerator. Ini adalah objek Task yang akan melakukan tugas berat di aplikasi pembuatan gambar Anda.

Tepat di bawah objek tersebut, Anda akan melihat fungsi bernama initializeImageGenerator() dengan komentar berikut: // Step 2 - initialize the image generator. Seperti yang mungkin Anda duga, di sinilah Anda akan menginisialisasi objek ImageGenerator. Ganti isi fungsi tersebut dengan kode berikut untuk menetapkan jalur model pembuatan gambar dan menginisialisasi objek ImageGenerator:

// Step 2 - initialize the image generator
val options = ImageGeneratorOptions.builder()
    .setImageGeneratorModelDirectory(modelPath)
    .build()

imageGenerator = ImageGenerator.createFromOptions(context, options)

Di bawahnya, Anda akan melihat fungsi lain bernama setInput(). Fungsi ini menerima tiga parameter: string perintah yang akan digunakan untuk menentukan gambar yang dihasilkan, jumlah iterasi yang harus dilakukan Tugas saat membuat gambar baru, dan nilai seed yang dapat digunakan untuk membuat versi baru gambar berdasarkan perintah yang sama sekaligus membuat gambar yang sama saat seed yang sama digunakan. Tujuan fungsi ini adalah untuk menetapkan parameter awal ini untuk generator gambar saat Anda mencoba membuat gambar yang menampilkan langkah-langkah perantara.

Lanjutkan dan ganti isi setInput() (tempat Anda akan melihat komentar // Step 3 - accept inputs) dengan baris ini:

// Step 3 - accept inputs
imageGenerator.setInputs(prompt, iteration, seed)

Dua langkah berikutnya adalah tempat pembuatan berlangsung. Fungsi generate() menerima input yang sama dengan setInput, tetapi membuat gambar sebagai panggilan sekali pakai yang tidak menampilkan gambar langkah perantara. Anda dapat mengganti isi fungsi ini (yang mencakup komentar // Step 4 - generate without showing iterations) dengan kode berikut:

// Step 4 - generate without showing iterations
val result = imageGenerator.generate(prompt, iteration, seed)
val bitmap = BitmapExtractor.extract(result?.generatedImage())
return bitmap

Penting untuk diketahui bahwa tugas ini terjadi secara sinkron, jadi Anda harus memanggil fungsi dari thread latar belakang. Anda akan mempelajari lebih lanjut hal tersebut sebentar lagi dalam codelab ini.

Langkah terakhir yang akan Anda lakukan dalam file ini adalah mengisi fungsi execute() (berlabel Langkah 5). Fungsi ini akan menerima parameter yang memberi tahu apakah fungsi tersebut harus menampilkan gambar perantara atau tidak untuk satu langkah pembuatan yang akan dilakukan dengan fungsi execute() ImageGenerator. Ganti isi fungsi dengan kode ini:

// Step 5 - generate with iterations
val result = imageGenerator.execute(showResult)

if (result == null || result.generatedImage() == null) {
    return Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888)
        .apply {
            val canvas = Canvas(this)
            val paint = Paint()
            paint.color = Color.WHITE
            canvas.drawPaint(paint)
        }
}

val bitmap =
    BitmapExtractor.extract(result.generatedImage())

return bitmap

Dan itu saja untuk file helper. Di bagian berikutnya, Anda akan mengisi file ViewModel yang menangani logika untuk contoh ini.

4. Menyatukan Aplikasi

File MainViewModel akan menangani status UI dan logika lain yang terkait dengan aplikasi contoh ini. Buka sekarang.

Di bagian atas file, Anda akan melihat komentar // Step 6 - set model path. Di sinilah Anda akan memberi tahu aplikasi Anda tempat aplikasi dapat menemukan file model yang diperlukan untuk pembuatan gambar. Untuk contoh ini, Anda akan menetapkan nilai ke /data/local/tmp/image_generator/bins/.

// Step 6 - set model path
private val MODEL_PATH = "/data/local/tmp/image_generator/bins/"

Dari sana, scroll ke bawah ke fungsi generateImage(). Di bagian bawah fungsi ini, Anda akan melihat Langkah 7 dan Langkah 8, yang akan digunakan untuk membuat gambar dengan iterasi yang ditampilkan atau tidak sama sekali. Karena kedua operasi ini terjadi secara sinkron, Anda akan melihat bahwa keduanya dibungkus dalam coroutine. Anda dapat memulai dengan mengganti // Step 7 - Generate without showing iterations dengan blok kode ini untuk memanggil generate() dari file ImageGenerationHelper, lalu memperbarui status UI.

// Step 7 - Generate without showing iterations
val result = helper?.generate(prompt, iteration, seed)
_uiState.update {
    it.copy(outputBitmap = result)
}

Langkah 8 menjadi sedikit lebih rumit. Karena fungsi execute() hanya melakukan satu langkah, bukan semua langkah untuk pembuatan gambar, Anda harus memanggil setiap langkah satu per satu melalui loop. Anda juga perlu menentukan apakah langkah saat ini harus ditampilkan kepada pengguna. Terakhir, Anda akan mengupdate status UI jika iterasi saat ini harus ditampilkan. Anda dapat melakukan semua ini sekarang.

// Step 8 - Generate with showing iterations
helper?.setInput(prompt, iteration, seed)
for (step in 0 until iteration) {
    isDisplayStep =
        (displayIteration > 0 && ((step + 1) % displayIteration == 0))
    val result = helper?.execute(isDisplayStep)

    if (isDisplayStep) {
        _uiState.update {
            it.copy(
                outputBitmap = result,
                generatingMessage = "Generating... (${step + 1}/$iteration)",
            )
        }
    }
}

Pada tahap ini, Anda seharusnya dapat menginstal aplikasi, menginisialisasi generator gambar, lalu membuat gambar baru berdasarkan perintah teks

... tetapi sekarang aplikasi akan error saat Anda mencoba menginisialisasi generator gambar. Hal ini terjadi karena Anda perlu menyalin file model ke perangkat Anda. Untuk mendapatkan informasi terbaru tentang model pihak ketiga yang diketahui berfungsi, mengonversinya untuk tugas MediaPipe ini, dan menyalinnya ke perangkat Anda, Anda dapat meninjau bagian ini dalam dokumentasi resmi.

Selain menyalin file langsung ke perangkat pengembangan, Anda juga dapat menyiapkan Firebase Storage untuk mendownload file yang diperlukan langsung ke perangkat pengguna saat runtime.

5. Men-deploy dan menguji aplikasi

Setelah semua itu, Anda akan memiliki aplikasi yang berfungsi dan dapat menerima perintah teks serta membuat gambar baru sepenuhnya di perangkat. Lanjutkan dan deploy aplikasi ke perangkat Android fisik untuk mengujinya, tetapi ingatlah bahwa Anda sebaiknya mencoba ini dengan perangkat yang memiliki memori minimal 8 GB.

  1. Klik Run ( 7e15a9c9e1620fe7.png) di toolbar Android Studio untuk menjalankan aplikasi.
  2. Pilih jenis langkah pembuatan (final atau dengan iterasi), lalu tekan tombol INITIALIZE.
  3. Di layar berikutnya, tetapkan properti yang Anda inginkan dan klik tombol GENERATE untuk melihat hasil yang dihasilkan alat.

e46cfaeb9d3fc235.gif

6. Selamat!

Anda berhasil! Dalam codelab ini, Anda telah mempelajari cara menambahkan pembuatan teks ke gambar di perangkat ke aplikasi Android.

Langkah berikutnya

Ada lebih banyak hal yang dapat Anda lakukan dengan tugas pembuatan gambar, termasuk

  • menggunakan gambar dasar untuk menyusun gambar yang dihasilkan melalui plugin, atau melatih bobot LoRA tambahan Anda sendiri melalui Vertex AI.
  • Gunakan Firebase Storage untuk mengambil file model di perangkat Anda tanpa memerlukan penggunaan alat ADB.

Kami tidak sabar melihat semua hal keren yang Anda buat dengan tugas eksperimental ini, dan terus nantikan codelab dan konten lainnya dari tim MediaPipe.