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 | Ukuran peningkatan sekitar 800 KB. | Peningkatan ukuran sekitar 6,9 MB. |
Waktu inisialisasi | Mungkin harus menunggu model didownload sebelum digunakan pertama kali. | Model akan segera tersedia |
Cobalah
- Cobalah aplikasi contoh untuk melihat contoh penggunaan API ini.
- Coba kode sendiri dengan codelab ini.
Sebelum memulai
Dalam file
build.gradle
level project, pastikan Anda menyertakan ID Repositori Maven di bagianbuildscript
danallprojects
.Tambahkan dependensi untuk library Android ML Kit ke modul Anda gradle level aplikasi, yang biasanya adalah
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.7' }
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 Anda memilih untuk menggunakan model ini di Layanan Google Play, Anda dapat mengonfigurasi aplikasi Anda untuk mengunduh model secara otomatis 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 bisa 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 diunduh saat pertama kali Anda menjalankan detektor. Permintaan yang Anda buat sebelum pengunduhan selesai, tidak akan memberikan hasil.
Panduan gambar input
Untuk pengenalan wajah, Anda harus menggunakan gambar dengan dimensi minimal 480x360 piksel. Agar ML Kit dapat mendeteksi wajah secara akurat, gambar input harus berisi wajah yang diwakili oleh data piksel yang memadai. Secara umum, setiap wajah yang Anda inginkan untuk dideteksi dalam gambar harus berukuran minimal 100x100 piksel. Jika Anda ingin mendeteksi kontur wajah, ML Kit membutuhkan input resolusi yang lebih tinggi: setiap wajah harus berukuran minimal 200x200 piksel.
Jika Anda mendeteksi wajah dalam aplikasi {i>real-time<i}, Anda mungkin juga ingin untuk mempertimbangkan dimensi gambar input secara keseluruhan. Gambar yang lebih kecil bisa diproses lebih cepat, sehingga untuk mengurangi latensi, ambil gambar pada resolusi lebih rendah, tetapi pertahankan memenuhi persyaratan akurasi di atas dan memastikan bahwa wajah subjek menempati sebanyak mungkin gambar. Lihat juga tips untuk meningkatkan performa real-time.
Fokus gambar yang buruk juga dapat memengaruhi akurasi. Jika Anda tidak dapat diterima meminta pengguna untuk mengambil ulang gambar.
Orientasi wajah relatif terhadap kamera juga dapat memengaruhi karakteristik wajah yang terdeteksi oleh ML Kit. Lihat Konsep Deteksi Wajah.
1. Mengonfigurasi detektor wajah
Jika Anda ingin mengubah setelan sebelum menerapkan deteksi wajah ke suatu gambar di setelan default detektor wajah, 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
Apakah untuk mencoba mengidentifikasi "landmark" wajah: mata, telinga, hidung, pipi, mulut, dan sebagainya. |
setContourMode
|
CONTOUR_MODE_NONE (default)
|
CONTOUR_MODE_ALL
Apakah mendeteksi kontur fitur wajah. Kontur adalah terdeteksi hanya untuk wajah yang paling terlihat dalam gambar. |
setClassificationMode
|
CLASSIFICATION_MODE_NONE (default)
|
CLASSIFICATION_MODE_ALL
Mengklasifikasikan wajah menjadi beberapa kategori atau tidak, seperti "tersenyum", dan "mata terbuka". |
setMinFaceSize
|
float (default: 0.1f )
Menetapkan ukuran wajah terkecil yang diinginkan, yang dinyatakan sebagai rasio lebar kepala selebar gambar. |
enableTracking
|
false (default) | true
Menetapkan ID pada wajah atau tidak, yang dapat digunakan untuk melacak wajah di seluruh gambar. Perhatikan bahwa saat deteksi kontur diaktifkan, hanya satu wajah yang terdeteksi, sehingga pelacakan wajah tidak memberikan hasil yang berguna. Untuk ini alasan, dan untuk meningkatkan kecepatan deteksi, jangan aktifkan kedua deteksi dan pelacakan wajah. |
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 minimal 480x360 piksel. Jika Anda mendeteksi wajah secara real time, menangkap frame pada resolusi minimum ini dapat membantu mengurangi latensi.
Anda dapat membuat InputImage
dari berbagai sumber, masing-masing akan dijelaskan di bawah ini.
Menggunakan media.Image
Untuk membuat InputImage
dari objek media.Image
, seperti saat Anda mengambil gambar dari
kamera perangkat, teruskan objek media.Image
dan objek
rotasi ke InputImage.fromMediaImage()
.
Jika Anda menggunakan
library CameraX, OnImageCapturedListener
dan
Class ImageAnalysis.Analyzer
menghitung nilai rotasi
keamanan 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 pustaka kamera yang memberi derajat rotasi gambar, Anda bisa menghitungnya dari derajat rotasi perangkat dan orientasi kamera sensor di 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; }
Lalu, 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 InputImage
dari URI file, teruskan konteks aplikasi dan URI file ke
InputImage.fromFilePath()
. Hal ini berguna ketika Anda
gunakan 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 InputImage
dari ByteBuffer
atau ByteArray
, hitung gambar terlebih dahulu
derajat rotasi seperti yang dijelaskan sebelumnya untuk input media.Image
.
Lalu, buat objek InputImage
dengan buffer atau array, beserta elemen
tinggi, lebar, format encoding warna, dan derajat rotasi:
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 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
diteruskan ke keberhasilan
pemroses. Setiap objek Face
mewakili wajah yang terdeteksi
pada gambar. Untuk setiap wajah, Anda bisa mendapatkan koordinat pembatasnya di input
serta informasi lain apa pun yang Anda
konfigurasikan sebagai pendeteksi wajah untuk
temukan. 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 Anda mengaktifkan deteksi kontur wajah, Anda akan mendapatkan daftar titik untuk setiap fitur wajah yang terdeteksi. Titik-titik ini menggambarkan bentuk aplikasi baru. Lihat Wajah Konsep Deteksi untuk mengetahui detail tentang bagaimana kontur terwakili.
Gambar berikut mengilustrasikan bagaimana titik-titik ini dipetakan ke wajah, klik untuk memperbesarnya:
Deteksi wajah real-time
Jika Anda ingin menggunakan deteksi wajah dalam aplikasi real-time, ikuti langkah-langkah berikut panduan untuk mencapai kecepatan frame terbaik:
Konfigurasi detektor wajah untuk menggunakan deteksi kontur wajah atau klasifikasi dan deteksi struktur, tetapi tidak keduanya:
Deteksi kontur
Deteksi tempat terkenal
Klasifikasi
Deteksi dan klasifikasi tempat terkenal
Deteksi kontur dan deteksi tempat terkenal
Deteksi dan klasifikasi kontur
Deteksi kontur, deteksi tempat terkenal, dan klasifikasiAktifkan mode
FAST
(diaktifkan secara default).Sebaiknya ambil gambar dengan resolusi yang lebih rendah. Namun, perlu diingat persyaratan dimensi gambar API ini.
Camera
atau
camera2
API,
men-throttle panggilan ke detektor. Jika video baru
{i>frame<i} menjadi tersedia saat detektor sedang berjalan, hapus {i>frame<i} tersebut. Lihat
VisionProcessorBase
dalam aplikasi contoh panduan memulai untuk digunakan sebagai contoh.
CameraX
API,
pastikan strategi tekanan balik ditetapkan ke nilai defaultnya
ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
.
Hal ini menjamin hanya satu gambar yang akan dikirimkan untuk analisis pada satu waktu. Jika lebih banyak gambar
yang dihasilkan ketika penganalisis sedang sibuk, mereka
akan dibuang secara otomatis dan tidak diantrekan
pengiriman. Setelah gambar yang dianalisis ditutup dengan memanggil
ImageProxy.close(), gambar terbaru berikutnya akan dikirim.
CameraSourcePreview
dan
GraphicOverlay
dalam aplikasi contoh panduan memulai sebagai contoh.
ImageFormat.YUV_420_888
. Jika Anda menggunakan Camera API versi lama, ambil gambar dengan
Format ImageFormat.NV21
.