המשימה 'מסווג תמונות' מאפשרת לכם לסווג תמונות. אפשר להשתמש במשימה הזו כדי לזהות מה תמונה מייצגת מתוך קבוצת קטגוריות שהוגדרה בזמן האימון. ההוראות הבאות מראות איך להשתמש במסווג התמונות באפליקציות ל-iOS. דוגמת הקוד שמתוארת בהוראות האלו זמינה ב-GitHub.
אפשר לראות את המשימה הזו בהדגמה של האינטרנט. בסקירה הכללית תוכלו לקרוא עוד על היכולות, המודלים ואפשרויות ההגדרה של המשימה הזו.
קוד לדוגמה
הקוד לדוגמה של Tasks ב-MediaPipe הוא הטמעה בסיסית של אפליקציית סיווג התמונות ל-iOS. בדוגמה נעשה שימוש במצלמה במכשיר iOS פיזי כדי לסווג אובייקטים באופן רציף, ואפשר גם להשתמש בתמונות ובסרטונים מגלריית המכשיר כדי לסווג אובייקטים.
אפשר להשתמש באפליקציה כנקודת התחלה לאפליקציה שלכם ל-iOS, או להתייחס אליה כשמשנים אפליקציה קיימת. הקוד לדוגמה של מסווג התמונות מתארח ב-GitHub.
להורדת הקוד
בהוראות הבאות מוסבר איך ליצור עותק מקומי של הקוד לדוגמה באמצעות כלי שורת הפקודה git.
כדי להוריד את הקוד לדוגמה:
משכפלים את מאגר ה-Git באמצעות הפקודה הבאה:
git clone https://github.com/google-ai-edge/mediapipe-samples
אפשר גם להגדיר את מכונת ה-Git לשימוש בקופה עם גישה מצומצמת, כך שיהיו לכם רק את הקבצים של האפליקציה לדוגמה של מסווג התמונות:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/image_classification/ios/
אחרי שיוצרים גרסה מקומית של הקוד לדוגמה, אפשר להתקין את ספריית המשימות MediaPipe, לפתוח את הפרויקט באמצעות Xcode ולהריץ את האפליקציה. הוראות מופיעות במדריך ההגדרה ל-iOS.
רכיבים מרכזיים
הקבצים הבאים מכילים את הקוד החיוני לאפליקציה לדוגמה של מסווג התמונות:
- ImageClassifierService.swift: הפעלת מסווג התמונות, טיפול בבחירת המודל והפעלת ההסקה על נתוני הקלט.
- CameraViewController.swift: הטמעה של ממשק המשתמש עבור מצב הקלט של פיד המצלמה בשידור חי והצגת התוצאות באופן חזותי.
- MediaLibraryViewController.swift הטמעה של ממשק המשתמש עבור מצב קלט תמונה וסרטון וידאו והצגת התוצאות באופן חזותי.
הגדרה
בקטע הזה מתוארים השלבים העיקריים להגדרת סביבת הפיתוח ופרויקטים בקוד לשימוש במסווג התמונות. במדריך ההגדרה ל-iOS תוכלו לקרוא מידע כללי על הגדרת סביבת הפיתוח לשימוש במשימות MediaPipe, כולל הדרישות לגרסת הפלטפורמה.
יחסי תלות
מסווג התמונות משתמש בספרייה MediaPipeTasksVision
, שאותה צריך להתקין באמצעות CocoaPods. הספרייה תואמת גם לאפליקציות Swift ו-Objective-C ואין צורך בהגדרות נוספות ספציפיות לשפה.
הוראות להתקנת CocoaPods ב-macOS מפורטות במדריך ההתקנה של CocoaPods.
במאמר שימוש ב-CocoaPods מוסבר איך ליצור Podfile
עם ה-Pods שדרושים לאפליקציה.
מוסיפים את הרצף של MediaPipeTasksVision ב-Podfile
באמצעות הקוד הבא:
target 'MyImageClassifierApp' do
use_frameworks!
pod 'MediaPipeTasksVision'
end
אם האפליקציה שלכם כוללת יעדים של בדיקת יחידות, עיינו במדריך ההגדרה ל-iOS למידע נוסף על הגדרת Podfile
.
דגם
כדי לבצע את המשימה של מסווג תמונות של MediaPipe צריך מודל מאומן שתואם למשימה הזו. מידע נוסף על המודלים המאומנים שזמינים למסווג התמונות זמין בקטע 'מודלים', בסקירה הכללית על המשימות.
בוחרים מודל ומורידים אותו, ומוסיפים אותו לספריית הפרויקט באמצעות Xcode. לקבלת הוראות להוספת קבצים לפרויקט Xcode, קראו את המאמר ניהול קבצים ותיקיות בפרויקט Xcode.
השתמשו במאפיין BaseOptions.modelAssetPath
כדי לציין את הנתיב למודל ב-App Bundle. בקטע הבא מופיע קוד לדוגמה.
יצירת המשימה
כדי ליצור את המשימה 'מסווג תמונות', אפשר להפעיל אחד מהמאתחלים שלה. המאתחל ImageClassifier(options:)
מגדיר ערכים לאפשרויות הגדרה, כולל מצב ריצה, לוקאל של שמות מוצגים, מספר מקסימלי של תוצאות, סף מהימנות, רשימת היתרים של קטגוריות ורשימת ישויות שנחסמו.
אם אתם לא צריכים מסווג תמונות עם אפשרויות הגדרה מותאמות אישית, תוכלו להשתמש במאתחל ImageClassifier(modelPath:)
כדי ליצור מסווג תמונות עם אפשרויות ברירת המחדל. למידע נוסף על אפשרויות ההגדרה, ראו סקירה כללית של ההגדרות.
במשימה של מסווג התמונות יש 3 סוגים של נתוני קלט: תמונות סטילס, קובצי וידאו וסטרימינג של וידאו בשידור חי. כברירת מחדל, ImageClassifier(modelPath:)
מאתחל משימה עבור תמונות סטילס. אם רוצים שהמשימה תתחיל לעבד קובצי וידאו או שידורים חיים, אפשר להשתמש ב-ImageClassifier(options:)
כדי לציין את מצב ההפעלה של הסרטון או השידור החי. במצב של השידור החי נדרשת גם אפשרות ההגדרה הנוספת imageClassifierLiveStreamDelegate
, שמאפשרת למסווג התמונות לשלוח למקבל הגישה באופן אסינכרוני תוצאות של סיווג תמונות.
בחרו את הכרטיסייה שתואמת למצב הריצה כדי לראות איך יוצרים את המשימה ומריצים את ההסקה.
Swift
תמונה
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ImageClassifierOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .image options.maxResults = 5 let imageClassifier = try ImageClassifier(options: options)
וידאו
import MediaPipeTasksVision let modelPath = Bundle.main.path(forResource: "model", ofType: "tflite") let options = ImageClassifierOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .video options.maxResults = 5 let imageClassifier = try ImageClassifier(options: options)
סטרימינג בשידור חי
import MediaPipeTasksVision // Class that conforms to the `ImageClassifierLiveStreamDelegate` protocol and // implements the method that the image classifier calls once it // finishes performing classification on each input frame. class ImageClassifierResultProcessor: NSObject, ImageClassifierLiveStreamDelegate { func imageClassifier( _ imageClassifier: ImageClassifier, didFinishClassification result: ImageClassifierResult?, timestampInMilliseconds: Int, error: Error?) { // Process the image classifier result or errors here. } } let modelPath = Bundle.main.path( forResource: "model", ofType: "tflite") let options = ImageClassifierOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .liveStream options.maxResults = 5 // Assign an object of the class to the `imageClassifierLiveStreamDelegate` // property. let processor = ImageClassifierResultProcessor() options.imageClassifierLiveStreamDelegate = processor let imageClassifier = try ImageClassifier(options: options)
Objective-C
תמונה
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeImage; options.maxResults = 5; MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options error:nil];
וידאו
@import MediaPipeTasksVision; NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeVideo; options.maxResults = 5; MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options error:nil];
סטרימינג בשידור חי
@import MediaPipeTasksVision; // Class that conforms to the `MPPImageClassifierLiveStreamDelegate` protocol // and implements the method that the image classifier calls once it finishes // performing classification on each input frame. @interface APPImageClassifierResultProcessor : NSObject@end @implementation APPImageClassifierResultProcessor - (void)imageClassifier:(MPPImageClassifier *)imageClassifier didFinishClassificationWithResult:(MPPImageClassifierResult *)imageClassifierResult timestampInMilliseconds:(NSInteger)timestampInMilliseconds error:(NSError *)error { // Process the image classifier result or errors here. } @end NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model" ofType:@"tflite"]; MPPImageClassifierOptions *options = [[MPPImageClassifierOptions alloc] init]; options.baseOptions.modelAssetPath = modelPath; options.runningMode = MPPRunningModeLiveStream; options.maxResults = 5; // Assign an object of the class to the `imageClassifierLiveStreamDelegate` // property. APPImageClassifierResultProcessor *processor = [APPImageClassifierResultProcessor new]; options.imageClassifierLiveStreamDelegate = processor; MPPImageClassifier *imageClassifier = [[MPPImageClassifier alloc] initWithOptions:options error:nil];
אפשרויות תצורה
המשימה הזו כוללת את אפשרויות ההגדרה הבאות לאפליקציות ל-iOS:
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
runningMode |
מגדיר את מצב הריצה של המשימה. יש שלושה מצבים: IMAGE: המצב שמאפשר קלט של תמונה יחידה. סרטון: המצב של פריימים מפוענחים בסרטון. LIVE_STREAM: המצב לשידור חי של נתוני קלט, למשל ממצלמה. במצב הזה, יש להפעיל את resultListener כדי להגדיר האזנה לקבלת תוצאות באופן אסינכרוני. |
{RunningMode.image, RunningMode.video, RunningMode.liveStream } |
RunningMode.image |
displayNamesLocale |
ההגדרה הזו מגדירה את השפה של התוויות שישמשו בשמות המוצגים שבמטא-נתונים של מודל המשימה, אם זמין. ברירת המחדל היא en לאנגלית. אפשר להוסיף תוויות שמותאמות לשוק המקומי למטא-נתונים של מודל מותאם אישית באמצעות TensorFlow Lite Metadata Writer API |
קוד שפה | en |
maxResults |
מגדיר את המספר המקסימלי האופציונלי של תוצאות סיווג עם התוצאות המובילות. אם הערך הוא פחות מ-0, יוחזרו כל התוצאות הזמינות. | מספרים חיוביים כלשהם | -1 |
scoreThreshold |
מגדירה את סף הציון של החיזוי (אם יש כזה) שמבטל את הסף שצוין במטא-נתונים של המודל. תוצאות מתחת לערך הזה נדחות. | כל מספר ממשי (float) | לא הוגדר |
categoryAllowlist |
מגדיר את הרשימה האופציונלית של שמות קטגוריות מותרות. אם השדה לא ריק, תוצאות הסיווג שבהן שם הקטגוריה לא נמצא בקבוצה הזו יסוננו. המערכת מתעלמת משמות קטגוריות כפולים או לא ידועים.
האפשרות הזו קיימת רק ב-categoryDenylist ומשתמשת בשתיהן כדי ליצור שגיאה. |
כל מחרוזת | לא הוגדר |
categoryDenylist |
מגדיר את הרשימה האופציונלית של שמות קטגוריות שאינם מותרים. אם השדה לא ריק, תוצאות הסיווג שבהן שם הקטגוריה נמצא בקבוצה הזו יסוננו. המערכת מתעלמת משמות קטגוריות כפולים או לא ידועים. האפשרות הזו בלעדית באופן הדדי ל-categoryAllowlist , והשימוש בשתי האפשרויות יוביל לשגיאה. |
כל מחרוזת | לא הוגדר |
resultListener |
מגדיר את אוזן התוצאות לקבל את תוצאות הסיווג באופן אסינכרוני כאשר מסווג התמונות נמצא במצב של שידור חי. אפשר להשתמש באפשרות הזו רק כשמצב הריצה מוגדר ל-LIVE_STREAM |
לא רלוונטי | לא הוגדר |
הגדרות השידור החי
כשמצב ההרצה מוגדר כשידור חי, למסווג התמונות נדרשת אפשרות הגדרה נוספת imageClassifierLiveStreamDelegate
, שמאפשרת למסווג לספק תוצאות סיווג באופן אסינכרוני. מקבל הגישה מיישם את השיטה imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:)
, שאליה מסווג התמונות, אחרי עיבוד תוצאות הסיווג של כל פריים.
שם האפשרות | תיאור | טווח ערכים | ערך ברירת מחדל |
---|---|---|---|
imageClassifierLiveStreamDelegate |
מאפשר למסווג התמונות לקבל תוצאות סיווג באופן אסינכרוני במצב חי. המחלקה שהמכונה שלה מוגדרת למאפיין הזה צריכה
להטמיע את
ה-method
imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:) . |
לא רלוונטי | לא הוגדר |
הכנת נתונים
צריך להמיר את תמונת הקלט או את המסגרת לאובייקט MPImage
לפני ההעברה למסווג התמונות. ב-MPImage
יש תמיכה בסוגים שונים של פורמטים של תמונות ב-iOS, ותוכלו להשתמש בהם בכל מצב פעיל כדי להסיק את הנתונים. מידע נוסף על MPImage
זמין ב-MPImage API
בוחרים פורמט תמונה ל-iOS בהתאם לתרחיש לדוגמה ולמצב ההרצה של האפליקציה.MPImage
מקבל את הפורמטים UIImage
של התמונות ל-iOS, CVPixelBuffer
ו-CMSampleBuffer
ל-iOS.
UIImage
הפורמט UIImage
מתאים במיוחד למצבי הריצה הבאים:
תמונות: אפשר להמיר תמונות מ-App Bundle, מגלריית משתמשים או ממערכת קבצים בפורמט
UIImage
לאובייקטMPImage
.סרטונים: אפשר להשתמש ב-AVAssetImageGenerator כדי לחלץ פריימים של סרטונים לפורמט CGImage, ולהמיר אותם ל-
UIImage
תמונות.
Swift
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(uiImage: image)
Objective-C
// Load an image on the user's device as an iOS `UIImage` object. // Convert the `UIImage` object to a MediaPipe's Image object having the default // orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
הדוגמה מפעילה MPImage
עם כיוון ברירת המחדל UIImage.Orientation.Up. אפשר לאתחל MPImage
עם כל אחד מהערכים הנתמכים של UIImage.Orientation. במסווג התמונות אין תמיכה בכיוונים משוכפלים כמו .upMirrored
, .downMirrored
, .leftMirrored
, .rightMirrored
.
מידע נוסף על UIImage
זמין במסמכי התיעוד למפתחים של UIImage של Apple.
CVPixelBuffer
הפורמט CVPixelBuffer
מתאים מאוד לאפליקציות שיוצרות פריימים ומשתמשות במסגרת CoreImage של iOS לצורך עיבוד.
הפורמט CVPixelBuffer
מתאים במיוחד למצבי הריצה הבאים:
תמונות: אפשר לשלוח אפליקציות שיוצרות תמונות
CVPixelBuffer
אחרי עיבוד באמצעות מסגרתCoreImage
של iOS למסווג התמונות במצב הרצה של תמונות.סרטונים: אפשר להמיר פריימים של וידאו לפורמט
CVPixelBuffer
לצורך עיבוד, ולשלוח אותם למסווג התמונות במצב וידאו.בשידור חי: אפליקציות שמשתמשות במצלמת iOS ליצירת פריימים יכולות לעבור המרה לפורמט
CVPixelBuffer
לעיבוד, לפני שיישלחו למסווג התמונות במצב שידור חי.
Swift
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(pixelBuffer: pixelBuffer)
Objective-C
// Obtain a CVPixelBuffer. // Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
מידע נוסף על CVPixelBuffer
זמין במסמכי התיעוד למפתחים של CVPixelBuffer Apple.
CMSampleBuffer
הפורמט CMSampleBuffer
שומר דוגמאות מדיה מסוג מדיה אחידה, והוא מתאים למצב ההרצה של השידור החי. פריימים חיים ממצלמות iOS נשלחים באופן אסינכרוני בפורמט CMSampleBuffer
על ידי iOS AVCaptureVideoDataOutput.
Swift
// Obtain a CMSampleBuffer. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default // orientation `UIImage.Orientation.up`. let image = try MPImage(sampleBuffer: sampleBuffer)
Objective-C
// Obtain a `CMSampleBuffer`. // Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the // default orientation `UIImageOrientationUp`. MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
מידע נוסף על CMSampleBuffer
זמין במסמכי התיעוד למפתחים של Apple CMSampleBuffer.
הרצת המשימה
כדי להפעיל את מסווג התמונות, צריך להשתמש ב-method classify()
הספציפית למצב הריצה שהוקצה:
- תמונת סטילס:
classify(image:)
- סרטון:
classify(videoFrame:timestampInMilliseconds:)
- שידור חי:
classifyAsync(image:timestampInMilliseconds:)
מסווג התמונות מחזיר את הקטגוריות האפשריות של האובייקט בתוך התמונה או המסגרת של הקלט.
דוגמאות הקוד הבאות מראות דוגמאות בסיסיות להרצת מסווג התמונות במצבי הריצה השונים:
Swift
תמונה
let result = try imageClassifier.classify(image: image)
וידאו
let result = try imageClassifier.classify( videoFrame: image, timestampInMilliseconds: timestamp)
סטרימינג בשידור חי
try imageClassifier.classifyAsync( image: image, timestampInMilliseconds: timestamp)
Objective-C
תמונה
MPPImageClassifierResult *result = [imageClassifier classifyImage:image error:nil];
וידאו
MPPImageClassifierResult *result = [imageClassifier classifyVideoFrame:image timestampInMilliseconds:timestamp error:nil];
סטרימינג בשידור חי
BOOL success = [imageClassifier classifyAsyncImage:image timestampInMilliseconds:timestamp error:nil];
קוד מסווג התמונות מציג את ההטמעות של כל אחד מהמצבים האלה בפירוט רב יותר: classify(image:)
, classify(videoFrame:timestampInMilliseconds:)
ו-classifyAsync(image:timestampInMilliseconds:)
. הקוד לדוגמה מאפשר למשתמשים לעבור בין מצבי עיבוד שלא נדרשים בתרחיש לדוגמה שלכם.
שימו לב לנקודות הבאות:
כשמריצים במצב וידאו או במצב שידור חי, צריך גם לציין את חותמת הזמן של מסגרת הקלט למשימה של מסווג התמונות.
כשעובדים במצב תמונה או וידאו, המשימה 'מסווג תמונות' חוסמת את השרשור הנוכחי עד לסיום העיבוד של התמונה או המסגרת. כדי למנוע את חסימת ה-thread הנוכחי, צריך לבצע את העיבוד ב-thread הנוכחי ברקע באמצעות frameworks של iOS Dispatch או של NSOperation.
במצב שידור חי, המשימה של מסווג התמונות חוזרת מיד ולא חוסמת את השרשור הנוכחי. הוא מפעיל את ה-method
imageClassifier(_:didFinishClassification:timestampInMilliseconds:error:)
עם תוצאת הסיווג אחרי העיבוד של כל מסגרת קלט. מסווג התמונות מפעיל את השיטה הזו באופן אסינכרוני בתור ייעודי לשליחה טורית. כדי להציג תוצאות בממשק המשתמש, צריך לשלוח את התוצאות לתור הראשי אחרי עיבוד התוצאות. אם נשלחת קריאה לפונקציהclassifyAsync
כשמשימה של מסווג תמונות עסוקה בעיבוד פריים אחר, מסווג התמונות מתעלם ממסגרת הקלט החדשה.
טיפול בתוצאות והצגתן
כשמריצים את ההסקה, המשימה של מסווג התמונות מחזירה אובייקט ImageClassifierResult
שמכיל רשימת קטגוריות אפשריות של האובייקטים בתמונה או במסגרת הקלט.
בדוגמה הבאה אפשר לראות את נתוני הפלט מהמשימה:
ImageClassifierResult:
Classifications #0 (single classification head):
head index: 0
category #0:
category name: "/m/01bwb9"
display name: "Passer domesticus"
score: 0.91406
index: 671
category #1:
category name: "/m/01bwbt"
display name: "Passer montanus"
score: 0.00391
index: 670
התוצאה הזו התקבלה על ידי הפעלת Bird Classifier על:
הקוד לדוגמה של מסווג התמונות שמדגים איך להציג את תוצאות הסיווג שהוחזרו מהמשימה מופיע בדוגמה לקוד.