Anda dapat menggunakan ML Kit untuk mendeteksi wajah dalam gambar dan video.
Fitur | Tidak Dipaketkan | Paket |
---|---|---|
Penerapan | Model didownload secara dinamis melalui Layanan Google Play. | Model ditautkan secara statis ke aplikasi Anda pada waktu build. |
Ukuran aplikasi | Peningkatan ukuran sekitar 800 KB. | Peningkatan ukuran sekitar 6,9 MB. |
Waktu inisialisasi | Mungkin harus menunggu model didownload sebelum penggunaan pertama. | Model akan segera tersedia |
Cobalah
- Silakan coba aplikasi contoh untuk melihat contoh penggunaan API ini.
- Coba kode sendiri dengan codelab.
Sebelum memulai
Dalam file
build.gradle
level project, pastikan Anda menyertakan repositori Maven Google di bagianbuildscript
danallprojects
.Tambahkan dependensi untuk library Android ML Kit ke file gradle level aplikasi modul Anda, biasanya
app/build.gradle
. Pilih salah satu dependensi berikut berdasarkan kebutuhan Anda:Untuk memaketkan model dengan aplikasi Anda:
dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:face-detection:16.1.5' }
Untuk menggunakan model di Layanan Google Play:
dependencies { // ... // Use this dependency to use the dynamically downloaded model in Google Play Services implementation 'com.google.android.gms:play-services-mlkit-face-detection:17.1.0' }
Jika memilih untuk menggunakan model ini di Layanan Google Play, Anda dapat mengonfigurasi aplikasi agar otomatis mendownload model ke perangkat setelah aplikasi diinstal dari Play Store. Untuk melakukannya, tambahkan deklarasi berikut ke file
AndroidManifest.xml
aplikasi Anda:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="face" > <!-- To use multiple models: android:value="face,model2,model3" --> </application>
Anda juga dapat secara eksplisit memeriksa ketersediaan model dan meminta download melalui ModuleInstallClient API layanan Google Play.
Jika Anda tidak mengaktifkan download model waktu-instal atau meminta download eksplisit, model akan didownload saat pertama kali Anda menjalankan detektor. Permintaan yang Anda buat sebelum download selesai tidak memberikan hasil apa pun.
Panduan gambar input
Untuk pengenalan wajah, Anda harus menggunakan gambar dengan dimensi minimal 480x360 piksel. Agar ML Kit dapat secara akurat mendeteksi wajah, gambar input harus berisi wajah yang diwakili oleh data piksel yang cukup. Secara umum, setiap wajah yang ingin Anda deteksi dalam gambar harus berukuran minimal 100x100 piksel. Jika Anda ingin mendeteksi kontur wajah, ML Kit memerlukan input resolusi lebih tinggi: setiap wajah harus berukuran minimal 200x200 piksel.
Jika mendeteksi wajah dalam aplikasi real-time, Anda mungkin perlu mempertimbangkan dimensi gambar input secara keseluruhan. Gambar yang lebih kecil dapat diproses lebih cepat. Jadi, untuk mengurangi latensi, ambil gambar dengan resolusi lebih rendah, tetapi perhatikan persyaratan akurasi di atas dan pastikan bahwa wajah subjek menempati gambar seluas mungkin. Lihat juga tips untuk meningkatkan performa real-time.
Fokus gambar yang buruk juga dapat memengaruhi akurasi. Jika tidak memperoleh hasil yang dapat diterima, minta pengguna untuk mengambil ulang gambar.
Orientasi wajah terhadap kamera juga dapat memengaruhi fitur wajah yang terdeteksi oleh ML Kit. Baca Konsep Deteksi Wajah.
1. Mengonfigurasi detektor wajah
Jika ingin mengubah salah satu setelan default detektor wajah sebelum menerapkan deteksi wajah ke suatu gambar, tentukan setelan tersebut dengan objekFaceDetectorOptions
.
Anda dapat mengubah setelan berikut:
Setelan | |
---|---|
setPerformanceMode
|
PERFORMANCE_MODE_FAST (default)
|
PERFORMANCE_MODE_ACCURATE
Mendukung kecepatan atau akurasi saat mendeteksi wajah. |
setLandmarkMode
|
LANDMARK_MODE_NONE (default)
|
LANDMARK_MODE_ALL
Mencoba mengidentifikasi "landmark" wajah: mata, telinga, hidung, pipi, mulut, dan sebagainya. |
setContourMode
|
CONTOUR_MODE_NONE (default)
|
CONTOUR_MODE_ALL
Apakah akan mendeteksi kontur fitur wajah atau tidak. Kontur dideteksi hanya untuk wajah yang paling tampil beda dalam suatu gambar. |
setClassificationMode
|
CLASSIFICATION_MODE_NONE (default)
|
CLASSIFICATION_MODE_ALL
Apakah akan mengklasifikasikan wajah ke dalam beberapa kategori, seperti "tersenyum" dan "mata terbuka". |
setMinFaceSize
|
float (default: 0.1f )
Menetapkan ukuran wajah terkecil yang diinginkan, yang dinyatakan sebagai rasio lebar kepala dengan lebar gambar. |
enableTracking
|
false (default) | true
Menetapkan ID pada wajah atau tidak, yang dapat digunakan untuk melacak wajah di seluruh gambar. Perhatikan bahwa ketika deteksi kontur diaktifkan, hanya satu wajah yang terdeteksi, sehingga pelacakan wajah tidak memberikan hasil yang berguna. Karena alasan ini, dan untuk meningkatkan kecepatan deteksi, jangan aktifkan deteksi kontur dan pelacakan wajah secara bersamaan. |
Contoh:
Kotlin
// High-accuracy landmark detection and face classification val highAccuracyOpts = FaceDetectorOptions.Builder() .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE) .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) .build() // Real-time contour detection val realTimeOpts = FaceDetectorOptions.Builder() .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) .build()
Java
// High-accuracy landmark detection and face classification FaceDetectorOptions highAccuracyOpts = new FaceDetectorOptions.Builder() .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE) .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) .build(); // Real-time contour detection FaceDetectorOptions realTimeOpts = new FaceDetectorOptions.Builder() .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) .build();
2. Menyiapkan gambar input
Untuk mendeteksi wajah dalam gambar, buat objekInputImage
dari Bitmap
, media.Image
, ByteBuffer
, array byte, atau file
di perangkat. Lalu, teruskan objek InputImage
ke metode process
FaceDetector
.
Untuk deteksi wajah, Anda harus menggunakan gambar dengan dimensi yang berukuran minimal 480x360 piksel. Jika Anda mendeteksi wajah secara real time, pengambilan frame pada resolusi minimum ini dapat membantu mengurangi latensi.
Anda dapat membuat objek InputImage
dari beberapa sumber, yang masing-masing langkahnya dijelaskan di bawah.
Menggunakan media.Image
Untuk membuat objek InputImage
dari objek media.Image
, seperti saat mengambil gambar dari kamera perangkat, teruskan objek media.Image
dan rotasi gambar ke InputImage.fromMediaImage()
.
Jika Anda menggunakan library
CameraX, class OnImageCapturedListener
dan ImageAnalysis.Analyzer
menghitung nilai rotasi untuk Anda.
Kotlin
private class YourImageAnalyzer : ImageAnalysis.Analyzer { override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image if (mediaImage != null) { val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) // Pass image to an ML Kit Vision API // ... } } }
Java
private class YourAnalyzer implements ImageAnalysis.Analyzer { @Override public void analyze(ImageProxy imageProxy) { Image mediaImage = imageProxy.getImage(); if (mediaImage != null) { InputImage image = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees()); // Pass image to an ML Kit Vision API // ... } } }
Jika Anda tidak menggunakan library kamera yang memberi derajat rotasi gambar, Anda dapat menghitungnya dari derajat rotasi perangkat dan orientasi sensor kamera pada perangkat:
Kotlin
private val ORIENTATIONS = SparseIntArray() init { ORIENTATIONS.append(Surface.ROTATION_0, 0) ORIENTATIONS.append(Surface.ROTATION_90, 90) ORIENTATIONS.append(Surface.ROTATION_180, 180) ORIENTATIONS.append(Surface.ROTATION_270, 270) } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Throws(CameraAccessException::class) private fun getRotationCompensation(cameraId: String, activity: Activity, isFrontFacing: Boolean): Int { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. val deviceRotation = activity.windowManager.defaultDisplay.rotation var rotationCompensation = ORIENTATIONS.get(deviceRotation) // Get the device's sensor orientation. val cameraManager = activity.getSystemService(CAMERA_SERVICE) as CameraManager val sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION)!! if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360 } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360 } return rotationCompensation }
Java
private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); static { ORIENTATIONS.append(Surface.ROTATION_0, 0); ORIENTATIONS.append(Surface.ROTATION_90, 90); ORIENTATIONS.append(Surface.ROTATION_180, 180); ORIENTATIONS.append(Surface.ROTATION_270, 270); } /** * Get the angle by which an image must be rotated given the device's current * orientation. */ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private int getRotationCompensation(String cameraId, Activity activity, boolean isFrontFacing) throws CameraAccessException { // Get the device's current rotation relative to its "native" orientation. // Then, from the ORIENTATIONS table, look up the angle the image must be // rotated to compensate for the device's rotation. int deviceRotation = activity.getWindowManager().getDefaultDisplay().getRotation(); int rotationCompensation = ORIENTATIONS.get(deviceRotation); // Get the device's sensor orientation. CameraManager cameraManager = (CameraManager) activity.getSystemService(CAMERA_SERVICE); int sensorOrientation = cameraManager .getCameraCharacteristics(cameraId) .get(CameraCharacteristics.SENSOR_ORIENTATION); if (isFrontFacing) { rotationCompensation = (sensorOrientation + rotationCompensation) % 360; } else { // back-facing rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360; } return rotationCompensation; }
Kemudian, teruskan objek media.Image
dan nilai derajat rotasi ke InputImage.fromMediaImage()
:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
Menggunakan URI file
Untuk membuat objek InputImage
dari URI file, teruskan konteks aplikasi dan URI file ke InputImage.fromFilePath()
. Hal ini berguna saat Anda menggunakan intent ACTION_GET_CONTENT
untuk meminta pengguna memilih gambar dari aplikasi galeri mereka.
Kotlin
val image: InputImage try { image = InputImage.fromFilePath(context, uri) } catch (e: IOException) { e.printStackTrace() }
Java
InputImage image; try { image = InputImage.fromFilePath(context, uri); } catch (IOException e) { e.printStackTrace(); }
Menggunakan ByteBuffer
atau ByteArray
Untuk membuat objek InputImage
dari ByteBuffer
atau ByteArray
, pertama-tama hitung derajat rotasi gambar seperti yang dijelaskan sebelumnya untuk input media.Image
.
Kemudian, buat objek InputImage
dengan buffer atau array, beserta tinggi, lebar, format encoding warna, dan derajat rotasi gambar:
Kotlin
val image = InputImage.fromByteBuffer( byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ) // Or: val image = InputImage.fromByteArray( byteArray, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 )
Java
InputImage image = InputImage.fromByteBuffer(byteBuffer, /* image width */ 480, /* image height */ 360, rotationDegrees, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 ); // Or: InputImage image = InputImage.fromByteArray( byteArray, /* image width */480, /* image height */360, rotation, InputImage.IMAGE_FORMAT_NV21 // or IMAGE_FORMAT_YV12 );
Menggunakan Bitmap
Untuk membuat objek InputImage
dari objek Bitmap
, buat deklarasi berikut:
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
Gambar direpresentasikan oleh objek Bitmap
bersama dengan derajat rotasi.
3. Mendapatkan instance FaceDetector
Kotlin
val detector = FaceDetection.getClient(options) // Or, to use the default option: // val detector = FaceDetection.getClient();
Java
FaceDetector detector = FaceDetection.getClient(options); // Or use the default options: // FaceDetector detector = FaceDetection.getClient();
4. Memproses gambar
Teruskan gambar ke metodeprocess
:
Kotlin
val result = detector.process(image) .addOnSuccessListener { faces -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
Java
Task<List<Face>> result = detector.process(image) .addOnSuccessListener( new OnSuccessListener<List<Face>>() { @Override public void onSuccess(List<Face> faces) { // Task completed successfully // ... } }) .addOnFailureListener( new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Task failed with an exception // ... } });
5. Mendapatkan informasi tentang wajah yang terdeteksi
Jika operasi deteksi wajah berhasil, daftar objekFace
akan diteruskan ke pemroses peristiwa sukses. Setiap objek Face
mewakili wajah yang terdeteksi dalam gambar. Untuk setiap wajah, Anda bisa mendapatkan koordinat pembatasnya di gambar input, serta informasi lain yang dapat ditemukan oleh detektor wajah sesuai dengan konfigurasi
yang Anda tetapkan. Contoh:
Kotlin
for (face in faces) { val bounds = face.boundingBox val rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees val rotZ = face.headEulerAngleZ // Head is tilted sideways rotZ degrees // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): val leftEar = face.getLandmark(FaceLandmark.LEFT_EAR) leftEar?.let { val leftEarPos = leftEar.position } // If contour detection was enabled: val leftEyeContour = face.getContour(FaceContour.LEFT_EYE)?.points val upperLipBottomContour = face.getContour(FaceContour.UPPER_LIP_BOTTOM)?.points // If classification was enabled: if (face.smilingProbability != null) { val smileProb = face.smilingProbability } if (face.rightEyeOpenProbability != null) { val rightEyeOpenProb = face.rightEyeOpenProbability } // If face tracking was enabled: if (face.trackingId != null) { val id = face.trackingId } }
Java
for (Face face : faces) { Rect bounds = face.getBoundingBox(); float rotY = face.getHeadEulerAngleY(); // Head is rotated to the right rotY degrees float rotZ = face.getHeadEulerAngleZ(); // Head is tilted sideways rotZ degrees // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): FaceLandmark leftEar = face.getLandmark(FaceLandmark.LEFT_EAR); if (leftEar != null) { PointF leftEarPos = leftEar.getPosition(); } // If contour detection was enabled: List<PointF> leftEyeContour = face.getContour(FaceContour.LEFT_EYE).getPoints(); List<PointF> upperLipBottomContour = face.getContour(FaceContour.UPPER_LIP_BOTTOM).getPoints(); // If classification was enabled: if (face.getSmilingProbability() != null) { float smileProb = face.getSmilingProbability(); } if (face.getRightEyeOpenProbability() != null) { float rightEyeOpenProb = face.getRightEyeOpenProbability(); } // If face tracking was enabled: if (face.getTrackingId() != null) { int id = face.getTrackingId(); } }
Contoh kontur wajah
Ketika mengaktifkan deteksi kontur wajah, Anda akan mendapatkan daftar titik untuk setiap fitur wajah yang terdeteksi. Titik-titik ini mewakili bentuk fitur. Baca Konsep Deteksi Wajah untuk mengetahui detail tentang cara kontur direpresentasikan.
Gambar berikut mengilustrasikan bagaimana titik-titik ini dipetakan ke wajah, klik gambar untuk memperbesarnya:
Deteksi wajah real-time
Jika ingin menggunakan deteksi wajah dalam aplikasi real-time, ikuti pedoman ini untuk mencapai frekuensi frame terbaik:
Konfigurasikan detektor wajah untuk menggunakan deteksi kontur wajah atau klasifikasi dan deteksi tempat terkenal, tetapi tidak keduanya:
Deteksi kontur
Deteksi tempat terkenal
Klasifikasi
Deteksi dan klasifikasi bangunan terkenal
Deteksi kontur dan deteksi tempat terkenal
Deteksi dan klasifikasi kontur
Deteksi kontur, deteksi tempat terkenal, dan klasifikasiAktifkan mode
FAST
(diaktifkan secara default).Pertimbangkan untuk mengambil gambar dengan resolusi lebih rendah. Namun, perhatikan juga persyaratan dimensi gambar API ini.
Camera
atau
camera2
API,
throttle panggilan ke detektor. Jika frame video baru tersedia saat detektor sedang berjalan, hapus frame tersebut. Lihat class
VisionProcessorBase
di aplikasi contoh panduan memulai untuk mengetahui contohnya.
CameraX
API,
pastikan strategi backpressure disetel ke nilai defaultnya
ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
.
Hal ini menjamin hanya satu gambar yang akan dikirimkan untuk analisis dalam satu waktu. Jika lebih banyak gambar dihasilkan saat analyzer sibuk, gambar tersebut akan otomatis dihapus dan tidak dimasukkan dalam antrean untuk dikirim. Setelah gambar yang dianalisis ditutup dengan memanggil ImageProxy.close(), gambar terbaru berikutnya akan dikirimkan.
CameraSourcePreview
dan
GraphicOverlay
dalam aplikasi contoh panduan memulai untuk mengetahui contohnya.
ImageFormat.YUV_420_888
. Jika Anda menggunakan Camera API versi lama, ambil gambar dalam format ImageFormat.NV21
.