میتوانید از ML Kit برای تشخیص چهره در تصاویر و ویدیو استفاده کنید.
| ویژگی | تفکیکشده | موجود در بستهبندی |
|---|---|---|
| پیادهسازی | مدل بهصورت پویا ازطریق «خدمات Google Play» بارگیری میشود. | مدل در زمان ساخت بهصورت ایستا به برنامهتان پیوند داده میشود. |
| حجم برنامه | حدود ۸۰۰ کیلوبایت افزایش اندازه. | حدود ۶٫۹ مگابایت افزایش اندازه. |
| زمان مقداردهی اولیه | ممکن است لازم باشد قبلاز اولین استفاده، منتظر بمانید تا مدل بارگیری شود. | مدل بلافاصله دردسترس است |
امتحان کنید
- با برنامه نمونه بازی کنید تا نمونهای از کاربرد این API را ببینید.
- با codelab خودتان کد را امتحان کنید.
قبلاز شروع
در فایل
build.gradleسطح پروژه، حتماً مخزن Maven مربوط به Google را در هر دو بخشbuildscriptوallprojectsاضافه کنید.وابستگیهای کتابخانههای ML Kit 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>همچنین میتوانید دردسترس بودن مدل را بهطور صریح بررسی کنید و ازطریق خدمات Google Play ModuleInstallClient API درخواست بارگیری کنید.
اگر بارگیری مدل در زمان نصب را فعال نکنید یا درخواست بارگیری صریح نکنید، مدل اولینباری که آشکارساز را اجرا میکنید بارگیری میشود. درخواستهایی که قبلاز تکمیل بارگیری انجام میدهید، نتیجهای نخواهد داشت.
دستورالعملهای تصویر ورودی
برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰×۳۶۰ پیکسل استفاده کنید. برای اینکه ML Kit چهرهها را بهدقت تشخیص دهد، تصاویر ورودی باید حاوی چهرههایی باشند که با دادههای پیکسل کافی نشان داده شدهاند. بهطورکلی، هر چهرهای که میخواهید در تصویر تشخیص داده شود باید حداقل ۱۰۰x۱۰۰ پیکسل باشد. اگر میخواهید خطوط چهره را تشخیص دهید، ML Kit به ورودی با وضوح بالاتر نیاز دارد: هر چهره باید حداقل ۲۰۰x۲۰۰ پیکسل باشد.
اگر چهرهها را در یک برنامه همزمان تشخیص میدهید، ممکن است بخواهید ابعاد کلی تصاویر ورودی را نیز درنظر بگیرید. تصاویر کوچکتر میتوانند سریعتر پردازش شوند، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایینتر ضبط کنید، اما الزامات دقت فوق را درنظر داشته باشید و مطمئن شوید که چهره سوژه تا حد امکان بخش بزرگی از تصویر را اشغال کند. همچنین نکاتی برای بهبود عملکرد همزمان را ببینید.
فوکوس ضعیف تصویر نیز میتواند بر دقت تأثیر بگذارد. اگر نتایج قابلقبولی دریافت نکردید، از کاربر بخواهید تصویر را دوباره ضبط کند.
جهت چهره نسبتبه دوربین نیز میتواند بر ویژگیهای چهرهای که 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();
۲. آماده کردن تصویر ورودی
برای تشخیص چهرهها در تصویر، ازBitmap، media.Image، ByteBuffer، آرایه بایت، یا فایلی در دستگاه، شیء InputImage ایجاد کنید. سپس، شیء 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);
استفاده از نشانی وب فایل
برای ایجاد شیء InputImage از نشانی وب فایل، بافت برنامه و نشانی وب فایل را به InputImage.fromFilePath() ارسال کنید. این کار زمانی مفید است که
از هدف ACTION_GET_CONTENT برای درخواست از کاربر برای انتخاب
تصویری از برنامه گالری خود استفاده میکنید.
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 ضبط کنید.