זיהוי ועקוב אחר אובייקטים עם ערכת ML ב-iOS

אתה יכול להשתמש ב-ML Kit כדי לזהות ולעקוב אחר אובייקטים על פני פריימים של וידאו.

כאשר אתה עובר תמונות ML Kit, ML Kit מחזיר, עבור כל תמונה, רשימה של עד חמישה אובייקטים שזוהו ומיקומם בתמונה. בעת זיהוי אובייקטים בזרמי וידאו, לכל אובייקט יש מזהה שבו אתה יכול להשתמש כדי לעקוב אחר האובייקט על פני תמונות. אתה יכול גם לאפשר סיווג אובייקט גס באופן אופציונלי, אשר מסמן אובייקטים עם תיאורי קטגוריות רחבים.

לפני שאתה מתחיל

  1. אם עדיין לא הוספת את Firebase לאפליקציה שלך, עשה זאת על ידי ביצוע השלבים במדריך לתחילת העבודה .
  2. כלול את ספריות ML Kit ב-Podfile שלך:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    לאחר שתתקין או תעדכן את ה-Pods של הפרויקט שלך, הקפד לפתוח את פרויקט Xcode שלך ​​באמצעות .xcworkspace שלו.
  3. באפליקציה שלך, ייבא את Firebase:

    מָהִיר

    import Firebase

    Objective-C

    @import Firebase;

1. הגדר את גלאי האובייקטים

כדי להתחיל לזהות ולעקוב אחר אובייקטים, תחילה צור מופע של VisionObjectDetector , אופציונלי לציין את כל הגדרות הגלאי שברצונך לשנות מברירת המחדל.

  1. הגדר את גלאי האובייקטים למקרה השימוש שלך עם אובייקט VisionObjectDetectorOptions . אתה יכול לשנות את ההגדרות הבאות:

    הגדרות גלאי אובייקטים
    מצב זיהוי .stream (ברירת מחדל) | .singleImage

    במצב זרם (ברירת מחדל), גלאי האובייקט פועל עם זמן אחזור נמוך מאוד, אך עלול להפיק תוצאות לא שלמות (כגון תיבות תוחמות או קטגוריה לא מוגדרת) בכמה הפעלות ראשונות של הגלאי. כמו כן, במצב זרם, הגלאי מקצה מזהי מעקב לאובייקטים, שבהם אתה יכול להשתמש כדי לעקוב אחר אובייקטים על פני מסגרות. השתמש במצב זה כאשר אתה רוצה לעקוב אחר אובייקטים, או כאשר זמן אחזור נמוך חשוב, כגון בעת ​​עיבוד זרמי וידאו בזמן אמת.

    במצב תמונה בודדת, גלאי האובייקטים ממתין עד שתיבה התוחמת של אובייקט מזוהה וקטגוריית (אם הפעלת סיווג) זמינות לפני החזרת תוצאה. כתוצאה מכך, זמן האחזור לזיהוי עשוי להיות גבוה יותר. כמו כן, במצב תמונה בודדת, מזהי מעקב אינם מוקצים. השתמש במצב זה אם זמן האחזור אינו קריטי ואתה לא רוצה להתמודד עם תוצאות חלקיות.

    זיהוי ומעקב אחר אובייקטים מרובים false (ברירת מחדל) | true

    האם לזהות ולעקוב אחר עד חמישה אובייקטים או רק האובייקט הבולט ביותר (ברירת מחדל).

    סיווג חפצים false (ברירת מחדל) | true

    האם לסווג אובייקטים שזוהו לקטגוריות גסות או לא. כאשר מופעל, גלאי האובייקטים מסווג אובייקטים לקטגוריות הבאות: מוצרי אופנה, מזון, מוצרים לבית, מקומות, צמחים ולא ידועים.

    ממשק ה-API לזיהוי ומעקב אובייקטים מותאם לשני מקרי שימוש הליבה האלה:

    • זיהוי ומעקב בזמן אמת אחר האובייקט הבולט ביותר בעינית המצלמה
    • זיהוי של מספר עצמים בתמונה סטטית

    כדי להגדיר את ה-API עבור מקרי שימוש אלה:

    מָהִיר

    // Live detection and tracking
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .stream
    options.shouldEnableMultipleObjects = false
    options.shouldEnableClassification = true  // Optional
    
    // Multiple object detection in static images
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .singleImage
    options.shouldEnableMultipleObjects = true
    options.shouldEnableClassification = true  // Optional
    

    Objective-C

    // Live detection and tracking
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeStream;
    options.shouldEnableMultipleObjects = NO;
    options.shouldEnableClassification = YES;  // Optional
    
    // Multiple object detection in static images
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeSingleImage;
    options.shouldEnableMultipleObjects = YES;
    options.shouldEnableClassification = YES;  // Optional
    
  2. קבל מופע של FirebaseVisionObjectDetector :

    מָהִיר

    let objectDetector = Vision.vision().objectDetector()
    
    // Or, to change the default settings:
    let objectDetector = Vision.vision().objectDetector(options: options)
    

    Objective-C

    FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector];
    
    // Or, to change the default settings:
    FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
    

2. הפעל את גלאי האובייקטים

כדי לזהות ולעקוב אחר אובייקטים, בצע את הפעולות הבאות עבור כל תמונה או פריים של וידאו. אם הפעלת את מצב הזרם, עליך ליצור אובייקטים של VisionImage מ- CMSampleBufferRef s.

  1. צור אובייקט VisionImage באמצעות UIImage או CMSampleBufferRef .

    כדי להשתמש UIImage :

    1. במידת הצורך, סובב את התמונה כך imageOrientation שלה יהיה .up .
    2. צור אובייקט VisionImage באמצעות UIImage המסובב כהלכה. אל תציין מטא נתונים כלשהם של סיבוב - יש להשתמש בערך ברירת המחדל, .topLeft .

      מָהִיר

      let image = VisionImage(image: uiImage)

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    כדי להשתמש ב- CMSampleBufferRef :

    1. צור אובייקט 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];
    2. צור אובייקט VisionImage באמצעות האובייקט CMSampleBufferRef והמטא נתונים של הסיבוב:

      מָהִיר

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. העבר את ה- VisionImage לאחת משיטות עיבוד התמונה של גלאי האובייקטים. אתה יכול להשתמש בשיטת process(image:) אסינכרונית או בשיטת results() .

    כדי לזהות אובייקטים באופן אסינכרוני:

    מָהִיר

    objectDetector.process(image) { detectedObjects, error in
      guard error == nil else {
        // Error.
        return
      }
      guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else {
        // No objects detected.
        return
      }
    
      // Success. Get object info here.
      // ...
    }
    

    Objective-C

    [objectDetector processImage:image
                      completion:^(NSArray<FIRVisionObject *> * _Nullable objects,
                                   NSError * _Nullable error) {
                        if (error == nil) {
                          return;
                        }
                        if (objects == nil | objects.count == 0) {
                          // No objects detected.
                          return;
                        }
    
                        // Success. Get object info here.
                        // ...
                      }];
    

    כדי לזהות אובייקטים באופן סינכרוני:

    מָהִיר

    var results: [VisionObject]? = nil
    do {
      results = try objectDetector.results(in: image)
    } catch let error {
      print("Failed to detect object with error: \(error.localizedDescription).")
      return
    }
    guard let detectedObjects = results, !detectedObjects.isEmpty else {
      print("Object detector returned no results.")
      return
    }
    
    // ...
    

    Objective-C

    NSError *error;
    NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image
                                                                   error:&error];
    if (error == nil) {
      return;
    }
    if (objects == nil | objects.count == 0) {
      // No objects detected.
      return;
    }
    
    // Success. Get object info here.
    // ...
    
  3. אם הקריאה למעבד התמונה מצליחה, הוא מעביר רשימה של VisionObject s למטפל ההשלמה או מחזיר את הרשימה, תלוי אם קראת לשיטה האסינכרונית או הסינכרונית.

    כל VisionObject מכיל את המאפיינים הבאים:

    frame CGRect המציין את מיקום האובייקט בתמונה.
    trackingID מספר שלם המזהה את האובייקט על פני תמונות. אפס במצב תמונה בודדת.
    classificationCategory הקטגוריה הגסה של האובייקט. אם לגלאי האובייקטים אין סיווג מופעל, זה תמיד .unknown .
    confidence ערך הביטחון של סיווג האובייקטים. אם לגלאי האובייקטים אין סיווג מופעל, או שהאובייקט מסווג כלא ידוע, זה nil .

    מָהִיר

    // detectedObjects contains one item if multiple object detection wasn't enabled.
    for obj in detectedObjects {
      let bounds = obj.frame
      let id = obj.trackingID
    
      // If classification was enabled:
      let category = obj.classificationCategory
      let confidence = obj.confidence
    }
    

    Objective-C

    // The list of detected objects contains one item if multiple
    // object detection wasn't enabled.
    for (FIRVisionObject *obj in objects) {
      CGRect bounds = obj.frame;
      if (obj.trackingID) {
        NSInteger id = obj.trackingID.integerValue;
      }
    
      // If classification was enabled:
      FIRVisionObjectCategory category = obj.classificationCategory;
      float confidence = obj.confidence.floatValue;
    }
    

שיפור השימושיות והביצועים

לחוויית המשתמש הטובה ביותר, פעל לפי ההנחיות הבאות באפליקציה שלך:

  • זיהוי אובייקט מוצלח תלוי במורכבות החזותית של האובייקט. אובייקטים עם מספר קטן של מאפיינים חזותיים עשויים להזדקק לתפוס חלק גדול יותר מהתמונה כדי להיות מזוהה. עליך לספק למשתמשים הנחיות לגבי לכידת קלט שעובדת היטב עם סוג האובייקטים שאתה רוצה לזהות.
  • בעת שימוש בסיווג, אם ברצונך לזהות אובייקטים שאינם נכנסים בצורה נקייה לקטגוריות הנתמכות, יישם טיפול מיוחד עבור אובייקטים לא ידועים.

כמו כן, בדוק את [ML Kit Material Design showcase app][showcase-link]{: .external } ואת אוסף התכונות של Material Design Patterns for Machine Learning .

בעת שימוש במצב סטרימינג באפליקציה בזמן אמת, עקוב אחר ההנחיות הבאות כדי להשיג את קצבי המסגרות הטובים ביותר:

  • אל תשתמש בזיהוי אובייקטים מרובים במצב סטרימינג, מכיוון שרוב המכשירים לא יוכלו לייצר קצבי פריימים נאותים.

  • השבת את הסיווג אם אינך זקוק לו.

  • מצערת קוראת לגלאי. אם מסגרת וידאו חדשה הופכת לזמינה בזמן שהגלאי פועל, שחרר את המסגרת.
  • אם אתה משתמש בפלט של הגלאי כדי לשכב גרפיקה על תמונת הקלט, תחילה קבל את התוצאה מ-ML Kit, ולאחר מכן עבד את התמונה ואת שכבת העל בצעד אחד. על ידי כך, אתה מעבד למשטח התצוגה רק פעם אחת עבור כל מסגרת קלט. ראה את המחלקות previewOverlayView ו- FIRDetectionOverlayView באפליקציה לדוגמה של הראווה לדוגמא.