Catch up on everthing we announced at this year's Firebase Summit. Learn more

Erkennen und Verfolgen von Objekten mit ML Kit auf iOS

Sie können ML Kit verwenden, um Objekte über Videoframes hinweg zu erkennen und zu verfolgen.

Wenn Sie ML Kit-Bilder übergeben, gibt ML Kit für jedes Bild eine Liste von bis zu fünf erkannten Objekten und deren Position im Bild zurück. Beim Erkennen von Objekten in Videostreams hat jedes Objekt eine ID, mit der Sie das Objekt über Bilder hinweg verfolgen können. Optional können Sie auch eine grobe Objektklassifizierung aktivieren, die Objekte mit umfassenden Kategoriebeschreibungen beschriftet.

Bevor Sie beginnen

  1. Wenn Sie nicht bereits Firebase zu Ihrer App, tun Sie dies , indem Sie die Schritte im Leitfaden zur Inbetriebnahme .
  2. Fügen Sie die ML - Kit - Bibliotheken in Ihrem Podfile:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    Nachdem Sie Ihr Projekt Pods installieren oder aktualisieren, sollten Sie Ihre Xcode - Projekt zu öffnen , seine Verwendung .xcworkspace .
  3. Importieren Sie Firebase in Ihre App:

    Schnell

    import Firebase

    Ziel c

    @import Firebase;

1. Konfigurieren Sie den Objektdetektor

So startet Erkennung von Objekten erfassen und zu verfolgen, erstellen Sie zuerst eine Instanz von VisionObjectDetector , optional alle Detektoreinstellungen Spezifizieren Sie Wechsel von dem Standard wollen.

  1. Konfigurieren Sie den Objektdetektor für Ihren Anwendungsfall mit einem VisionObjectDetectorOptions Objekt. Sie können die folgenden Einstellungen ändern:

    Objektdetektoreinstellungen
    Erkennungsmodus .stream (default) | .singleImage

    Im Stream-Modus (Standard) wird der Objektdetektor mit sehr geringer Latenz ausgeführt, kann jedoch bei den ersten Aufrufen des Detektors unvollständige Ergebnisse (z. B. nicht spezifizierte Begrenzungsrahmen oder Kategorie) liefern. Außerdem weist der Detektor im Stream-Modus Objekten Tracking-IDs zu, mit denen Sie Objekte über Frames hinweg verfolgen können. Verwenden Sie diesen Modus, wenn Sie Objekte verfolgen möchten oder wenn eine geringe Latenz wichtig ist, beispielsweise bei der Verarbeitung von Videostreams in Echtzeit.

    Im Einzelbildmodus wartet der Objektdetektor, bis der Begrenzungsrahmen eines erkannten Objekts und (wenn Sie die Klassifizierung aktiviert haben) die Kategorie verfügbar sind, bevor ein Ergebnis zurückgegeben wird. Infolgedessen ist die Erkennungslatenz möglicherweise höher. Außerdem werden im Einzelbildmodus keine Tracking-IDs zugewiesen. Verwenden Sie diesen Modus, wenn die Latenz nicht kritisch ist und Sie nicht mit Teilergebnissen umgehen möchten.

    Mehrere Objekte erkennen und verfolgen false (default) | true

    Ob bis zu fünf Objekte oder nur das prominenteste Objekt erkannt und verfolgt werden sollen (Standard).

    Objekte klassifizieren false (default) | true

    Ob erkannte Objekte in grobe Kategorien eingeteilt werden sollen oder nicht. Wenn aktiviert, klassifiziert der Objektdetektor Objekte in die folgenden Kategorien: Modeartikel, Lebensmittel, Haushaltswaren, Orte, Pflanzen und Unbekanntes.

    Die API zur Objekterkennung und -verfolgung ist für diese beiden Kernanwendungsfälle optimiert:

    • Live-Erkennung und Verfolgung des markantesten Objekts im Kamerasucher
    • Erkennung mehrerer Objekte in einem statischen Bild

    So konfigurieren Sie die API für diese Anwendungsfälle:

    Schnell

    // 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
    

    Ziel 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. Erhalten Sie eine Instanz von FirebaseVisionObjectDetector :

    Schnell

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

    Ziel c

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

2. Führen Sie den Objektdetektor aus

Um Objekte zu erkennen und zu verfolgen, gehen Sie für jedes Bild oder Videobild wie folgt vor. Wenn Sie Stream - Modus aktiviert ist , müssen Sie erstellen VisionImage Objekte aus CMSampleBufferRef s.

  1. Erstellen Sie ein VisionImage Objekt unter Verwendung eines UIImage oder eine CMSampleBufferRef .

    So verwenden Sie eine UIImage :

    1. Falls erforderlich, drehen Sie das Bild so , dass seine imageOrientation Eigenschaft ist .up .
    2. Erstellen Sie ein VisionImage Objekt die korrekt gedreht mit UIImage . Geben Sie nicht jede Drehung Metadaten den Standardwert, .topLeft , verwendet werden.

      Schnell

      let image = VisionImage(image: uiImage)

      Ziel c

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

    So verwenden Sie eine CMSampleBufferRef :

    1. Erstellen eines VisionImageMetadata Objekt , das angibt , ist die Orientierung der Bilddaten in der enthaltenen CMSampleBufferRef Puffer.

      So erhalten Sie die Bildausrichtung:

      Schnell

      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
          }
      }

      Ziel 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;
        }
      }

      Erstellen Sie dann das Metadatenobjekt:

      Schnell

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      Ziel 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. Erstellen Sie ein VisionImage Objekt mit dem CMSampleBufferRef Objekt und die Rotation von Metadaten:

      Schnell

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

      Ziel c

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. Übergeben der VisionImage zu einer der Bildverarbeitungsverfahren des Objektdetektor. Sie können entweder die asynchronen verwenden process(image:) - Methode oder die Synchron results() Methode.

    So erkennen Sie Objekte asynchron:

    Schnell

    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.
      // ...
    }
    

    Ziel 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.
                        // ...
                      }];
    

    Um Objekte synchron zu erkennen:

    Schnell

    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
    }
    
    // ...
    

    Ziel 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. Wenn der Anruf an den Bildprozessor erfolgreich ist , geht es entweder eine Liste von VisionObject s zum Abschluss Handler oder gibt die Liste, je nachdem , ob Sie die asynchrone oder synchrone Methode aufgerufen.

    Jede VisionObject enthält die folgenden Eigenschaften:

    frame A CGRect die Position des Objekts in dem Bild angibt.
    trackingID Eine ganze Zahl, die das Objekt bildübergreifend identifiziert. Null im Einzelbildmodus.
    classificationCategory Die grobe Kategorie des Objekts. Wenn der Objektdetektor ist nicht kennzeichnungs aktiviert ist , wird dies immer .unknown .
    confidence Der Konfidenzwert der Objektklassifizierung. Wenn der Objektdetektor nicht über Klassifizierung aktiviert ist , oder das Objekt als unbekannt eingestuft, dies ist nil .

    Schnell

    // 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
    }
    

    Ziel 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;
    }
    

Verbesserung der Benutzerfreundlichkeit und Leistung

Befolgen Sie für eine optimale Benutzererfahrung diese Richtlinien in Ihrer App:

  • Eine erfolgreiche Objekterkennung hängt von der visuellen Komplexität des Objekts ab. Objekte mit wenigen visuellen Merkmalen müssen möglicherweise einen größeren Teil des zu erkennenden Bildes einnehmen. Sie sollten den Benutzern Anleitungen zum Erfassen von Eingaben geben, die gut mit der Art von Objekten funktionieren, die Sie erkennen möchten.
  • Wenn Sie bei der Klassifizierung Objekte erkennen möchten, die nicht eindeutig in die unterstützten Kategorien fallen, implementieren Sie eine spezielle Behandlung für unbekannte Objekte.

Auch, ob die [ML Kit Material Design Vitrine app] [Vitrine-link] {: .Externes} und das Material Design Patterns für maschinelle Lernen betriebener Funktionen Sammlung.

Wenn Sie den Streaming-Modus in einer Echtzeitanwendung verwenden, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:

  • Verwenden Sie im Streaming-Modus keine Mehrfachobjekterkennung, da die meisten Geräte keine angemessenen Frameraten erzeugen können.

  • Deaktivieren Sie die Klassifizierung, wenn Sie sie nicht benötigen.

  • Throttle-Anrufe an den Detektor. Wenn ein neues Videobild verfügbar wird, während der Detektor läuft, lassen Sie das Bild fallen.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild zu überlagern, rufen Sie zuerst das Ergebnis von ML Kit ab und rendern Sie dann das Bild und die Überlagerung in einem einzigen Schritt. Auf diese Weise rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche. Siehe die previewOverlayView und FIRDetectionOverlayView Klassen in der Vitrine Beispielanwendung für ein Beispiel.