Anda dapat menggunakan feed kamera yang ditangkap ARCore dalam pipeline machine learning untuk menciptakan pengalaman augmented reality yang cerdas. Contoh ARCore ML Kit menunjukkan cara menggunakan ML Kit dan Google Cloud Vision API untuk mengidentifikasi objek dunia nyata. Sampel ini menggunakan model machine learning untuk mengklasifikasikan objek dalam tampilan kamera dan melampirkan label ke objek dalam adegan virtual.
Contoh ARCore ML Kit adalah yang ditulis dalam Kotlin. Alat ini juga tersedia sebagai sampel ml_kotlin di ARCore SDK repositori GitHub ASL.
Menggunakan image CPU ARCore
ARCore menangkap setidaknya dua set aliran gambar secara default:
- Aliran gambar CPU yang digunakan untuk pengenalan fitur dan pemrosesan gambar. Secara default, gambar CPU memiliki resolusi VGA (640x480). ARCore dapat dikonfigurasi untuk menggunakan streaming gambar beresolusi lebih tinggi, jika diperlukan.
- Streaming tekstur GPU, yang berisi tekstur resolusi tinggi, biasanya pada resolusi 1080p. Ini biasanya digunakan sebagai pratinjau kamera yang ditampilkan kepada pengguna.
Class ini disimpan dalam tekstur OpenGL yang ditentukan oleh
Session.setCameraTextureName()
. - Streaming tambahan apa pun yang ditentukan oleh
SharedCamera.setAppSurfaces()
.
Pertimbangan ukuran image CPU
Tidak ada biaya tambahan yang dikenakan jika streaming CPU default berukuran VGA digunakan karena ARCore menggunakan streaming ini untuk mendapatkan pemahaman dunia. Meminta streaming dengan resolusi berbeda mungkin mahal, karena streaming tambahan perlu direkam. Perlu diingat bahwa resolusi yang lebih tinggi bisa cepat habis untuk model Anda: menggandakan lebar dan tinggi gambar akan menambah jumlah piksel sebanyak empat kali lipat pada gambar.
Hal ini mungkin akan menguntungkan untuk memperkecil gambar, jika model Anda masih dapat berperforma baik pada gambar beresolusi lebih rendah.
Mengonfigurasi streaming gambar CPU beresolusi tinggi tambahan
Performa model ML Anda mungkin bergantung pada resolusi gambar yang digunakan sebagai input. Resolusi streaming ini dapat disesuaikan dengan mengubah CameraConfig
saat ini menggunakan Session.setCameraConfig()
, dengan memilih konfigurasi yang valid dari Session.getSupportedCameraConfigs()
.
Java
CameraConfigFilter cameraConfigFilter = new CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK); List<CameraConfig> supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter); // Select an acceptable configuration from supportedCameraConfigs. CameraConfig cameraConfig = selectCameraConfig(supportedCameraConfigs); session.setCameraConfig(cameraConfig);
Kotlin
val cameraConfigFilter = CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK) val supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter) // Select an acceptable configuration from supportedCameraConfigs. val cameraConfig = selectCameraConfig(supportedCameraConfigs) session.setCameraConfig(cameraConfig)
Mengambil image CPU
Ambil image CPU menggunakan Frame.acquireCameraImage()
.
Gambar ini harus dibuang segera setelah tidak diperlukan lagi.
Java
Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); // Process `cameraImage` using your ML inference model. } catch (NotYetAvailableException e) { // NotYetAvailableException is an exception that can be expected when the camera is not ready // yet. The image may become available on a next frame. } catch (RuntimeException e) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e); } finally { if (cameraImage != null) { cameraImage.close(); } }
Kotlin
// NotYetAvailableException is an exception that can be expected when the camera is not ready yet. // Map it to `null` instead, but continue to propagate other errors. fun Frame.tryAcquireCameraImage() = try { acquireCameraImage() } catch (e: NotYetAvailableException) { null } catch (e: RuntimeException) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e) } // The `use` block ensures the camera image is disposed of after use. frame.tryAcquireCameraImage()?.use { image -> // Process `image` using your ML inference model. }
Memproses image CPU
Untuk memproses image CPU, berbagai library machine learning dapat digunakan.
- ML Kit: ML Kit menyediakan Deteksi dan Pelacakan Objek API di perangkat.
Model ini dilengkapi dengan pengklasifikasi umum yang terintegrasi dalam API, dan juga dapat menggunakan model klasifikasi kustom untuk mencakup domain objek yang lebih sempit.
Gunakan
InputImage.fromMediaImage
untuk mengonversi image CPU menjadiInputImage
. - Firebase Machine Learning: Firebase menyediakan Machine Learning API yang berfungsi di cloud atau di perangkat. Baca artikel Dokumentasi Firebase tentang Memberi Label pada Gambar secara Aman dengan Cloud Vision menggunakan Firebase Auth dan Functions di Android.
Menampilkan hasil dalam scene AR
Model pengenalan citra sering kali menghasilkan objek yang terdeteksi dengan menunjukkan titik tengah atau poligon pembatas yang mewakili objek yang terdeteksi.
Dengan menggunakan titik tengah atau bagian tengah kotak pembatas yang dihasilkan dari model, Anda dapat memasang anchor ke objek yang terdeteksi. Gunakan Frame.hitTest()
untuk memperkirakan pose objek di adegan virtual.
Konversi koordinat IMAGE_PIXELS
menjadi koordinat VIEW
:
Java
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. float[] cpuCoordinates = new float[] {mlResult.getX(), mlResult.getY()}; float[] viewCoordinates = new float[2]; frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates); // `viewCoordinates` now contains coordinates suitable for hit testing.
Kotlin
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. val cpuCoordinates = floatArrayOf(mlResult.x, mlResult.y) val viewCoordinates = FloatArray(2) frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates ) // `viewCoordinates` now contains coordinates suitable for hit testing.
Gunakan koordinat VIEW
ini untuk melakukan hit test dan membuat anchor dari hasil:
Java
List<HitResult> hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]); HitResult depthPointResult = null; for (HitResult hit : hits) { if (hit.getTrackable() instanceof DepthPoint) { depthPointResult = hit; break; } } if (depthPointResult != null) { Anchor anchor = depthPointResult.getTrackable().createAnchor(depthPointResult.getHitPose()); // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Kotlin
val hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]) val depthPointResult = hits.filter { it.trackable is DepthPoint }.firstOrNull() if (depthPointResult != null) { val anchor = depthPointResult.trackable.createAnchor(depthPointResult.hitPose) // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Pertimbangan performa
Ikuti rekomendasi berikut untuk menghemat daya pemrosesan dan mengonsumsi lebih sedikit energi:
- Jangan menjalankan model ML Anda pada setiap frame yang masuk. Sebaiknya jalankan deteksi objek pada kecepatan frame rendah.
- Pertimbangkan model inferensi ML online untuk mengurangi kompleksitas komputasi.
Langkah berikutnya
- Pelajari Praktik Terbaik untuk Engineering ML.
- Pelajari praktik Responsible AI.
- Ikuti kursus dasar-dasar machine learning dengan TensorFlow.