شما میتوانید از کیت ML برای تشخیص چهره در تصاویر و ویدیو استفاده کنید.
| ویژگی | بدون دسته بندی | بستهبندیشده | 
|---|---|---|
| پیادهسازی | مدل به صورت پویا از طریق سرویسهای گوگل پلی دانلود میشود. | مدل در زمان ساخت به صورت ایستا به برنامه شما متصل است. | 
| اندازه برنامه | حدود ۸۰۰ کیلوبایت افزایش حجم. | حدود ۶.۹ مگابایت افزایش حجم. | 
| زمان اولیه سازی | ممکن است لازم باشد قبل از اولین استفاده، منتظر دانلود مدل باشید. | مدل فوراً موجود است | 
امتحانش کن.
- برای مشاهدهی نحوهی استفاده از این API، با برنامهی نمونه کار کنید.
- خودتان کد را با codelab امتحان کنید.
قبل از اینکه شروع کنی
- در فایل - build.gradleسطح پروژه خود، مطمئن شوید که مخزن Maven گوگل را هم در بخشهای- buildscriptو هم- allprojectsخود وارد کردهاید.
- وابستگیهای کتابخانههای اندروید ML Kit را به فایل gradle سطح برنامه ماژول خود که معمولاً - app/build.gradleاست، اضافه کنید. بر اساس نیاز خود، یکی از وابستگیهای زیر را انتخاب کنید:- برای باندل کردن مدل با اپلیکیشن خود: - dependencies { // ... // Use this dependency to bundle the model with your app implementation 'com.google.mlkit:face-detection:16.1.7' }- برای استفاده از مدل در سرویسهای گوگل پلی: - 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' }
- اگر تصمیم دارید از مدل در سرویسهای گوگل پلی استفاده کنید ، میتوانید برنامه خود را طوری پیکربندی کنید که پس از نصب برنامه از فروشگاه پلی استور، مدل را به طور خودکار روی دستگاه دانلود کند. برای انجام این کار، اعلان زیر را به فایل - 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>- همچنین میتوانید به صراحت در دسترس بودن مدل را بررسی کرده و از طریق API ModuleInstallClient سرویسهای گوگل پلی درخواست دانلود دهید. - اگر دانلود مدل در زمان نصب را فعال نکنید یا درخواست دانلود صریح ندهید، مدل در اولین باری که آشکارساز را اجرا میکنید دانلود میشود. درخواستهایی که قبل از اتمام دانلود انجام میدهید، هیچ نتیجهای ندارند. 
دستورالعملهای تصویر ورودی
برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰x۳۶۰ پیکسل استفاده کنید. برای اینکه کیت یادگیری ماشین بتواند چهرهها را به طور دقیق تشخیص دهد، تصاویر ورودی باید حاوی چهرههایی باشند که با دادههای پیکسلی کافی نمایش داده میشوند. به طور کلی، هر چهرهای که میخواهید در یک تصویر تشخیص دهید باید حداقل ۱۰۰x۱۰۰ پیکسل باشد. اگر میخواهید خطوط چهرهها را تشخیص دهید، کیت یادگیری ماشین به ورودی با وضوح بالاتر نیاز دارد: هر چهره باید حداقل ۲۰۰x۲۰۰ پیکسل باشد.
اگر چهرهها را در یک برنامه بلادرنگ تشخیص میدهید، ممکن است بخواهید ابعاد کلی تصاویر ورودی را نیز در نظر بگیرید. تصاویر کوچکتر میتوانند سریعتر پردازش شوند، بنابراین برای کاهش تأخیر، تصاویر را با وضوح پایینتر ضبط کنید، اما الزامات دقت فوق را در نظر داشته باشید و مطمئن شوید که چهره سوژه تا حد امکان فضای بیشتری از تصویر را اشغال میکند. همچنین به نکاتی برای بهبود عملکرد بلادرنگ مراجعه کنید.
فوکوس ضعیف تصویر نیز میتواند بر دقت تأثیر بگذارد. اگر نتایج قابل قبولی به دست نیاوردید، از کاربر بخواهید که دوباره تصویر را ثبت کند.
جهتگیری چهره نسبت به دوربین نیز میتواند بر ویژگیهای چهرهای که کیت ML تشخیص میدهد تأثیر بگذارد. به مفاهیم تشخیص چهره مراجعه کنید.
۱. پیکربندی تشخیص چهره
قبل از اعمال تشخیص چهره به یک تصویر، اگر میخواهید هر یک از تنظیمات پیشفرض تشخیص چهره را تغییر دهید، آن تنظیمات را با شیء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اینکه آیا به چهرهها شناسهای اختصاص داده شود یا خیر، که بتوان از آن برای ردیابی چهرهها در تصاویر استفاده کرد. توجه داشته باشید که وقتی تشخیص خطوط اطراف فعال است، فقط یک چهره شناسایی میشود، بنابراین ردیابی چهره نتایج مفیدی به همراه ندارد. به همین دلیل و برای بهبود سرعت تشخیص، هم تشخیص خطوط اطراف و هم ردیابی چهره را فعال نکنید. | 
برای مثال:
کاتلین
// 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 ارسال کنید.برای تشخیص چهره، باید از تصویری با ابعاد حداقل ۴۸۰x۳۶۰ پیکسل استفاده کنید. اگر چهرهها را به صورت بلادرنگ تشخیص میدهید، ثبت فریمها با این حداقل وضوح میتواند به کاهش تأخیر کمک کند.
 شما میتوانید یک شیء InputImage را از منابع مختلفی ایجاد کنید که هر کدام در زیر توضیح داده شدهاند.
 استفاده از یک media.Image
 برای ایجاد یک شیء InputImage از یک شیء media.Image ، مانند زمانی که از دوربین یک دستگاه تصویر میگیرید، شیء media.Image و چرخش تصویر را به InputImage.fromMediaImage() ارسال کنید.
 اگر از کتابخانه CameraX استفاده میکنید، کلاسهای OnImageCapturedListener و ImageAnalysis.Analyzer مقدار چرخش را برای شما محاسبه میکنند. 
کاتلین
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 // ... } } }
اگر از کتابخانه دوربینی که درجه چرخش تصویر را به شما بدهد استفاده نمیکنید، میتوانید آن را از درجه چرخش دستگاه و جهت سنسور دوربین در دستگاه محاسبه کنید:
کاتلین
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() ارسال کنید: 
کاتلین
val image = InputImage.fromMediaImage(mediaImage, rotation)
Java
InputImage image = InputImage.fromMediaImage(mediaImage, rotation);
استفاده از یک URI فایل
 برای ایجاد یک شیء InputImage از یک URI فایل، متن برنامه و URI فایل را به InputImage.fromFilePath() ارسال کنید. این زمانی مفید است که از یک ACTION_GET_CONTENT برای وادار کردن کاربر به انتخاب یک تصویر از برنامه گالری خود استفاده میکنید. 
کاتلین
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 را با بافر یا آرایه، به همراه ارتفاع، عرض، فرمت کدگذاری رنگ و درجه چرخش تصویر ایجاد کنید: 
کاتلین
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 ، تعریف زیر را انجام دهید: 
کاتلین
val image = InputImage.fromBitmap(bitmap, 0)
Java
InputImage image = InputImage.fromBitmap(bitmap, rotationDegree);
 تصویر توسط یک شیء Bitmap به همراه درجه چرخش نمایش داده میشود.
۳. یک نمونه از FaceDetector دریافت کنید
کاتلین
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 ارسال کنید: کاتلین
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 ، چهرهای را نشان میدهد که در تصویر شناسایی شده است. برای هر چهره، میتوانید مختصات مرزی آن را در تصویر ورودی و همچنین هر اطلاعات دیگری را که آشکارساز چهره برای یافتن آن پیکربندی کردهاید، دریافت کنید. به عنوان مثال: کاتلین
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 استفاده میکنید، فراخوانیهای throttle به آشکارساز انجام میشود. اگر در حین اجرای آشکارساز، یک فریم ویدیویی جدید در دسترس قرار گرفت، فریم را حذف کنید. برای مثال، به کلاس VisionProcessorBase در برنامه نمونه شروع سریع مراجعه کنید.CameraX استفاده میکنید، مطمئن شوید که استراتژی فشار معکوس (backpressure strategy) روی مقدار پیشفرض خود ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST تنظیم شده است. این تضمین میکند که فقط یک تصویر در هر زمان برای تجزیه و تحلیل تحویل داده میشود. اگر تصاویر بیشتری هنگام مشغول بودن تحلیلگر تولید شوند، به طور خودکار حذف میشوند و برای تحویل در صف قرار نمیگیرند. پس از بسته شدن تصویر در حال تجزیه و تحلیل با فراخوانی ImageProxy.close()، آخرین تصویر بعدی تحویل داده میشود.CameraSourcePreview و GraphicOverlay در برنامه نمونه شروع سریع مراجعه کنید.ImageFormat.YUV_420_888 ضبط کنید. اگر از API دوربین قدیمیتر استفاده میکنید، تصاویر را با فرمت ImageFormat.NV21 ضبط کنید.