میتوانید از ML Kit برای تشخیص چهره در تصاویر و ویدیو استفاده کنید.
| ویژگی | بستهبندینشده | موجود در بستهبندی |
|---|---|---|
| پیادهسازی | مدل بهطور پویا ازطریق «خدمات Google Play» بارگیری میشود. | مدل در زمان ساخت بهصورت ایستا به برنامهتان پیوند میشود. |
| حجم برنامه | حدود ۸۰۰ کیلوبایت افزایش اندازه. | حدود ۶٫۹ مگابایت افزایش اندازه. |
| زمان مقداردهی اولیه | ممکن است لازم باشد قبلاز اولین استفاده، منتظر بمانید تا مدل بارگیری شود. | مدل بلافاصله دردسترس است |
امتحان کنید
- با برنامه نمونه کار کنید تا نمونهای از کاربرد این API را ببینید.
- کد را خودتان با codelab امتحان کنید.
قبلاز شروع
در فایل
build.gradleسطح پروژه، حتماً مخزن Maven مربوط به Google را در هر دو بخشbuildscriptوallprojectsاضافه کنید.وابستگیهای کتابخانههای Android «کیت یادگیری ماشین» را به فایل gradle سطح برنامه ماژولتان اضافه کنید. این فایل معمولاً
app/build.gradleاست. یکی از وابستگیهای زیر را براساس نیازهایتان انتخاب کنید:برای بستهبندی مدل با برنامهتان:
dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:face-detection:16.1.7' }برای استفاده از مدل در «خدمات 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' }اگر تصمیم بگیرید از مدل در «خدمات Google Play» استفاده کنید، میتوانید برنامهتان را پیکربندی کنید تا پساز نصب برنامهتان از «فروشگاه Play»، مدل را بهطور خودکار در دستگاه بارگیری کند. برای انجام این کار، اظهارنامه زیر را به فایل
AndroidManifest.xmlبرنامهتان اضافه کنید:<application ...> ... <meta-data android:name="com.google.mlkit.vision.DEPENDENCIES" android:value="face" > <!-- To use multiple models: android:value="face,model2,model3" --> </application>همچنین میتوانید بهطور صریح دردسترس بودن مدل را بررسی کنید و ازطریق ModuleInstallClient API در خدمات Google Play درخواست بارگیری کنید.
اگر بارگیری مدل در زمان نصب را فعال نکنید یا درخواست بارگیری صریح نکنید، مدل اولین باری که آشکارساز را اجرا میکنید بارگیری میشود. درخواستهایی که قبلاز تکمیل بارگیری ارسال میکنید نتیجهای دربر نخواهد داشت.
دستورالعملهای تصویر ورودی
برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰×۳۶۰ پیکسل استفاده کنید. برای اینکه ML Kit بتواند چهرهها را بهطور دقیق تشخیص دهد، تصاویر ورودی باید حاوی چهرههایی باشند که با دادههای پیکسلی کافی نمایش داده شدهاند. بهطور کلی، هر چهرهای که میخواهید در تصویر تشخیص داده شود باید حداقل ۱۰۰×۱۰۰ پیکسل باشد. اگر میخواهید پَربندهای چهرهها را تشخیص دهید، «کیت یادگیری ماشین» به ورودی با وضوح بالاتر نیاز دارد: هر چهره باید حداقل ۲۰۰×۲۰۰ پیکسل باشد.
اگر چهرهها را در برنامهای همزمان تشخیص میدهید، شاید بهتر باشد ابعاد کلی تصاویر ورودی را نیز درنظر بگیرید. تصاویر کوچکتر را میتوان سریعتر پردازش کرد، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایینتر ثبت کنید، اما الزامات دقت بالا را درنظر داشته باشید و مطمئن شوید که چهره سوژه تا حد امکان بخش بیشتری از تصویر را اشغال میکند. همچنین نکاتی برای بهبود عملکرد همزمان را ببینید.
تمرکز ضعیف تصویر نیز میتواند بر دقت تأثیر بگذارد. اگر نتایج قابلقبولی دریافت نکردید، از کاربر بخواهید تصویر را دوباره بگیرد.
جهت چهره نسبتبه دوربین نیز میتواند بر ویژگیهای چهرهای که ML Kit تشخیص میدهد تأثیر بگذارد. مفاهیم تشخیص چهره را ببینید.
۱. پیکربندی تشخیصدهنده چهره
قبلاز اعمال تشخیص چهره روی تصویر، اگر میخواهید هرکدام از تنظیمات پیشفرض تشخیص چهره را تغییر دهید، آن تنظیمات را با شیءFaceDetectorOptions مشخص کنید.
میتوانید تنظیمات زیر را تغییر دهید:
| تنظیمات | |
|---|---|
setPerformanceMode
|
PERFORMANCE_MODE_FAST (پیشفرض)
|
PERFORMANCE_MODE_ACCURATE
هنگام تشخیص چهره، سرعت یا دقت را ترجیح دهید. |
setLandmarkMode
|
LANDMARK_MODE_NONE (پیشفرض)
|
LANDMARK_MODE_ALL
اینکه آیا برای شناسایی «نشانههای» چهره تلاش شود یا نه: چشمها، گوشها، بینی، گونهها، دهان، و غیره. |
setContourMode
|
CONTOUR_MODE_NONE (پیشفرض)
|
CONTOUR_MODE_ALL
آیا خطوط اجزای صورت شناسایی شود یا نه. خطوط پیرامونی فقط برای برجستهترین چهره در تصویر شناسایی میشود. |
setClassificationMode
|
CLASSIFICATION_MODE_NONE (پیشفرض)
|
CLASSIFICATION_MODE_ALL
اینکه چهرهها در دستههایی مانند «خندان» و «چشمان باز» طبقهبندی شوند یا نه. |
setMinFaceSize
|
float (پیشفرض: 0.1f)
کوچکترین اندازه چهره موردنظر را تنظیم میکند که بهصورت نسبت عرض سر به عرض تصویر بیان میشود. |
enableTracking
|
false (پیشفرض) | true
آیا به چهرهها شناسه اختصاص داده شود یا نه، که میتواند برای ردیابی چهرهها در تصاویر استفاده شود. توجه داشته باشید که وقتی تشخیص کانتور فعال است، فقط یک چهره تشخیص داده میشود، بنابراین ردگیری چهره نتایج مفیدی تولید نمیکند. به همین دلیل، و برای بهبود سرعت تشخیص، هر دو ویژگی تشخیص کانتور و ردگیری چهره را فعال نکنید. |
برای مثال:
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()
جاوا
// 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();
۲. آماده کردن تصویر ورودی
برای تشخیص چهرهها در تصویر، شیءInputImage را از Bitmap، media.Image، ByteBuffer، آرایه بایت، یا فایلی در دستگاه ایجاد کنید. سپس، شیء InputImage را به
روش process FaceDetector ارسال کنید.
برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰×۳۶۰ پیکسل استفاده کنید. اگر چهرهها را در زمان واقعی تشخیص میدهید، ثبت فریمها با این حداقل وضوح میتواند به کاهش تأخیر کمک کند.
میتوانید شیء InputImage را از منابع مختلف ایجاد کنید، هرکدام در زیر توضیح داده شده است.
استفاده از media.Image
برای ایجاد شیء InputImage
از شیء media.Image، مثلاً وقتی تصویری را از
دوربین دستگاه ضبط میکنید، شیء media.Image و چرخش تصویر را به
InputImage.fromMediaImage() ارسال کنید.
اگر از کتابخانه
CameraX استفاده میکنید، کلاسهای OnImageCapturedListener و
ImageAnalysis.Analyzer مقدار چرخش را برای شما
محاسبه میکنند.
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 // ... } } }
جاوا
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 // ... } } }
اگر از کتابخانه دوربینی استفاده نمیکنید که درجه چرخش تصویر را به شما بدهد، میتوانید آن را از درجه چرخش دستگاه و جهت حسگر دوربین در دستگاه محاسبه کنید:
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 }
جاوا
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; }
سپس، شیء media.Image و مقدار درجه چرخش را به InputImage.fromMediaImage() ارسال کنید:
Kotlin
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
استفاده از URI فایل
برای ایجاد شیء InputImage
از URI فایل، بافت برنامه و URI فایل را به
InputImage.fromFilePath() ارسال کنید. این کار زمانی مفید است که
از ACTION_GET_CONTENT intent برای درخواست از کاربر برای انتخاب
تصویری از برنامه گالریاش استفاده میکنید.
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(); }
استفاده از ByteBuffer یا ByteArray
برای ایجاد شیء InputImage
از ByteBuffer یا ByteArray، ابتدا درجه چرخش تصویر را
همانطور که قبلاً برای ورودی media.Image شرح داده شد محاسبه کنید.
سپس، شیء InputImage را با میانگیر یا آرایه، بههمراه ارتفاع، عرض، قالب کدبندی رنگ، و درجه چرخش تصویر ایجاد کنید:
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 )
جاوا
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 );
استفاده از Bitmap
برای ایجاد شیء InputImage
از شیء Bitmap، اعلان زیر را انجام دهید:
Kotlin
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
تصویر با شیء Bitmap بههمراه درجه چرخش نشان داده میشود.
۳. دریافت نمونهای از FaceDetector
Kotlin
val detector = FaceDetection.getClient(options) // Or, to use the default option: // val detector = FaceDetection.getClient();
جاوا
FaceDetector detector = FaceDetection.getClient(options); // Or use the default options: // FaceDetector detector = FaceDetection.getClient();
۴. پردازش تصویر
تصویر را به روشprocess ارسال کنید:
Kotlin
val result = detector.process(image) .addOnSuccessListener { faces -> // Task completed successfully // ... } .addOnFailureListener { e -> // Task failed with an exception // ... }
جاوا
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 // ... } });
۵. دریافت اطلاعات درباره چهرههای شناساییشده
اگر عملیات تشخیص چهره موفقیتآمیز باشد، فهرستی از اشیاءFace به شنونده موفقیت
ارسال میشود. هر شیء Face نشاندهنده چهرهای است که در تصویر شناسایی شده است. برای هر چهره، میتوانید مختصات مرزی آن را در تصویر ورودی و همچنین هر اطلاعات دیگری را که برای یافتن آن پیکربندی کردهاید، دریافت کنید. برای مثال:
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 } }
جاوا
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(); } }
نمونهای از پَربندهای چهره
وقتی تشخیص خطوط چهره را فعال کرده باشید، فهرستی از نقاط برای هر ویژگی چهره که شناسایی شده است دریافت میکنید. این نقطهها نشاندهنده شکل عارضه است. برای جزئیات بیشتر درباره نحوه نمایش کانتورها، به مفاهیم تشخیص چهره مراجعه کنید.
تصویر زیر نشان میدهد که این نقاط چگونه روی چهره نگاشت میشوند، برای بزرگ کردن تصویر روی آن کلیک کنید:
تشخیص چهره همزمان
اگر میخواهید از تشخیص چهره در یک برنامه همزمان استفاده کنید، این دستورالعملها را دنبال کنید تا بهترین نرخ فریم را بهدست آورید:
تشخیصدهنده چهره را برای استفاده از تشخیص خطوط چهره یا طبقهبندی و تشخیص نشانههای چهره پیکربندی کنید، اما نه هر دو:
تشخیص خطوط محیطی
تشخیص نشانگر مکانی
طبقهبندی
تشخیص و طبقهبندی نشانگر مکانی
تشخیص خطوط محیطی و تشخیص نشانگر مکانی
تشخیص و طبقهبندی خطوط محیطی
تشخیص خطوط محیطی، تشخیص نشانگر مکانی، و طبقهبندیحالت
FASTرا فعال کنید (بهطور پیشفرض فعال است).تصاویر را با وضوح پایینتری بگیرید. بااینحال، الزامات ابعاد تصویر این API را نیز درنظر داشته باشید.
Camera یا
camera2 API استفاده میکنید،
فراخوانیهای آشکارساز را محدود کنید. اگر درحین اجرای آشکارساز، فریم ویدیویی جدیدی دردسترس قرار گرفت، فریم را رها کنید. برای دیدن نمونه، کلاس
VisionProcessorBase را در برنامه نمونه شروع سریع ببینید.
CameraX API استفاده میکنید،
مطمئن شوید که استراتژی فشار برگشتی روی مقدار پیشفرض آن
ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST تنظیم شده باشد.
این کار تضمین میکند که در هر بار فقط یک تصویر برای تجزیهوتحلیل ارسال شود. اگر وقتی تحلیلگر مشغول است تصاویر بیشتری تولید شود، این تصاویر بهطور خودکار حذف میشوند و برای تحویل در صف قرار نمیگیرند. وقتی تصویری که درحال تجزیهوتحلیل است با فراخوانی
ImageProxy.close() بسته شود، تصویر جدید بعدی ارائه خواهد شد.
CameraSourcePreview و
GraphicOverlay را در برنامه نمونه شروع سریع ببینید.
ImageFormat.YUV_420_888 ضبط کنید. اگر از Camera API قدیمیتر استفاده میکنید، تصاویر را در قالب
ImageFormat.NV21 ضبط کنید.