אתה יכול להשתמש בערכת ML כדי לזהות פרצופים בתמונות ובווידאו.
לפני שאתה מתחיל
- אם עדיין לא הוספת את 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
Objective-C
@import Firebase;
הנחיות לקלט תמונה
כדי ש-ML Kit יזהה במדויק פרצופים, תמונות קלט חייבות להכיל פרצופים המיוצגים על ידי מספיק נתוני פיקסלים. באופן כללי, כל פנים שאתה רוצה לזהות בתמונה צריך להיות לפחות 100x100 פיקסלים. אם אתה רוצה לזהות את קווי המתאר של הפנים, ערכת ML דורשת קלט ברזולוציה גבוהה יותר: כל פנים צריך להיות לפחות 200x200 פיקסלים.
אם אתה מזהה פרצופים ביישום בזמן אמת, אולי תרצה לשקול גם את הממדים הכוללים של תמונות הקלט. ניתן לעבד תמונות קטנות יותר מהר יותר, לכן כדי להפחית את זמן ההשהיה, צלם תמונות ברזולוציות נמוכות יותר (תזכור את דרישות הדיוק שלעיל) והבטח שהפנים של הנושא תופסות כמה שיותר מהתמונה. ראה גם טיפים לשיפור הביצועים בזמן אמת .
מיקוד לקוי של התמונה עלול לפגוע ברמת הדיוק. אם אינך מקבל תוצאות מקובלות, נסה לבקש מהמשתמש לצלם מחדש את התמונה.
כיוון הפנים ביחס למצלמה יכול גם להשפיע על תווי הפנים שמזהה 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
Objective-C
// 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)
Objective-C
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)
Objective-C
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 } }
Objective-C
- (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 )
Objective-C
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
Objective-C
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 // ... }
Objective-C
[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 } }
Objective-C
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
(מופעל כברירת מחדל).שקול לצלם תמונות ברזולוציה נמוכה יותר. עם זאת, זכור גם את דרישות ממדי התמונה של ממשק API זה.
- מצערת קוראת לגלאי. אם מסגרת וידאו חדשה הופכת לזמינה בזמן שהגלאי פועל, שחרר את המסגרת.
- אם אתה משתמש בפלט של הגלאי כדי לשכב גרפיקה על תמונת הקלט, תחילה קבל את התוצאה מ-ML Kit, ולאחר מכן עבד את התמונה ואת שכבת העל בצעד אחד. על ידי כך, אתה מעבד למשטח התצוגה רק פעם אחת עבור כל מסגרת קלט. ראה את המחלקות previewOverlayView ו- FIRDetectionOverlayView באפליקציה לדוגמה לראווה לדוגמא.