הוספת תוויות לתמונות באמצעות מודל שעבר אימון AutoML ב-iOS
אחרי שתאמנים את המודל באמצעות AutoML Vision Edge, אפשר להשתמש בו באפליקציה כדי להוסיף תוויות לתמונות.
יש שתי דרכים לשלב מודלים שעברו אימון מ-AutoML Vision Edge. אפשר לקבץ את המודל על ידי העתקת קובצי המודל לפרויקט Xcode, או יכולים להוריד אותו באופן דינמי מ-Firebase.
אפשרויות לחבילה של מודלים | |
---|---|
מקובצות באפליקציה שלך |
|
באירוח Firebase |
|
רוצה לנסות?
- מומלץ לשחק עם האפליקציה לדוגמה כדי .
לפני שמתחילים
1. כוללים את ספריות ML Kit ב-Podfile:לשילוב מודל עם האפליקציה:
pod 'GoogleMLKit/ImageLabelingAutoML'כדי להוריד מודל באופן דינמי מ-Firebase, צריך להוסיף את הקוד
LinkFirebase
של תלות:
pod 'GoogleMLKit/ImageLabelingAutoML' pod 'GoogleMLKit/LinkFirebase'2. אחרי שמתקינים או מעדכנים את קבוצות ה-Pod של הפרויקט, פותחים את פרויקט Xcode באמצעות ה
.xcworkspace
קוד> שלו. יש תמיכה ב-ML Kit ב-Xcode
מגרסה 13.2.1 ואילך.
3. אם אתם רוצים להוריד מודל, צריך לוודא
מוסיפים את Firebase לפרויקט iOS,
אם עדיין לא עשיתם זאת. אין צורך לעשות זאת כשהחבילה של
מודל טרנספורמר.
1. טעינת המודל
הגדרת מקור למודל מקומי
כדי לצרף את המודל לאפליקציה:1. חילוץ המודל והמטא-נתונים שלו מארכיון ה-ZIP שהורדתם ממסוף Firebase לתיקייה:
your_model_directory |____dict.txt |____manifest.json |____model.tfliteכל שלושת הקבצים חייבים להיות באותה תיקייה. מומלץ להשתמש בקבצים כפי שהורדתם אותם, בלי לבצע שינויים (כולל שמות הקבצים).
2. מעתיקים את התיקייה לפרויקט Xcode ומקפידים לבחור לשם כך, צרו הפניות לתיקיות. קובץ המודל והמטא-נתונים ייכללו ב-App Bundle ויהיו זמינים ל-ML Kit.
3. יוצרים אובייקט
AutoMLImageLabelerLocalModel
, מציינים את הנתיב אל
קובץ מניפסט של מודל:
Swift
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return } let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)
Objective-C
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKAutoMLImageLabelerLocalModel *localModel = [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];
הגדרת מקור מודל שמתארח ב-Firebase
כדי להשתמש במודל שמתארח מרחוק, צריך ליצור AutoMLImageLabelerRemoteModel
, שמציין את השם שהקציתם למודל כשפרסמתם אותו:
Swift
let remoteModel = AutoMLImageLabelerRemoteModel( name: "your_remote_model" // The name you assigned in // the Firebase console. )
Objective-C
MLKAutoMLImageLabelerRemoteModel *remoteModel = [[MLKAutoMLImageLabelerRemoteModel alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console.
לאחר מכן, מתחילים את המשימה של הורדת המודל, ומציינים את התנאים שבהם שרוצים לאפשר את ההורדה שלהם. אם הדגם לא נמצא במכשיר, או אם של המודל זמינה, המשימה תוריד באופן אסינכרוני מ-Firebase:
Swift
let downloadConditions = ModelDownloadConditions( allowsCellularAccess: true, allowsBackgroundDownloading: true ) let downloadProgress = ModelManager.modelManager().download( remoteModel, conditions: downloadConditions )
Objective-C
MLKModelDownloadConditions *downloadConditions = [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES allowsBackgroundDownloading:YES]; NSProgress *downloadProgress = [[MLKModelManager modelManager] downloadModel:remoteModel conditions:downloadConditions];
אפליקציות רבות מתחילות את משימת ההורדה בקוד האתחול שלהן, אבל תוכלו לעשות זאת בכל שלב לפני שתצטרכו להשתמש במודל.
יצירת מתייג לתמונה מהמודל
אחרי שמגדירים את המקורות של המודלים, צריך ליצור אובייקט ImageLabeler
מאובייקט
מהם.
אם יש לכם רק מודל באריזה מקומית, פשוט יוצרים מתייגים
אובייקט אחד (AutoMLImageLabelerLocalModel
) והגדרת רמת הסמך
הסף הנדרש (למידע נוסף, תוכלו לקרוא על הערכת המצב:
Swift
let options = AutoMLImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Firebase console // to determine an appropriate value. let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKAutoMLImageLabelerOptions *options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); // Evaluate your model in the Firebase console // to determine an appropriate value. MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
אם יש לך מודל שמתארח מרחוק, עליך לבדוק שהוא
שהורדתם לפני שהפעלתם אותו. אפשר לבדוק את סטטוס ההורדה של המודל
משימה באמצעות שיטת isModelDownloaded
(remoteModel:) של מנהל המודלים.
למרות שצריך לאשר זאת רק לפני הפעלת המתייג, אם
יש להם גם מודל שמתארח מרחוק וגם מודל בחבילות מקומיות, זה עלול ליצור
לבצע את הבדיקה הזו כשמממשים את ImageLabeler
: יוצרים
ממתייג מהמודל המרוחק, אם הוא כבר הורד, ומהמודל המקומי
אחרת.
Swift
var options: AutoMLImageLabelerOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = AutoMLImageLabelerOptions(remoteModel: remoteModel) } else { options = AutoMLImageLabelerOptions(localModel: localModel) } options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Firebase console // to determine an appropriate value. let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKAutoMLImageLabelerOptions *options; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel]; } options.confidenceThreshold = @(0.0); // Evaluate your model in the Firebase console // to determine an appropriate value. MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];
אם יש לך רק מודל שמתארח מרחוק, עליך להשבית את התכונה שקשורה למודלים פונקציונליות - לדוגמה, הצגה באפור או הסתרה של חלק מממשק המשתמש - עד מוודאים שבוצעה הורדה של המודל.
כדי לראות את סטטוס ההורדה של המודל, אפשר לצרף תצפיתנים לברירת המחדל
מרכז ההתראות. חשוב להשתמש בהתייחסות חלשה אל self
בצופה
מכיוון שהורדות עשויות להימשך זמן מה, ואובייקט המקור יכול להיות
בחינם עד לסיום ההורדה. לדוגמה:
Swift
NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidSucceed, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel, model.name == "your_remote_model" else { return } // The model was downloaded and is available on the device } NotificationCenter.default.addObserver( forName: .mlkitModelDownloadDidFail, object: nil, queue: nil ) { [weak self] notification in guard let strongSelf = self, let userInfo = notification.userInfo, let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue] as? RemoteModel else { return } let error = userInfo[ModelDownloadUserInfoKey.error.rawValue] // ... }
Objective-C
__weak typeof(self) weakSelf = self; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidSucceedNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel]; if ([model.name isEqualToString:@"your_remote_model"]) { // The model was downloaded and is available on the device } }]; [NSNotificationCenter.defaultCenter addObserverForName:MLKModelDownloadDidFailNotification object:nil queue:nil usingBlock:^(NSNotification *_Nonnull note) { if (weakSelf == nil | note.userInfo == nil) { return; } __strong typeof(self) strongSelf = weakSelf; NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError]; }];
2. הכנת תמונת הקלט
יצירת אובייקט 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. הפעלה של מתייג התמונות
באופן אסינכרוני:
Swift
imageLabeler.process(image) { labels, error in guard error == nil, let labels = labels, !labels.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[imageLabeler processImage:image completion:^(NSArray*_Nullable labels, NSError *_Nullable error) { if (labels.count == 0) { // Handle the error. return; } // Show results. }];
סינכרוני:
Swift
var labels: [ImageLabel] do { labels = try imageLabeler.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray*labels = [imageLabeler resultsInImage:image error:&error]; // Show results or handle the error.
4. אחזור מידע על אובייקטים מתויגים
אם הפעולה של הוספת תווית לתמונות מצליחה, היא מחזירה מערך שלImageLabel
כל ImageLabel
מייצג משהו
שמסומן בתמונה. אפשר לקבל תיאור טקסט של כל תווית (אם הוא זמין
המטא-נתונים של קובץ המודל TensorFlow Lite, ציון המהימנות והאינדקס.
לדוגמה:
Swift
for label in labels { let labelText = label.text let confidence = label.confidence let index = label.index }
Objective-C
for (MLKImageLabel *label in labels) { NSString *labelText = label.text; float confidence = label.confidence; NSInteger index = label.index; }
טיפים לשיפור הביצועים בזמן אמת
כדי להוסיף תווית לתמונות באפליקציה בזמן אמת, צריך לפעול לפי השלבים הבאים כדי להשיג את קצבי הפריימים הטובים ביותר:
- כדי לעבד פריימים של וידאו, צריך להשתמש ב-API הסינכרוני
results(in:)
של הגלאי. שיחת טלפון שיטה זו מAVCaptureVideoDataOutputSampleBufferDelegate
פונקציהcaptureOutput(_, didOutput:from:)
לקבלת תוצאות בסרטון הנתון באופן סינכרוני מסגרת. שמור את שלAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
בתורtrue
כדי לווסת שיחות למזהה. אם תג חדש פריים הווידאו יהפוך לזמין כשהגלאי פועל, הוא יוסר. - אם משתמשים בפלט של הגלאי כדי להציג גרפיקה בשכבת-על מקבלים קודם את התוצאה מ-ML Kit ואז מעבדים את התמונה וליצור שכבת-על בשלב אחד. כך תוכלו להציג את משטח המסך רק פעם אחת לכל מסגרת קלט שעברה עיבוד. אפשר לעיין בתצוגה updatePreviewOverlayViewWithLastFrame בדוגמת המדריך למתחילים ל-ML Kit.