אפשר להשתמש ב-ML Kit כדי לזהות אובייקטים בפריימים רצופים של וידאו ולעקוב אחריהם.
כשמעבירים תמונה לערכת ML, היא מזהה עד חמישה אובייקטים בתמונה וכן המיקום של כל אובייקט בתמונה. בעת זיהוי אובייקטים ב: וידאו בסטרימינג. לכל אובייקט יש מזהה ייחודי שאפשר להשתמש בו כדי לעקוב אחרי האובייקט ממסגרת למסגרת. אפשר גם להפעיל אובייקט גס של סיווג, שמוסיף תוויות לאובייקטים עם תיאורים רחבים של קטגוריות.
רוצה לנסות?
- מומלץ לשחק עם האפליקציה לדוגמה כדי .
- לצפייה בתצוגה של עיצוב חומרים (Material Design) אפליקציה להטמעה מקצה לקצה של ה-API הזה.
לפני שמתחילים
- כוללים ב-Podfile את רצפי ה-ML Kit הבאים:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- אחרי שמתקינים או מעדכנים את קבוצות ה-Pod של הפרויקט, פותחים את פרויקט Xcode באמצעות
.xcworkspace
יש תמיכה ב-ML Kit ב-Xcode מגרסה 12.4 ואילך.
1. הגדרת מזהה האובייקטים
כדי לזהות אובייקטים ולעקוב אחריהם, קודם צריך ליצור מופע של
ObjectDetector
ואפשר גם לציין כל הגדרות מזהה שרוצים
שינוי מברירת המחדל.
מגדירים את מזהה האובייקטים לתרחיש לדוגמה שלכם באמצעות אובייקט
ObjectDetectorOptions
. אפשר לשנות את האפשרויות הבאות ההגדרות:הגדרות של מזהה אובייקטים מצב זיהוי .stream
(ברירת מחדל) |.singleImage
במצב סטרימינג (ברירת מחדל), מזהה האובייקטים פועל כשהטמפרטורה נמוכה מאוד זמן אחזור, אבל הן עשויות להניב תוצאות חלקיות (למשל, תוצאות שלא צוינו) תיבות תוחמות או קטגוריות) בהפעלות הראשונות של את גלאי. כמו כן, במצב שידור, הגלאי מקצה מעקב מזהים של אובייקטים, שאפשר להשתמש בהם כדי לעקוב אחרי אובייקטים בין מסגרות. כדאי להשתמש במצב הזה כשרוצים לעקוב אחרי אובייקטים, או כשזמן האחזור קצר הוא חשוב, למשל כשמעבדים זרמי וידאו בזמן האימון.
במצב תמונה יחידה, מזהה האובייקטים מחזיר את התוצאה אחרי שהתיבה התוחמת של האובייקט נקבעה. אם תפעילו גם את הוא מחזיר את התוצאה אחרי שהתיבה התוחמת (bounding box) שתי תוויות הקטגוריה זמינות. כתוצאה מכך, זמן האחזור עשוי להיות ארוך יותר. כמו כן, במצב תמונה יחידה, מעקב לא מוקצה לו מזהים. מומלץ להשתמש במצב הזה אם זמן האחזור אינו קריטי לא רוצים לטפל בתוצאות חלקיות.
זיהוי של מספר אובייקטים ומעקב אחריהם false
(ברירת מחדל) |true
האם לזהות ולעקוב אחר עד חמישה אובייקטים או רק את רובם אובייקט בולט (ברירת מחדל).
סיווג אובייקטים false
(ברירת מחדל) |true
האם לסווג את האובייקטים שזוהו לקטגוריות גסות. כשההגדרה מופעלת, מזהה האובייקטים מסווג את האובייקטים הקטגוריות הבאות: מוצרי אופנה, אוכל, מוצרים לבית, מקומות שונים וצמחים.
ה-API לזיהוי אובייקטים ולמעקב מותאם לשני השימושים העיקריים האלה במקרים:
- זיהוי בזמן אמת ומעקב אחרי האובייקט הבולט ביותר במצלמה את העינית.
- זיהוי של מספר אובייקטים בתמונה סטטית.
כדי להגדיר את ה-API לתרחישים לדוגמה האלה:
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- מקבלים מופע של
ObjectDetector
:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. הכנת תמונת הקלט
כדי לזהות אובייקטים ולעקוב אחריהם, מבצעים את הפעולות הבאות בכל תמונה או פריים בסרטון.
אם הפעלתם את מצב הסטרימינג, צריך ליצור VisionImage
אובייקטים מ-
CMSampleBuffer
שנ'.
יצירת אובייקט VisionImage
באמצעות UIImage
או
CMSampleBuffer
אם משתמשים ב-UIImage
, צריך לבצע את השלבים הבאים:
- יוצרים אובייקט
VisionImage
באמצעותUIImage
. חשוב להקפיד לציין.orientation
נכון.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
אם משתמשים ב-CMSampleBuffer
, צריך לבצע את השלבים הבאים:
-
לציין את הכיוון של נתוני התמונה שנכללים ברכיב
CMSampleBuffer
כדי לקבל את הכיוון של התמונה:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- יוצרים אובייקט
VisionImage
באמצעות אובייקט וכיווןCMSampleBuffer
:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. עיבוד התמונה
מעבירים את הערךVisionImage
לאחד מעיבוד התמונה של מזהה האובייקטים
שיטות. אפשר להשתמש בשיטה process(image:)
האסינכרונית או ב-
שיטת results()
סינכרונית.
כדי לזהות אובייקטים באופן אסינכרוני:
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
כדי לזהות אובייקטים באופן סינכרוני:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. קבלת מידע על אובייקטים שזוהו
אם הקריאה למעבד התמונות מצליחה, היא מעבירה רשימה שלObject
שניות ל-handler של השלמת הצפייה או מחזירה את הרשימה, בהתאם
אם קראתם לשיטה האסינכרונית או הסנכרונית.
כל Object
מכיל את המאפיינים (properties) הבאים:
frame |
CGRect שמציין את המיקום של האובייקט
תמונה. |
trackingID |
מספר שלם שמזהה את האובייקט בתמונות, או 'nil' ב- מצב של תמונה יחידה. |
labels |
מערך תוויות שמתארות את האובייקט שהמזהה מחזיר.
הנכס ריק אם אפשרות המזהה
הערך של shouldEnableClassification מוגדר ל-false .
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.joined(separator:"\n") }
Objective-C
// The list of detected objects contains one item if multiple // object detection wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; ... } }
שיפור השימושיות והביצועים
כדי ליהנות מחוויית המשתמש הטובה ביותר, מומלץ לפעול לפי ההנחיות הבאות באפליקציה:
- ההצלחה של זיהוי אובייקטים תלויה במורכבות הוויזואלית של האובייקט. לחשבון כדי שניתן יהיה לזהות אובייקטים עם מעט מאוד מאפיינים חזותיים, כך שתתפוס חלק גדול יותר מהתמונה. צריך לספק למשתמשים הנחיות לגבי לתיעוד קלט שפועל בצורה טובה עם סוגי האובייקטים שאתם רוצים לזהות.
- כשמשתמשים בסיווג, אם רוצים לזהות אובייקטים שלא נופלים ישירות לקטגוריות הנתמכות, להטמיע טיפול מיוחד במקרים לא ידועים אובייקטים.
כדאי גם לראות את Material Design אוסף תבניות לתכונות מבוססות-למידת מכונה.
כשמשתמשים במצב סטרימינג באפליקציה בזמן אמת, צריך לפעול לפי ההנחיות הבאות כדי להשיג את קצבי הפריימים הטובים ביותר:
- אין להשתמש בזיהוי אובייקטים מרובים במצב סטרימינג, כי רוב המכשירים לא מסוגל להפיק קצבי פריימים מתאימים.
- אפשר להשבית את הסיווג אם לא צריך אותו.
- כדי לעבד פריימים של וידאו, צריך להשתמש ב-API הסינכרוני
results(in:)
של הגלאי. שיחת טלפון שיטה זו מAVCaptureVideoDataOutputSampleBufferDelegate
פונקציהcaptureOutput(_, didOutput:from:)
לקבלת תוצאות בסרטון הנתון באופן סינכרוני מסגרת. שמור את שלAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
בתורtrue
כדי לווסת שיחות למזהה. אם תג חדש הפריים של הווידאו הופך להיות זמין כשהגלאי פועל, והוא יוסר. - אם משתמשים בפלט של הגלאי כדי להציג גרפיקה בשכבת-על מקבלים קודם את התוצאה מ-ML Kit ואז מעבדים את התמונה וליצור שכבת-על בשלב אחד. כך תוכלו להציג את משטח המסך רק פעם אחת לכל מסגרת קלט שעברה עיבוד. אפשר לעיין בתצוגה updatePreviewOverlayViewWithLastFrame בדוגמת המדריך למתחילים ל-ML Kit.