يمكنك استخدام ML Kit لاكتشاف الوجوه في الصور والفيديو.
قبل ان تبدأ
- إذا لم تكن قد أضفت Firebase إلى تطبيقك بالفعل، فقم بذلك باتباع الخطوات الواردة في دليل البدء .
- قم بتضمين مكتبات ML Kit في ملف Podfile الخاص بك:
pod 'Firebase/MLVision', '6.25.0' # If you want to detect face contours (landmark detection and classification # don't require this additional model): pod 'Firebase/MLVisionFaceModel', '6.25.0'
بعد تثبيت أو تحديث Pods لمشروعك، تأكد من فتح مشروع Xcode الخاص بك باستخدام.xcworkspace
. - في تطبيقك، قم باستيراد Firebase:
سويفت
import Firebase
ج موضوعية
@import Firebase;
إرشادات إدخال الصورة
لكي تتمكن ML Kit من اكتشاف الوجوه بدقة، يجب أن تحتوي الصور المدخلة على وجوه يتم تمثيلها ببيانات بيكسل كافية. بشكل عام، يجب أن يكون حجم كل وجه تريد اكتشافه في الصورة 100 × 100 بكسل على الأقل. إذا كنت تريد اكتشاف ملامح الوجوه، فإن ML Kit يتطلب إدخالاً بدقة أعلى: يجب أن يكون كل وجه 200 × 200 بكسل على الأقل.
إذا كنت تكتشف وجوهًا في تطبيق في الوقت الفعلي، فقد ترغب أيضًا في مراعاة الأبعاد الإجمالية للصور المدخلة. يمكن معالجة الصور الأصغر حجمًا بشكل أسرع، وذلك لتقليل زمن الوصول، والتقاط الصور بدقة أقل (مع الأخذ في الاعتبار متطلبات الدقة المذكورة أعلاه) والتأكد من أن وجه الهدف يشغل أكبر قدر ممكن من الصورة. راجع أيضًا نصائح لتحسين الأداء في الوقت الفعلي .
قد يؤدي التركيز الضعيف للصورة إلى الإضرار بالدقة. إذا لم تحصل على نتائج مقبولة، فحاول مطالبة المستخدم باستعادة الصورة.
يمكن أن يؤثر أيضًا اتجاه الوجه بالنسبة للكاميرا على ميزات الوجه التي يكتشفها ML Kit. راجع مفاهيم اكتشاف الوجه .
1. قم بتكوين كاشف الوجه
قبل تطبيق اكتشاف الوجه على صورة ما، إذا كنت تريد تغيير أي من الإعدادات الافتراضية لكاشف الوجه، فحدد تلك الإعدادات باستخدام كائنVisionFaceDetectorOptions
. يمكنك تغيير الإعدادات التالية:إعدادات | |
---|---|
performanceMode | fast (افتراضي) | accurate فضل السرعة أو الدقة عند اكتشاف الوجوه. |
landmarkMode | none (افتراضي) | all ما إذا كان سيتم محاولة اكتشاف "معالم" الوجه - العيون والأذنين والأنف والخدين والفم - لجميع الوجوه المكتشفة. |
contourMode | none (افتراضي) | all سواء للكشف عن ملامح ملامح الوجه. يتم الكشف عن الملامح للوجه الأبرز فقط في الصورة. |
classificationMode | none (افتراضي) | all ما إذا كان سيتم تصنيف الوجوه إلى فئات مثل "مبتسم" و"عيون مفتوحة" أم لا. |
minFaceSize | CGFloat (الافتراضي: 0.1 )الحد الأدنى لحجم الوجوه المراد اكتشافها بالنسبة للصورة. |
isTrackingEnabled | false (افتراضي) | true ما إذا كان سيتم تعيين معرف للوجه أم لا، والذي يمكن استخدامه لتتبع الوجوه عبر الصور. لاحظ أنه عند تمكين اكتشاف الكفاف، يتم اكتشاف وجه واحد فقط، لذا لا يؤدي تتبع الوجه إلى نتائج مفيدة. لهذا السبب، ولتحسين سرعة الاكتشاف، لا تقم بتمكين اكتشاف الكفاف وتتبع الوجه. |
على سبيل المثال، قم بإنشاء كائن VisionFaceDetectorOptions
مثل أحد الأمثلة التالية:
سويفت
// High-accuracy landmark detection and face classification let options = VisionFaceDetectorOptions() options.performanceMode = .accurate options.landmarkMode = .all options.classificationMode = .all // Real-time contour detection of multiple faces let options = VisionFaceDetectorOptions() options.contourMode = .all
ج موضوعية
// High-accuracy landmark detection and face classification FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.performanceMode = FIRVisionFaceDetectorPerformanceModeAccurate; options.landmarkMode = FIRVisionFaceDetectorLandmarkModeAll; options.classificationMode = FIRVisionFaceDetectorClassificationModeAll; // Real-time contour detection of multiple faces FIRVisionFaceDetectorOptions *options = [[FIRVisionFaceDetectorOptions alloc] init]; options.contourMode = FIRVisionFaceDetectorContourModeAll;
2. قم بتشغيل كاشف الوجه
لاكتشاف الوجوه في صورة ما، قم بتمرير الصورة كـUIImage
أو CMSampleBufferRef
إلى طريقة detect(in:)
VisionFaceDetector
:- احصل على مثيل
VisionFaceDetector
:سويفت
lazy var vision = Vision.vision() let faceDetector = vision.faceDetector(options: options)
ج موضوعية
FIRVision *vision = [FIRVision vision]; FIRVisionFaceDetector *faceDetector = [vision faceDetector]; // Or, to change the default settings: // FIRVisionFaceDetector *faceDetector = // [vision faceDetectorWithOptions:options];
قم بإنشاء كائن
VisionImage
باستخدامUIImage
أوCMSampleBufferRef
.لاستخدام
UIImage
:- إذا لزم الأمر، قم بتدوير الصورة بحيث تكون خاصية
imageOrientation
الخاصة بها هي.up
. - قم بإنشاء كائن
VisionImage
باستخدامUIImage
الذي تم تدويره بشكل صحيح. لا تحدد أي بيانات تعريف للتدوير — يجب استخدام القيمة الافتراضية،.topLeft
.سويفت
let image = VisionImage(image: uiImage)
ج موضوعية
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
لاستخدام
CMSampleBufferRef
:قم بإنشاء كائن
VisionImageMetadata
الذي يحدد اتجاه بيانات الصورة الموجودة في المخزن المؤقتCMSampleBufferRef
.للحصول على اتجاه الصورة:
سويفت
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
ج موضوعية
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
ثم قم بإنشاء كائن بيانات التعريف:
سويفت
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
ج موضوعية
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- قم بإنشاء كائن
VisionImage
باستخدام كائنCMSampleBufferRef
وبيانات تعريف التدوير:سويفت
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
ج موضوعية
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- إذا لزم الأمر، قم بتدوير الصورة بحيث تكون خاصية
- ثم قم بتمرير الصورة إلى طريقة
detect(in:)
:سويفت
faceDetector.process(visionImage) { faces, error in guard error == nil, let faces = faces, !faces.isEmpty else { // ... return } // Faces detected // ... }
ج موضوعية
[faceDetector detectInImage:image completion:^(NSArray<FIRVisionFace *> *faces, NSError *error) { if (error != nil) { return; } else if (faces != nil) { // Recognized faces } }];
3. الحصول على معلومات حول الوجوه المكتشفة
إذا نجحت عملية اكتشاف الوجه، فسيقوم كاشف الوجه بتمرير مجموعة من كائناتVisionFace
إلى معالج الإكمال. يمثل كل كائن VisionFace
وجهًا تم اكتشافه في الصورة. بالنسبة لكل وجه، يمكنك الحصول على إحداثياته المحيطة في الصورة المدخلة، بالإضافة إلى أي معلومات أخرى قمت بتكوين كاشف الوجه للعثور عليها. على سبيل المثال: سويفت
for face in faces { let frame = face.frame if face.hasHeadEulerAngleY { let rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees } if face.hasHeadEulerAngleZ { let rotZ = face.headEulerAngleZ // Head is rotated upward rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): if let leftEye = face.landmark(ofType: .leftEye) { let leftEyePosition = leftEye.position } // If contour detection was enabled: if let leftEyeContour = face.contour(ofType: .leftEye) { let leftEyePoints = leftEyeContour.points } if let upperLipBottomContour = face.contour(ofType: .upperLipBottom) { let upperLipBottomPoints = upperLipBottomContour.points } // If classification was enabled: if face.hasSmilingProbability { let smileProb = face.smilingProbability } if face.hasRightEyeOpenProbability { let rightEyeOpenProb = face.rightEyeOpenProbability } // If face tracking was enabled: if face.hasTrackingID { let trackingId = face.trackingID } }
ج موضوعية
for (FIRVisionFace *face in faces) { // Boundaries of face in image CGRect frame = face.frame; if (face.hasHeadEulerAngleY) { CGFloat rotY = face.headEulerAngleY; // Head is rotated to the right rotY degrees } if (face.hasHeadEulerAngleZ) { CGFloat rotZ = face.headEulerAngleZ; // Head is tilted sideways rotZ degrees } // If landmark detection was enabled (mouth, ears, eyes, cheeks, and // nose available): FIRVisionFaceLandmark *leftEar = [face landmarkOfType:FIRFaceLandmarkTypeLeftEar]; if (leftEar != nil) { FIRVisionPoint *leftEarPosition = leftEar.position; } // If contour detection was enabled: FIRVisionFaceContour *upperLipBottomContour = [face contourOfType:FIRFaceContourTypeUpperLipBottom]; if (upperLipBottomContour != nil) { NSArray<FIRVisionPoint *> *upperLipBottomPoints = upperLipBottomContour.points; if (upperLipBottomPoints.count > 0) { NSLog("Detected the bottom contour of the subject's upper lip.") } } // If classification was enabled: if (face.hasSmilingProbability) { CGFloat smileProb = face.smilingProbability; } if (face.hasRightEyeOpenProbability) { CGFloat rightEyeOpenProb = face.rightEyeOpenProbability; } // If face tracking was enabled: if (face.hasTrackingID) { NSInteger trackingID = face.trackingID; } }
مثال على ملامح الوجه
عند تمكين اكتشاف محيط الوجه، تحصل على قائمة بالنقاط لكل ميزة وجه تم اكتشافها. تمثل هذه النقاط شكل الميزة. راجع نظرة عامة على مفاهيم اكتشاف الوجه للحصول على تفاصيل حول كيفية تمثيل الخطوط.
توضح الصورة التالية كيفية تعيين هذه النقاط للوجه (انقر على الصورة للتكبير):
كشف الوجه في الوقت الحقيقي
إذا كنت تريد استخدام اكتشاف الوجه في تطبيق في الوقت الفعلي، فاتبع هذه الإرشادات لتحقيق أفضل معدلات الإطارات:
قم بتكوين كاشف الوجه لاستخدام إما اكتشاف محيط الوجه أو التصنيف واكتشاف المعالم، ولكن ليس كليهما:
الكشف عن الكنتور
الكشف عن المعالم
تصنيف
كشف المعالم وتصنيفها
كشف الكفاف والكشف عن المعالم
الكشف عن الكنتور وتصنيفه
كشف الكفاف، كشف المعالم، والتصنيفتمكين الوضع
fast
(ممكّن افتراضيًا).فكر في التقاط الصور بدقة أقل. ومع ذلك، ضع في اعتبارك أيضًا متطلبات أبعاد الصورة لواجهة برمجة التطبيقات هذه.
- خنق المكالمات إلى الكاشف. إذا أصبح إطار فيديو جديد متاحًا أثناء تشغيل الكاشف، قم بإسقاط الإطار.
- إذا كنت تستخدم مخرجات الكاشف لتراكب الرسومات على الصورة المدخلة، فاحصل أولاً على النتيجة من ML Kit، ثم قم بعرض الصورة والتراكب في خطوة واحدة. من خلال القيام بذلك، يمكنك العرض على سطح العرض مرة واحدة فقط لكل إطار إدخال. راجع فئتي PreviewOverlayView و FIRDetectionOverlayView في نموذج تطبيق العرض للحصول على مثال.