Pengguna mengharapkan aplikasi pihak ketiga dapat mengambil foto dan video dengan fidelitas tinggi yang sama seperti kamera bawaan perangkat, terlepas dari kondisi pencahayaan atau tingkat hardware. Menghadirkan konsistensi ini di seluruh ekosistem Android yang terus berkembang memerlukan pertimbangan arsitektur yang penting. Sesi ini menunjukkan cara membuat pipeline pengambilan yang andal dan profesional yang memaksimalkan kemampuan perangkat sekaligus tetap andal di semua faktor bentuk.
Kami akan membahas kemajuan terbaru di CameraX, menunjukkan cara mengintegrasikan kapabilitas canggih seperti Foto motion (foto dengan gambar bergerak) dan Sempurnakan dengan AI di perangkat melalui layanan Google Play, serta pengalaman spasial menggunakan Jetpack XR SDK. Kami juga akan membahas kemampuan CameraX, yang memungkinkan agen coding pilihan Anda menerapkan konsep dalam presentasi ini secara otomatis, dan banyak lagi.
CameraXViewfinder menyesuaikan pratinjau kamera di berbagai faktor bentuk seperti perangkat foldable. Di CameraX 1.7, kontrol gestur dan dukungan Flash Layar ditambahkan.ProjectedDeviceContext, CameraX dapat mengambil gambar langsung dari kacamata pintar.Transkrip
Halo semuanya.
Selamat datang di sesi kami.
Saya Aman, dan bersama saya ada Scott.
Hari ini, kami sangat senang membahas cara Anda dapat meningkatkan pengalaman kamera di berbagai perangkat dengan CameraX dan kecerdasan di perangkat.
Jadi, mari kita mulai.
Pikirkan cara Anda menggunakan ponsel.
Kita sering menggunakan kamera ponsel untuk mengabadikan momen dan berbagi dengan orang yang kita cintai.
Kamera telah menjadi pusat pengalaman smartphone.
Bahkan, kamera yang bagus sering kali menjadi faktor utama saat membeli smartphone.
Hari ini, kita akan membahas dua tema umum untuk membangun pengalaman kamera premium.
Pertama, kita akan mempelajari beberapa fitur CameraX, lalu mempelajari beberapa teknik machine learning di perangkat.
Mari kita mulai dengan CameraX.
Jetpack CameraX mendukung pengalaman kamera di Android.
Selain CameraX, kami juga memiliki Camera1 dan Camera2, yang merupakan bagian dari framework platform Android.
Jadi, library mana yang harus Anda gunakan?
Camera1 adalah API kamera asli di Android.
API ini kini tidak digunakan lagi, sehingga aplikasi baru harus menggunakan Camera2 atau CameraX.
Camera2 menggantikan Camera1.
Jadi, jika Anda memerlukan kontrol kamera tingkat rendah untuk kasus penggunaan yang kompleks, Camera2 adalah opsi yang tepat.
Namun, Anda harus menangani konfigurasi khusus perangkat sendiri.
Dan terakhir, Jetpack CameraX dibuat berdasarkan Camera2.
Library ini menyediakan API yang konsisten dan menangani konfigurasi khusus perangkat secara otomatis.
Ini adalah pilihan yang direkomendasikan untuk sebagian besar developer.
Kami memiliki info yang sangat penting untuk disampaikan.
Kami berencana menonaktifkan Camera1 dan ini akan dimulai dengan penegakan kebijakan Play tahun depan di Android 18.
Jika masih menggunakan Camera1 API lama, Anda harus bermigrasi ke CameraX atau Camera2.
Jadi, mengapa Anda harus menggunakan CameraX?
Pertama, library ini mendukung Android 7 dan yang lebih baru, sehingga kompatibel dengan hampir 99% perangkat Android yang aktif.
Kedua, CameraX mudah digunakan dan menyediakan API sederhana untuk kasus penggunaan umum seperti pratinjau, pengambilan gambar, dan perekaman dengan lebih sedikit kode.
Ketiga, CameraX memberikan pengalaman yang konsisten di berbagai perangkat dengan mengurangi masalah khusus perangkat seperti peregangan pratinjau, yang cukup umum terjadi pada perangkat foldable dan tablet.
Terakhir, CameraX menyederhanakan implementasi kemampuan OEM lanjutan seperti mode malam dan potret.
Sekarang, saya ingin mengundang Scott untuk membahas beberapa fitur CameraX.
Silakan, Scott.
Terima kasih, Aman.
Halo semuanya.
Nama saya Scott.
Hari ini, kita akan membahas beberapa fitur CameraX untuk memungkinkan Anda membangun pengalaman kamera tingkat profesional.
Yang pertama adalah Jendela Bidik Adaptif.
Fitur ini dirancang untuk sepenuhnya menghilangkan kesulitan dalam menangani pratinjau di berbagai faktor bentuk dan ukuran layar.
Pengguna kini memiliki berbagai perangkat, termasuk perangkat foldable, ponsel, dan laptop, serta perangkat XR.
Jadi, membangun pengalaman kamera yang beradaptasi dengan faktor bentuk baru menjadi semakin penting.
Dan pratinjau kamera terkenal sulit untuk ditampilkan dengan benar, terutama pada perangkat foldable layar lebar.
Pada perangkat ini, saat dibentangkan, kamera dalamnya dipasang secara horizontal, sedangkan kamera belakangnya dipasang secara vertikal.
Jadi, jika Anda mengasumsikan semua sensor kamera dipasang secara vertikal, Anda akan mengalami ketidakcocokan spasial dan menyebabkan distorsi atau posisi miring.
Dan CameraXViewfinder, dirancang untuk sepenuhnya menangani kompleksitas untuk Anda, sehingga memastikan pratinjau kamera Anda berfungsi dengan lancar di semua faktor bentuk.
Mari kita lihat cara menggunakan composable CameraXViewfinder.
var surfaceRequest by remember {
mutableStateOf<SurfaceRequest?>(null)
}
LaunchedEffect(...) {
preview.setSurfaceProvider { surfaceRequest = it }
cameraProvider.bindToLifecycle(..., preview)
}
surfaceRequest?.let { request ->
CameraXViewfinder(
surfaceRequest = request,
contentScale = ContentScale.Fit
)
}Pertama, Anda mendeklarasikan variabel konten surfaceRequest untuk menyimpan permintaan platform.
Maaf.
Kedua, di LaunchedEffect, Anda menetapkan penyedia platform untuk menangkap objek permintaan platform.
Kemudian, Anda mengikat ke siklus proses, lalu memulai kamera.
Terakhir, setiap kali status diperbarui dengan permintaan platform yang valid dan memicu rekomposisi, Anda menetapkan permintaan langsung ke CameraXViewfinder.
Dan di sini, Anda dapat menyetel contentScale agar pas atau dipangkas, bergantung pada preferensi Anda.
Selesai. Anda sudah siap.
Di CameraX 1.7, kami telah menambahkan beberapa fitur baru ke CameraXViewfinder.
Hal ini mencakup gestur baru seperti ketuk untuk memfokuskan atau cubit untuk memperbesar.
Fitur ini juga mendukung Flash Layar, yang memungkinkan Anda menggunakan layar untuk mencerahkan foto selfie.
Menerapkan fitur ini sangatlah mudah.
CameraXViewfinder(
surfaceRequest = viewModel.surfaceRequest,
contentScale = ContentScale.Fit,
isTapToFocusEnabled = true,
isPinchToZoomEnabled = true,
onScreenFlashReady =
{
imageCapture.screenFlash = it
imageCapture.flashMode = FLASH_MODE_SCREEN
}
)Anda hanya perlu mengaktifkan ketuk untuk Fokus dan cubit untuk Zoom ke true.
Dan untuk Flash Layar, Anda mendapatkan instance Flash Layar dari callback onScreenFlashReady, lalu meneruskannya ke ImageCapture dan menyetel mode flash ke FLASH_MODE_SCREEN.
Selesai.
Kita telah melihat cara CameraX memungkinkan Pratinjau kamera yang berfungsi lancar di semua faktor bentuk.
Sekarang, mari kita lanjutkan dengan pengambilan gambar kamera di Android XR.
Jadi, ada tiga kategori perangkat XR: pertama, Headset XR.
Headset ini sepenuhnya tertutup dan imersif, menggunakan kamera untuk menangkap dunia fisik, dan menampilkannya di dalam headset.
Kedua, Kacamata XR Berkabel.
Kami telah mengumumkan XREAL Aura dalam keynote dalam kategori ini hari ini.
Jadi, seperti yang Anda lihat dalam keynote, ini adalah kacamata tembus pandang yang terhubung ke puck komputasi dan memungkinkan Anda melihat overlay konten virtual di dunia nyata.
Dan yang ketiga, Kacamata Pintar Audio dan Kacamata Pintar dengan Layar.
Ini adalah kacamata ringan.
Perangkat ini dapat menggabungkan audio, kamera, dan layar untuk pengalaman handsfree dan sekilas.
Dua kategori pertama, headset XR dan Kacamata XR Berkabel, juga mendukung Camera2 dan CameraX, seperti ponsel biasa.
Jadi, hari ini kita akan fokus pada kacamata pintar audio dan Kacamata Pintar dengan Layar.
Di kacamata ini, aplikasi berjalan di ponsel Android, ponsel Android host, bukan kacamata, tetapi di sini akses ke kamera ponsel dan kamera kacamata.
Pertanyaan utamanya adalah bagaimana Anda tahu kamera mana yang Anda ajak bicara?
Jadi, ini mudah.
Dengan Context standar, CameraX Anda mengakses kamera ponsel.
Dengan ProjectedDeviceContext, CameraX mengakses kamera kacamata pintar.
Jadi, Context yang berbeda akan mengarah ke kamera target yang berbeda.
Ingat, izin kamera dan kacamata pintar terpisah.
Izin ponsel dan kacamata terpisah, jadi Anda perlu meminta izin kacamata secara terpisah.
Opsi lainnya adalah menggunakan Aktivitas yang Diproyeksikan, yang juga berjalan di perangkat Android host, tetapi UI Anda diproyeksikan ke kacamata.
Dan di sini aturannya berubah.
Jika Anda menggunakan Context standar, Anda akan mengakses kamera kacamata pintar.
Jika ingin mengakses kamera ponsel, Anda harus menggunakan HostContext.
Mari kita lihat kode, lihat cara kita dapat mengambil gambar menggunakan kamera kacamata.
// In a coroutine
val imageCapture = ImageCapture.Builder().build()
ProjectedContext.isProjectedDeviceConnected(activity, coroutineContext)
.collectLatest { isConnected ->
if (isConnected) {
val projectedContext = ProjectedContext.createProjectedDeviceContext(activity)
val cameraConfig = CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
.setRepeatingStreamForced(false)
.build()
val cameraProvider = LifecycleCameraProvider.createInstance(projectedContext, cameraConfig)
cameraProvider.bindToLifecycle(activity, DEFAULT_BACK_CAMERA, imageCapture)
}
}
// Shutter button clicked
imageCapture.takePicture(...)Pertama, Anda memanggil isProjectedDeviceConnected untuk melihat apakah kacamata pintar terhubung atau tidak.
Kemudian, Anda memanggil createProjectedDeviceContext untuk mendapatkan projectedContext.
Kedua, di sini Anda menggunakan LifecycleCameraProvider untuk melakukan inisialisasi CameraX, bukan ProcessCameraProvider.
Jadi, ProcessCameraProvider adalah singleton yang tidak dapat Anda ubah Context-nya setelah inisialisasi.
Jadi, penggunaan LifecycleCameraProvider memungkinkan Anda mengubah Context kapan saja Anda mau.
Selanjutnya, Anda perlu menonaktifkan streaming berulang tambahan di CameraX.
Hal ini diperlukan karena kacamata saat ini hanya mendukung satu streaming.
API ini saat ini bersifat internal, tetapi kami akan segera membuatnya tersedia untuk publik.
Selesai.
Dari sini, Anda hanya perlu mengikat ImageCapture, dan Anda kini dapat mengambil gambar melalui kacamata pintar.
Oke.
Selanjutnya, mari kita lihat cara CameraX membantu Anda menemukan kombinasi fitur yang berfungsi bersama dan mendapatkan hasil terbaik dari perangkat.
Aplikasi kamera modern ditentukan oleh fitur canggih dan pengguna mengharapkan kamera tersebut mendukung fitur seperti HDR, 60 FPS, dan Stabilisasi Pratinjau, semuanya secara bersamaan.
Namun, sebagai developer, kami tahu bahwa menggabungkan fitur-fitur ini tidak selalu mudah.
Memeriksa dukungan fitur dukungan individual tidak menjamin bahwa fitur tersebut akan berfungsi bersama.
Ketidakpastian ini memaksa developer untuk bersikap konservatif dan membatasi pengalaman pengguna di perangkat yang mumpuni.
Untuk mengatasi hal ini, kami memperkenalkan Feature Group API, yang didukung oleh framework kueri kombinasi fitur Camera2.
Ada dua cara untuk menggunakannya: pertama, gunakan requiredFeatureGroup untuk memeriksa dan mengaktifkan kombinasi fitur jika didukung.
Kedua, Anda dapat memberikan prioritas fitur berdasarkan preferredFeatureGroup, lalu CameraX akan memilih kombinasi yang didukung terbaik untuk Anda.
Berikut contohnya.
Di sebelah kanan, di sebelah kiri, maaf, dengan mengaktifkan Nothing, hanya ponsel biasa, perekaman biasa.
Di sebelah kiri, kami mengaktifkan HDR, 60 FPS, dan Stabilisasi Pratinjau sekaligus.
Anda dapat melihat kualitasnya meningkat secara signifikan dengan video yang lebih cerah, lebih halus, dan bebas guncangan.
Mari kita lihat kodenya.
cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
// HDR_HLG10 > FPS_60 > Preview Stabilization.
preferredFeatureGroup =
listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),
)
)Jadi, di sini kita menggunakan preferredFeatureGroup untuk memberikan daftar prioritas fitur, yaitu HDR, lalu 60 FPS, dan kemudian Stabilisasi Pratinjau.
CameraX akan memeriksa kombinasi dan memilih kombinasi terbaik yang didukung oleh perangkat.
Dengan CameraX 1.6 ke atas, kami menambahkan Perekaman 4K dan Stabilisasi Video langsung ke Feature Group API.
// CameraX 1.6+ supports:
// 4K, video stabilization & Effect
val sessionConfig = SessionConfig(
useCases = listOf(preview, videoCapture),
requiredFeatureGroup =
setOf(UHD_RECORDING, VIDEO_STABILIZATION),
effects = listOf(overlayEffect)
)Penggabungan 4K dan Stabilisasi Video didukung oleh banyak perangkat premium.
Sekarang, dengan Feature Group API, Anda dapat mengaktifkannya bersama-sama dengan yakin.
Selain itu, Anda kini memiliki fleksibilitas untuk menerapkan efek real-time dengan Feature Group API, yang sebelumnya tidak dapat dilakukan.
Sekarang, mari kita bahas cara mendapatkan pengambilan gambar berkualitas tinggi di CameraX.
CameraX kini mendukung pengambilan foto RAW DNG.
Fitur ini memberi Anda akses ke gambar RAW yang tidak diproses dan tidak dikompresi langsung dari sensor kamera untuk pengeditan profesional.
Selanjutnya, kami telah meningkatkan ekstensi Mode Malam.
Ekstensi ini memungkinkan pengambilan foto yang terang dan jelas dalam kondisi cahaya redup tanpa menggunakan flash.
Kami juga telah memperkenalkan API Indikator Mode Malam baru.
API ini akan memantau kapan lingkungan saat ini gelap dan cocok untuk Mode Malam, dan Anda dapat menggunakannya untuk menampilkan indikator Mode Malam.
Dan Ultra HDR kini didukung di ekstensi CameraX.
Hal ini menghadirkan rentang dinamis yang lebih luas dan warna yang cerah ke Mode Malam, dan Mode Malam dengan Ultra HDR saat ini didukung di banyak perangkat premium terbaru.
Anda dapat melihat perbedaannya di sini antara mode normal, malam, dan Mode Malam dengan Ultra HDR.
Mari kita lihat cara mengimplementasikannya.
val cameraInfo = cameraProvider.getCameraInfo(cameraSelector,
ExtensionSessionConfig(ExtensionMode.NIGHT, extensionsManager))
val imageCapabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
if (imageCapabilities.supportedOutputFormats
.contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR)) {
setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)
}
}.build()
val extensionSessionConfig = ExtensionSessionConfig(
ExtensionMode.NIGHT, extensionsManager, preview, imageCapture
)
cameraProvider.bindToLifecycle(..., extensionSessionConfig)Pertama, buat ExtensionSessionConfig untuk Mode Malam, dan gunakan untuk mendapatkan instance CameraInfo.
Selanjutnya, Anda menggunakan CameraInfo untuk mendapatkan kemampuan pengambilan gambar, lalu membuat kueri apakah Ultra HDR didukung.
Lalu, Anda menetapkan format output ke Ultra HDR.
Terakhir, Anda membuat ExtensionSessionConfig lagi dengan kasus penggunaan, dan mengikatnya ke siklus proses.
Sekarang Anda siap mengambil foto dengan Mode Malam dan Ultra HDR.
Kami juga menghadirkan dukungan Foto Motion ke CameraX.
Foto Motion merekam suara dan gerakan di sekitar foto, sehingga mengabadikan momen, bukan hanya gambar diam.
Kami menstandarkan hal ini di berbagai ponsel dan perangkat Android, serta mempermudah dukungan Foto Motion.
Foto Motion akan hadir di CameraX pada Q1 2027.
Setelah tersedia, cukup setel mode Foto Motion di ImageCapture.Builder, dan kini Anda dapat mulai mengambil Foto Motion.
val imageCapture = ImageCapture.Builder()
.setMotionPhotoMode(
ImageCapture.MOTION_PHOTO_MODE_ON,
customConfig
)
.build()
cameraProvider.bindToLifecycle(.. imageCapture)
imageCapture.takePicture(...)Selanjutnya, mari kita pelajari cara CameraX mengaktifkan perekaman video berkecepatan tinggi.
Merekam aksi yang bergerak cepat dengan jelas adalah fitur penting yang dimiliki aplikasi kamera modern.
Mode ini sangat berguna untuk skenario yang bergerak cepat seperti olahraga.
Hal ini dicapai melalui pengambilan gambar berkecepatan tinggi pada 120 atau 240 fps.
Ada dua cara untuk menggunakannya.
Pertama, encoding pada kecepatan frame yang sama, lalu Anda akan membuat video dengan kecepatan frame tinggi yang sebenarnya.
Opsi lainnya adalah mengenkode video pada 30 fps untuk membuat video slow-motion yang siap diputar.
Misalnya, satu detik yang direkam pada 120 fps memerlukan waktu empat detik untuk diputar pada 30 fps.
Jadi, rentang waktu ini menciptakan efek gerak lambat.
Dan untuk menerapkan perekaman kecepatan tinggi, Anda membuat HighSpeedVideoSessionConfig dengan videoCapture.
val recorder = Recorder.Builder().build()
val videoCapture = VideoCapture.withOutput(recorder)
val frameRateRange = cameraInfo.getSupportedFrameRateRanges(
HighSpeedVideoSessionConfig(videoCapture, preview)).first()
val sessionConfig = HighSpeedVideoSessionConfig(
videoCapture,
preview,
frameRateRange = frameRateRange,
isSlowMotionEnabled = true
)
cameraProvider.bindToLifecycle(
lifecycleOwner, cameraSelector, sessionConfig)
// Start recording slow motion videos.
val recording = recorder.prepareRecording(context, outputOption)
.start(executor, {})Kemudian, Anda menetapkan isSlowMotionEnabled ke true untuk mengenkode video pada 30 fps guna membuat video slow-motion, atau menetapkannya ke false untuk membuat video dengan kecepatan frame tinggi.
Dan saat mode slow motion diaktifkan, Google Foto akan otomatis mengidentifikasinya, dan menambahkan badge slow motion ke thumbnail.
Mari kita lihat cara kerjanya di Google Foto.
Di sini, gerak lambat memberikan efek dramatis pada kucing tersebut.
Kucing saya tidak pernah mau saya sentuh.
Maaf.
Terakhir, mari kita lihat beberapa peningkatan dalam API serentak, Concurrent Camera API.
API serentak memungkinkan aplikasi Anda melakukan streaming dari kamera depan dan belakang secara bersamaan.
Tahun ini, kami memperkenalkan beberapa peningkatan pada Concurrent Camera API.
Anda dapat memperbarui komposisi kamera secara dinamis setelah mengikat ke siklus proses dan membuka kamera.
Jadi, ini termasuk mengubah posisi, ukuran, dan urutan rendering.
Anda juga dapat menambahkan gaya seperti sudut membulat, atau lebar batas, dan warna batas.
Berikut caranya: cukup gunakan CompositionSettings untuk mengonfigurasi gaya seperti sudut membulat, lebar batas, dan warna, serta gunakan setZOrder untuk menyesuaikan urutan rendering.
val concurrentCamera =
cameraProvider.bindToLifecycle(list(config1, config2))
// CameraX 1.7 features: rounded corner, border width & color
val pipSettings = CompositionSettings.Builder()
.setOffset(0.2f, 0.2f)
.setScale(0.35f, 0.35f)
.setRoundedCornerRatio(0.15f)
.setBorderWidthRatio(0.02f)
.setBorderColor(Color.WHITE)
.setZOrder(1)
.build()
// CameraX 1.7 features: dynamical composition update
concurrentCamera.setCompositionSettings(
listOf(mainSettings, pipSettings))Selanjutnya, Anda cukup memanggil setCompositionSettings pada kamera serentak yang aktif untuk memperbarui komposisi secara dinamis.
Selesai.
Anda dapat melanjutkan untuk memperbarui komposisi secara dinamis.
Oke.
Sekarang kita telah membahas semua fitur.
Kami memiliki info penting di sini, jadi sebaiknya Anda mengupgrade ke CameraX 1.6 dan yang lebih baru.
Hal ini dapat menghindari error pada perangkat mendatang yang mendukung format baru, Video Eclipsa, dan juga memastikan ekstensi CameraX Anda terus berfungsi pada update Pixel mendatang.
Dengan demikian, kita mengakhiri sesi pertama.
Kita telah membahas fitur CameraX yang membantu Anda membangun pengalaman kamera tingkat profesional, dan sekarang saya ingin mengundang Aman untuk membahas sesi berikutnya tentang AI di perangkat.
Terima kasih, Scott, telah menjelaskan fitur CameraX kepada kami.
Sekarang, mari kita lihat cara memanfaatkan Machine Learning Di Perangkat untuk membangun pengalaman kamera yang cerdas.
Machine learning di perangkat memungkinkan berbagai kasus penggunaan kamera di dua area utama.
Pertama adalah pra-pengambilan.
Di sini, Anda dapat menganalisis pratinjau kamera secara real time untuk melakukan hal-hal seperti deteksi objek atau Anda dapat meningkatkan kualitas pratinjau itu sendiri.
Kedua adalah pasca-pengambilan.
Setelah mengambil gambar, Anda dapat menyempurnakan kualitasnya atau melakukan hal-hal seperti membuat deskripsi untuk gambar tersebut.
Sekarang, mari kita pelajari beberapa solusi machine learning di perangkat yang kami miliki untuk aplikasi kamera Anda.
Library ML di perangkat pertama yang akan kita bahas adalah ML Kit.
ML Kit utamanya dibuat untuk menyelesaikan masalah umum dalam domain visi dan natural language seperti pengenalan teks, deteksi wajah, dan terjemahan bahasa.
Tahun lalu, kami memperkenalkan ML Kit.
Berikut beberapa contoh Vision API ML Kit, misalnya deteksi mesh wajah, segmentasi subjek, dan deteksi objek real-time.
Ya.
Tahun lalu, kami memperkenalkan API GenAI.
API ini memanfaatkan kecanggihan Gemini Nano untuk mengaktifkan kemampuan seperti ringkasan teks, deskripsi gambar, dan banyak lagi.
Berikut adalah contoh deskripsi gambar menggunakan Prompt API.
Kami meneruskan bitmap gambar dengan perintah teks ke model, dan deskripsi hasilnya berbunyi robot Android kecil berwarna hijau dengan desain seperti kaktus yang duduk di permukaan hitam.
Dan semua ini terjadi di perangkat.
Cukup keren, bukan?
Adobe Photoshop telah menggunakan Prompt API untuk meningkatkan pengalaman pengguna di aplikasinya.
Saat mengedit aset, pengguna sering kali harus mengelola beberapa lapisan di aplikasi Photoshop.
Dengan menggunakan Prompt API, aplikasi kini dapat otomatis mengganti nama lapisan yang tidak teratur.
Aplikasi ini juga menggunakan Prompt API untuk membuat teks dan hashtag untuk gambar, yang cukup berguna untuk dibagikan di media sosial.
Mari kita lihat kode untuk deskripsi gambar menggunakan Prompt API.
// 1. Initialize the on-device GenerativeModel client
val generativeModel = Generation.getClient()
// 2. Check whether Gemini Nano is available on the device
val status = generativeModel.checkStatus()
when (status) {
FeatureStatus.UNAVAILABLE -> {}
FeatureStatus.DOWNLOADABLE -> {}
FeatureStatus.DOWNLOADING -> {}
FeatureStatus.AVAILABLE -> {}
}Pertama, Anda memerlukan objek klien generativeModel, lalu periksa apakah Gemini Nano tersedia atau dapat didownload di perangkat Anda.
Selanjutnya, buat permintaan konten dengan menggabungkan gambar dan perintah teks, lalu berikan permintaan ini ke panggilan generateContent untuk menjalankan inferensi di Gemini Nano dan mendapatkan deskripsi gambar Anda.
// 3. Build a multimodal request with the image and text prompt
val request = generateContentRequest(
ImagePart(bitmap),
TextPart("Describe this image in detail.")
) {}
// 4. Run inference on-device and get the description
val response = generativeModel.generateContent(request)
val description = response.candidates.first().textYa, library ML di perangkat berikutnya yang kami miliki adalah MediaPipe.
MediaPipe menawarkan berbagai solusi machine learning untuk aplikasi Anda.
Anda dapat dengan cepat mengunjungi situs MediaPipe untuk mencoba berbagai contoh seperti deteksi wajah, deteksi objek, segmentasi gambar, dan banyak lagi.
Semua kasus penggunaan ini terdengar sangat mirip dengan ML Kit, jadi library mana yang harus Anda gunakan?
Meskipun MediaPipe dan ML Kit menyelesaikan masalah yang serupa, ada beberapa perbedaan utama.
Pertama adalah dukungan platform.
MediaPipe berfungsi di Android, iOS, Web, dan Python, sedangkan ML Kit hanya berfokus pada Android dan iOS.
Selanjutnya, MediaPipe menawarkan penyesuaian model, sedangkan ML Kit menyediakan API siap pakai.
Terakhir, meskipun MediaPipe bersifat open source, ML Kit adalah SDK Google.
Berikut adalah contoh pengenalan gestur menggunakan MediaPipe Vision API.
API ini mendeteksi gestur tangan secara real time dari input kamera.
Misalnya, fitur ini dapat digunakan untuk memulai atau menghentikan perekaman kamera menggunakan gestur tangan sederhana saat berdiri agak jauh dari ponsel.
Mari kita lihat kodenya.
Jadi, pertama-tama, Anda perlu membangun objek GestureRecognizerOptions, dengan memberikan jalur model, mode live streaming, dan pemroses hasil.
// 1. Build GestureRecognizerOptions
val options = GestureRecognizerOptions.builder().setBaseOptions(
BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK).build())
.setRunningMode(RunningMode.LIVE_STREAM)
.setResultListener { result, image -> /* Handle detected gesture */ }
.build()
// 2. Create the GestureRecognizer
val gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
// 3. Convert CameraX ImageProxy to MediaPipe MPImage
val bitmap = rotateBitmap(imageProxy.toBitmap(),
imageProxy.imageInfo.rotationDegrees)
val mpImage = BitmapImageBuilder(bitmap).build()
// 4. Run gesture recognition on the image
gestureRecognizer.recognizeAsync(mpImage, frameTime)Kemudian, buat objek pengenal gestur dari opsi tersebut.
Selanjutnya, dapatkan ImageProxy CameraX dan konversikan menjadi bitmap, lalu gunakan bitmap tersebut untuk membuat objek mpImage MediaPipe.
Terakhir, Anda perlu menyediakan objek mpImage MediaPipe ke panggilan recognizeAsync untuk mendeteksi gestur secara real-time.
Selanjutnya, kami memiliki fitur Peningkatan Gambar dan Video di Perangkat yang tersedia melalui API layanan Google Play.
Model ini memberikan kemampuan seperti pemetaan warna, penghilangan blur, dan Resolusi Super di sebagian besar perangkat premium.
Berikut adalah contoh gambar yang dipetakan nuansanya dan ditingkatkan resolusinya menggunakan model ini.
Anda dapat melihat dengan jelas warna yang lebih kaya di langit dan laut serta ketajaman yang lebih baik pada gambar yang ditingkatkan kualitasnya.
Mari kita lihat kode untuk Penyempurnaan Gambar.
// Step 1: Verify device support & install module
val enhancementClient = Enhancement.getClient(context)
suspend fun prepare(): Boolean {
if (!enhancementClient.isDeviceSupported().await()) return false
if (!enhancementClient.isModuleInstalled().await()) {
check(enhancementClient.installModule().await()) {
"Enhancement module install failed"
}
}
return true
}Pertama, Anda perlu mengkueri apakah perangkat yang mendasarinya mendukungnya atau tidak, dan jika perlu, Anda perlu menginstal modul peningkatan di perangkat Anda.
Selanjutnya, buat objek EnhancementOptions dengan menentukan bitmap dan peningkatan kualitas yang ingin Anda pilih.
// Step 2: Select Enhancement options & create session
val options = EnhancementOptions(
width = bitmap.width,
height = bitmap.height,
enhancementMode = EnhancementMode.BITMAP,
isTonemappingEnabled = true,
isDeblurAndDenoisePhotoEnabled = true,
isDeblurAndDenoiseVideoEnabled = false,
isUpscalePhotoEnabled = false,
isUpscaleVideoEnabled = false
)
val enhancementSession = enhancementClient
.createSessionAsync(options, enhancementExecutor)Selanjutnya, buat sesi klien dengan Google Play services API, lalu tentukan callback untuk menangani bitmap yang dihasilkan, dan terakhir panggil fungsi proses dengan bitmap dan opsi untuk meningkatkan kualitas gambar Anda.
// Step 3: Process Enhancement
val enhancedBitmap = suspendCancellableCoroutine { continuation ->
val enhancementCallback = object : EnhancementCallback {
override fun onBitmapProcessed(result: Bitmap) {
if (continuation.isActive) continuation.resume(result)
}
override fun onError(statusCode: Int) {
if (continuation.isActive) {
continuation.resumeWithException(
Exception("Bitmap processing failed: $statusCode")
)
}
}
override fun onSurfaceProcessed(timestamp: Long) {}
}
enhancementSession.process(bitmap, options, enhancementCallback)
}Baru-baru ini, kami telah mengintegrasikan Video Enhancement API ke dalam Jetpack Media3.
Anda dapat melihat diskusi media kami untuk mempelajari lebih lanjut Image and Video Enhancement API.
Fitur ML Di Perangkat terakhir yang akan kita bahas adalah Peningkatan Cahaya Redup.
Mengambil foto dalam kondisi cahaya redup adalah masalah umum bagi pengguna smartphone.
Bayangkan pengguna yang mengambil gambar atau melakukan panggilan video di lingkungan yang remang-remang.
Mode Pencahayaan Rendah mengatasi masalah ini dengan mencerahkan pratinjau kamera Anda secara real-time.
Ada dua varian Low Light Boost: hardware dan software.
Versi hardware menggunakan hardware OEM untuk meningkatkan kualitas frame yang remang-remang tanpa menggunakan machine learning.
Sebaliknya, versi software menggunakan model ML Di Perangkat untuk meningkatkan kualitas frame.
Mari kita lihat sekilas cara mengintegrasikan CameraX dengan Software Peningkatan Cahaya Redup, yang juga dikenal sebagai Peningkatan Cahaya Redup Google.
Google Low Light Boost memerlukan dua platform utama: pertama, Anda memerlukan platform input untuk frame kamera mentah dan platform target output untuk frame output yang ditingkatkan.
Untuk berintegrasi dengan CameraX, cukup gabungkan pipeline Google Low Light Boost di dalam CameraEffect.
CameraX otomatis menangani siklus proses dan pemilihan rute platform dengan lancar untuk Anda.
Terakhir, kami akan meluncurkan Efek Peningkatan Cahaya Redup di CameraX pada kuartal keempat tahun 2026.
// Integrates SW Low Light Boost
val lowLightBoostEffect =
LowLightBoostEffect(
CameraEffect.PREVIEW or
CameraEffect.VIDEO_CAPTURE or
CameraEffect.IMAGE_CAPTURE
)
val sessionConfig = SessionConfig(
useCases = listOf(preview, imageCapture),
effects = lowLightBoostEffect
)
cameraProvider.bindToLifecycle(.. sessionConfig)Dengan begitu, Anda dapat membuat objek Low Light Boost dan menambahkannya ke konfigurasi sesi, lalu mengikat konfigurasi sesi ke siklus proses kamera, dan fitur ini akan langsung berfungsi di perangkat yang didukung.
Kita telah sampai di akhir kedua bagian tersebut.
Mari kita rangkum dengan cepat semua yang telah kita bahas hari ini.
Hari ini, kita membahas cara meningkatkan pengalaman kamera di berbagai perangkat dengan CameraX dan machine learning di perangkat.
Pertama, dengan CameraXViewfinder, Anda dapat mengaktifkan pratinjau kamera untuk beradaptasi dengan berbagai faktor bentuk.
Selanjutnya, kita melihat bahwa CameraX memungkinkan Anda mengambil gambar di perangkat XR juga.
Kemudian, Feature Group API membantu Anda menemukan kombinasi fitur hardware yang optimal.
Kita juga telah mempelajari upgrade pada Pengambilan Gambar dan mempelajari Perekaman Video Kecepatan Tinggi untuk video gerak lambat.
Terakhir, kita mempelajari cara meningkatkan pratinjau Kamera Serentak secara dinamis.
Selanjutnya, kita membahas beberapa solusi machine learning di perangkat seperti ML Kit dan MediaPipe untuk membangun pengalaman vision yang cerdas.
Terakhir, kami melihat Peningkatan Kualitas Gambar dan Video di perangkat serta Peningkatan Cahaya Redup untuk mencerahkan pratinjau kamera Anda secara real-time.
Seperti yang disebutkan sebelumnya, kami berencana untuk menonaktifkan Camera1, sehingga kami sangat menyarankan Anda untuk bermigrasi ke CameraX.
Untuk mendukung migrasi ini, kami baru-baru ini meluncurkan keterampilan CameraX.
Kami juga memiliki panduan migrasi dan repositori contoh kamera untuk memandu Anda.
Anda dapat membuka link ini untuk mengakses referensi lainnya tentang fitur yang kita bahas hari ini.
Halaman ini menyertakan link ke dokumentasi, blog, referensi migrasi, semuanya di satu tempat.
Saya akan berhenti sejenak.
Oke.
Terima kasih, semuanya.
Kita sudah berada di penghujung diskusi.
var surfaceRequest by remember {
mutableStateOf<SurfaceRequest?>(null)
}
LaunchedEffect(...) {
preview.setSurfaceProvider { surfaceRequest = it }
cameraProvider.bindToLifecycle(..., preview)
}
surfaceRequest?.let { request ->
CameraXViewfinder(
surfaceRequest = request,
contentScale = ContentScale.Fit
)
}CameraXViewfinder(
surfaceRequest = viewModel.surfaceRequest,
contentScale = ContentScale.Fit,
isTapToFocusEnabled = true,
isPinchToZoomEnabled = true,
onScreenFlashReady =
{
imageCapture.screenFlash = it
imageCapture.flashMode = FLASH_MODE_SCREEN
}
)// In a coroutine
val imageCapture = ImageCapture.Builder().build()
ProjectedContext.isProjectedDeviceConnected(activity, coroutineContext)
.collectLatest { isConnected ->
if (isConnected) {
val projectedContext = ProjectedContext.createProjectedDeviceContext(activity)
val cameraConfig = CameraXConfig.Builder.fromConfig(Camera2Config.defaultConfig())
.setRepeatingStreamForced(false)
.build()
val cameraProvider = LifecycleCameraProvider.createInstance(projectedContext, cameraConfig)
cameraProvider.bindToLifecycle(activity, DEFAULT_BACK_CAMERA, imageCapture)
}
}
// Shutter button clicked
imageCapture.takePicture(...)cameraProvider.bindToLifecycle(
lifecycleOwner,
cameraSelector,
SessionConfig(
useCases = listOf(preview, videoCapture),
// HDR_HLG10 > FPS_60 > Preview Stabilization.
preferredFeatureGroup =
listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),
)
)// CameraX 1.6+ supports:
// 4K, video stabilization & Effect
val sessionConfig = SessionConfig(
useCases = listOf(preview, videoCapture),
requiredFeatureGroup =
setOf(UHD_RECORDING, VIDEO_STABILIZATION),
effects = listOf(overlayEffect)
)val cameraInfo = cameraProvider.getCameraInfo(cameraSelector,
ExtensionSessionConfig(ExtensionMode.NIGHT, extensionsManager))
val imageCapabilities = ImageCapture.getImageCaptureCapabilities(cameraInfo)
val imageCapture = ImageCapture.Builder().apply {
if (imageCapabilities.supportedOutputFormats
.contains(OUTPUT_FORMAT_JPEG_ULTRA_HDR)) {
setOutputFormat(OUTPUT_FORMAT_JPEG_ULTRA_HDR)
}
}.build()
val extensionSessionConfig = ExtensionSessionConfig(
ExtensionMode.NIGHT, extensionsManager, preview, imageCapture
)
cameraProvider.bindToLifecycle(..., extensionSessionConfig)val imageCapture = ImageCapture.Builder()
.setMotionPhotoMode(
ImageCapture.MOTION_PHOTO_MODE_ON,
customConfig
)
.build()
cameraProvider.bindToLifecycle(.. imageCapture)
imageCapture.takePicture(...)val recorder = Recorder.Builder().build()
val videoCapture = VideoCapture.withOutput(recorder)
val frameRateRange = cameraInfo.getSupportedFrameRateRanges(
HighSpeedVideoSessionConfig(videoCapture, preview)).first()
val sessionConfig = HighSpeedVideoSessionConfig(
videoCapture,
preview,
frameRateRange = frameRateRange,
isSlowMotionEnabled = true
)
cameraProvider.bindToLifecycle(
lifecycleOwner, cameraSelector, sessionConfig)
// Start recording slow motion videos.
val recording = recorder.prepareRecording(context, outputOption)
.start(executor, {})val concurrentCamera =
cameraProvider.bindToLifecycle(list(config1, config2))
// CameraX 1.7 features: rounded corner, border width & color
val pipSettings = CompositionSettings.Builder()
.setOffset(0.2f, 0.2f)
.setScale(0.35f, 0.35f)
.setRoundedCornerRatio(0.15f)
.setBorderWidthRatio(0.02f)
.setBorderColor(Color.WHITE)
.setZOrder(1)
.build()
// CameraX 1.7 features: dynamical composition update
concurrentCamera.setCompositionSettings(
listOf(mainSettings, pipSettings))// 1. Initialize the on-device GenerativeModel client
val generativeModel = Generation.getClient()
// 2. Check whether Gemini Nano is available on the device
val status = generativeModel.checkStatus()
when (status) {
FeatureStatus.UNAVAILABLE -> {}
FeatureStatus.DOWNLOADABLE -> {}
FeatureStatus.DOWNLOADING -> {}
FeatureStatus.AVAILABLE -> {}
}// 3. Build a multimodal request with the image and text prompt
val request = generateContentRequest(
ImagePart(bitmap),
TextPart("Describe this image in detail.")
) {}
// 4. Run inference on-device and get the description
val response = generativeModel.generateContent(request)
val description = response.candidates.first().text// 1. Build GestureRecognizerOptions
val options = GestureRecognizerOptions.builder().setBaseOptions(
BaseOptions.builder().setModelAssetPath(MP_RECOGNIZER_TASK).build())
.setRunningMode(RunningMode.LIVE_STREAM)
.setResultListener { result, image -> /* Handle detected gesture */ }
.build()
// 2. Create the GestureRecognizer
val gestureRecognizer = GestureRecognizer.createFromOptions(context, options)
// 3. Convert CameraX ImageProxy to MediaPipe MPImage
val bitmap = rotateBitmap(imageProxy.toBitmap(),
imageProxy.imageInfo.rotationDegrees)
val mpImage = BitmapImageBuilder(bitmap).build()
// 4. Run gesture recognition on the image
gestureRecognizer.recognizeAsync(mpImage, frameTime)// Step 1: Verify device support & install module
val enhancementClient = Enhancement.getClient(context)
suspend fun prepare(): Boolean {
if (!enhancementClient.isDeviceSupported().await()) return false
if (!enhancementClient.isModuleInstalled().await()) {
check(enhancementClient.installModule().await()) {
"Enhancement module install failed"
}
}
return true
}// Step 2: Select Enhancement options & create session
val options = EnhancementOptions(
width = bitmap.width,
height = bitmap.height,
enhancementMode = EnhancementMode.BITMAP,
isTonemappingEnabled = true,
isDeblurAndDenoisePhotoEnabled = true,
isDeblurAndDenoiseVideoEnabled = false,
isUpscalePhotoEnabled = false,
isUpscaleVideoEnabled = false
)
val enhancementSession = enhancementClient
.createSessionAsync(options, enhancementExecutor)// Step 3: Process Enhancement
val enhancedBitmap = suspendCancellableCoroutine { continuation ->
val enhancementCallback = object : EnhancementCallback {
override fun onBitmapProcessed(result: Bitmap) {
if (continuation.isActive) continuation.resume(result)
}
override fun onError(statusCode: Int) {
if (continuation.isActive) {
continuation.resumeWithException(
Exception("Bitmap processing failed: $statusCode")
)
}
}
override fun onSurfaceProcessed(timestamp: Long) {}
}
enhancementSession.process(bitmap, options, enhancementCallback)
}// Integrates SW Low Light Boost
val lowLightBoostEffect =
LowLightBoostEffect(
CameraEffect.PREVIEW or
CameraEffect.VIDEO_CAPTURE or
CameraEffect.IMAGE_CAPTURE
)
val sessionConfig = SessionConfig(
useCases = listOf(preview, imageCapture),
effects = lowLightBoostEffect
)
cameraProvider.bindToLifecycle(.. sessionConfig)