Kasus penggunaan analisis gambar
memberi aplikasi Anda gambar yang dapat diakses CPU, yang memungkinkan Anda
melakukan pemrosesan gambar, computer vision, atau inferensi machine learning. Aplikasi
ini mengimplementasikan
metode analyze()
yang dijalankan di setiap frame.
Untuk mempelajari cara mengintegrasikan ML Kit Google dengan aplikasi CameraX, lihat ML Kit Analyzer.
Mode Operasi
Jika pipeline analisis aplikasi tidak dapat memenuhi persyaratan kecepatan frame CameraX, CameraX dapat dikonfigurasi untuk menghapus frame dengan salah satu cara berikut:
non-pemblokiran (default): Dalam mode ini, eksekutor selalu men-cache gambar terbaru ke buffering gambar (mirip dengan antrean dengan kedalaman satu) saat aplikasi menganalisis gambar sebelumnya. Jika CameraX menerima gambar baru sebelum aplikasi selesai memproses gambar sebelumnya, gambar baru akan disimpan ke buffering yang sama dan menimpa gambar sebelumnya. Perlu diperhatikan bahwa
ImageAnalysis.Builder.setImageQueueDepth()
tidak berpengaruh dalam skenario ini, dan konten buffering akan selalu ditimpa. Anda dapat mengaktifkan mode non-pemblokiran ini dengan memanggilsetBackpressureStrategy()
menggunakanSTRATEGY_KEEP_ONLY_LATEST
. Untuk informasi selengkapnya tentang implikasi eksekutor, lihat dokumentasi referensi untukSTRATEGY_KEEP_ONLY_LATEST
.pemblokiran: Dalam mode ini, eksekutor internal dapat menambahkan beberapa gambar ke antrean gambar internal dan mulai menghapus frame hanya saat antrean penuh. Pemblokiran terjadi di seluruh cakupan perangkat kamera: jika perangkat kamera memiliki beberapa kasus penggunaan terikat, kasus penggunaan tersebut semuanya akan diblokir saat CameraX memproses gambar ini. Misalnya, jika analisis pratinjau dan gambar terikat ke perangkat Kamera, pratinjau juga akan diblokir saat CameraX memproses gambar. Anda dapat mengaktifkan mode pemblokiran dengan meneruskan
STRATEGY_BLOCK_PRODUCER
kesetBackpressureStrategy()
. Anda juga dapat mengonfigurasi kedalaman antrean gambar menggunakan ImageAnalysis.Builder.setImageQueueDepth().
Dengan analyzer berlatensi rendah dan berperforma tinggi saat total waktu untuk menganalisis gambar kurang dari durasi frame CameraX (misalnya, 16 md untuk 60 fps), kedua mode operasi memberikan pengalaman keseluruhan yang lancar. Mode pemblokiran masih dapat membantu dalam beberapa skenario, seperti saat menangani jitter sistem yang sangat singkat.
Dengan analyzer berlatensi tinggi dan berperforma tinggi, mode pemblokiran dengan antrean yang lebih panjang diperlukan untuk mengimbangi latensi. Namun, perlu diperhatikan bahwa aplikasi masih dapat memproses semua frame.
Dengan analyzer berlatensi tinggi dan memakan waktu (analyzer tidak dapat memproses semua frame), mode non-pemblokiran mungkin menjadi pilihan yang lebih tepat, karena frame harus dihapus untuk jalur analisis, tetapi kasus penggunaan terikat serentak lainnya masih dapat melihat semua frame.
Implementasi
Untuk menggunakan analisis gambar dalam aplikasi, ikuti langkah-langkah berikut:
- Buat kasus penggunaan
ImageAnalysis
. - Buat
ImageAnalysis.Analyzer
. - Setel analyzer ke
ImageAnalysis
Anda. - Ikat
pemilik siklus proses, pemilih kamera, dan kasus penggunaan
ImageAnalysis
ke siklus proses.
Segera setelah pengikatan, CameraX akan mengirimkan gambar ke analyzer yang terdaftar.
Setelah menyelesaikan analisis, panggil
ImageAnalysis.clearAnalyzer()
atau lepas kasus penggunaan ImageAnalysis
untuk menghentikan analisis.
Membuat kasus penggunaan ImageAnalysis
ImageAnalysis
menghubungkan
analyzer (konsumen gambar) ke CameraX, yang merupakan penghasil gambar.
Aplikasi dapat menggunakan
ImageAnalysis.Builder
untuk membuat objek ImageAnalysis
. Dengan ImageAnalysis.Builder
,
aplikasi dapat mengonfigurasi hal berikut:
- Parameter output gambar:
- Format: CameraX mendukung
YUV_420_888
danRGBA_8888
melaluisetOutputImageFormat(int)
. Format default-nya adalahYUV_420_888
. - Resolusi dan AspectRatio: Anda dapat menyetel salah satu parameter ini, tetapi perhatikan bahwa Anda tidak dapat menyetel kedua nilai secara bersamaan.
- Rotasi.
- Nama Target: Gunakan parameter ini untuk tujuan proses debug.
- Format: CameraX mendukung
- Kontrol alur gambar:
Aplikasi dapat menyetel resolusi atau rasio lebar tinggi, tetapi tidak
keduanya. Resolusi output yang tepat bergantung pada ukuran (atau rasio aspek)
dan kemampuan hardware yang diminta aplikasi, dan mungkin berbeda dengan ukuran atau rasio
yang diminta. Untuk mengetahui informasi tentang algoritme pencocokan resolusi, lihat
dokumentasi untuk
setTargetResolution()
Aplikasi dapat mengonfigurasi piksel gambar output agar berada dalam ruang warna YUV (default)
atau RGBA. Jika menyetel format output RGBA, CameraX akan mengonversi gambar secara internal dari
ruang warna YUV ke RGBA dan memaketkan bit gambar ke
ByteBuffer
bidang pertama ImageProxy (dua bidang lainnya tidak digunakan) dengan
urutan berikut:
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...
Saat melakukan analisis gambar yang rumit dan perangkat tidak dapat mempertahankan kecepatan frame, Anda dapat mengonfigurasi CameraX untuk menghapus frame dengan strategi yang dijelaskan di bagian Mode Operasi dalam topik ini.
Membuat analyzer
Aplikasi dapat membuat penganalisis dengan menerapkan
ImageAnalysis.Analyzer
antarmuka pengguna dan penggantian
analyze(ImageProxy image)
.
Di setiap analyzer, aplikasi menerima
ImageProxy
, yang merupakan wrapper
untuk Media.Image.
Format gambar dapat dibuat kuerinya dengan
ImageProxy.getFormat()
.
Formatnya adalah salah satu dari nilai berikut yang disediakan
aplikasi dengan ImageAnalysis.Builder
:
ImageFormat.RGBA_8888
jika aplikasi memintaOUTPUT_IMAGE_FORMAT_RGBA_8888
.ImageFormat.YUV_420_888
jika aplikasi memintaOUTPUT_IMAGE_FORMAT_YUV_420_888
.
Lihat Membuat kasus penggunaan ImageAnalysis untuk mengetahui konfigurasi ruang warna dan tempat pengambilan byte piksel.
Di dalam analyzer, aplikasi harus melakukan hal berikut:
- Menganalisis frame tertentu secepat mungkin, yang sebaiknya dalam batas waktu kecepatan frame tertentu (misalnya, kurang dari 32 md untuk kasus 30 fps). Jika aplikasi tidak dapat menganalisis frame dengan cukup cepat, pertimbangkan salah satu mekanisme penghapusan frame yang didukung.
- Merilis
ImageProxy
ke CameraX dengan memanggilImageProxy.close()
. Perhatikan bahwa Anda tidak boleh memanggil fungsi close Media.Image yang digabungkan (Media.Image.close()
).
Aplikasi dapat menggunakan Media.Image
yang digabungkan dalam ImageProxy secara langsung.
Namun, jangan memanggil Media.Image.close()
pada gambar yang digabungkan karena hal itu akan mengganggu
mekanisme berbagi gambar di dalam CameraX. Sebagai gantinya, gunakan
ImageProxy.close()
untuk merilis Media.Image
utama ke CameraX.
Mengonfigurasi analyzer untuk ImageAnalysis
Setelah membuat analyzer, gunakan
ImageAnalysis.setAnalyzer()
untuk mendaftarkannya agar dapat memulai analisis. Setelah menyelesaikan analisis, gunakan
ImageAnalysis.clearAnalyzer()
untuk menghapus analyzer yang terdaftar.
Hanya satu analyzer aktif yang dapat dikonfigurasi untuk analisis gambar. Memanggil
ImageAnalysis.setAnalyzer()
akan menggantikan analyzer yang terdaftar
jika sudah ada. Aplikasi dapat menyetel analyzer baru kapan saja, sebelum atau setelah mengikat
kasus penggunaan.
Mengikat ImageAnalysis ke Lifecycle
Sangat direkomendasikan untuk mengikat ImageAnalysis
Anda ke siklus proses AndroidX
yang ada
dengan fungsi
ProcessCameraProvider.bindToLifecycle()
. Perhatikan bahwa fungsi bindToLifecycle()
akan menampilkan
Camera
yang dipilih, yang dapat digunakan
untuk menyesuaikan setelan lanjutan seperti eksposur dan lainnya. Lihat panduan ini untuk informasi selengkapnya tentang mengontrol output kamera.
Contoh berikut menggabungkan semua langkah sebelumnya, yaitu mengikat
kasus penggunaan ImageAnalysis
dan Preview
CameraX ke pemilik lifeCycle
:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() // enable the following line if RGBA output is needed. // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> val rotationDegrees = imageProxy.imageInfo.rotationDegrees // insert your code here. ... // after done, release the ImageProxy object imageProxy.close() }) cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() // enable the following line if RGBA output is needed. //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(new Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { @Override public void analyze(@NonNull ImageProxy imageProxy) { int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); // insert your code here. ... // after done, release the ImageProxy object imageProxy.close(); } }); cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
Referensi lainnya
Untuk mempelajari CameraX lebih lanjut, lihat referensi tambahan berikut.
Codelab
Contoh kode