Objekte mit ML Kit unter iOS erkennen und verfolgen

Mit ML Kit können Sie Objekte über Videoframes hinweg erkennen und verfolgen.

Wenn Sie ML Kit-Bilder übergeben, gibt ML Kit für jedes Bild eine Liste bis zu fünf erkannte Objekte und ihre Position im Bild. Bei der Erkennung von Objekten in Videostreams hat jedes Objekt eine ID, mit der Sie das Objekt in Bildern verfolgen können. Optional können Sie auch das grobe Objekt aktivieren. -Klassifizierung, bei der Objekte mit allgemeinen Kategoriebeschreibungen gekennzeichnet werden.

Hinweis

  1. Wenn Sie Ihrer App noch nicht Firebase hinzugefügt haben, folgen Sie der im Startleitfaden.
  2. Fügen Sie die ML Kit-Bibliotheken in Ihre Podfile ein:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie unbedingt Ihren Xcode mithilfe der .xcworkspace zu erstellen.
  3. Importieren Sie Firebase in Ihre App:

    Swift

    import Firebase

    Objective-C

    @import Firebase;

1. Objektdetektor konfigurieren

Um mit der Erkennung und dem Tracking von Objekten zu beginnen, erstellen Sie zunächst eine Instanz von VisionObjectDetector: Sie können optional die gewünschten Detektoreinstellungen angeben von der Standardeinstellung ändern.

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

    Einstellungen für Objektdetektoren
    Erkennungsmodus .stream (Standard) | .singleImage

    Im Stream-Modus (Standardeinstellung) läuft die Objekterkennung mit sehr niedrigen Latenz, kann jedoch zu unvollständigen Ergebnissen (z. B. nicht spezifizierte Begrenzungsrahmen oder Kategorie) auf die ersten Aufrufe von Detektor an. Im Streammodus weist der Detektor IDs zu Objekten, mit denen Sie Objekte über Frames hinweg verfolgen können. Verwenden Sie diesen Modus, wenn Sie Objekte verfolgen möchten oder wenn die Latenz niedrig ist ist wichtig, etwa bei der Verarbeitung von Videostreams in .

    Im Einzelbildmodus wartet die Objekterkennung, bis eine erkannte Begrenzungsrahmen des Objekts und (wenn Sie die Klassifizierung aktiviert haben) die Kategorie verfügbar sind, bevor ein Ergebnis zurückgegeben wird. Infolgedessen ist potenziell höher. In einem Einzelbild werden keine Tracking-IDs zugewiesen. Verwenden Sie diesen Modus, wenn nicht kritisch ist und Sie sich nicht mit unvollständigen Ergebnisse.

    Mehrere Objekte erkennen und verfolgen false (Standard) | true

    Erkennung und Verfolgung von bis zu fünf Objekten oder nur den auffälliges Objekt (Standardeinstellung).

    Objekte klassifizieren false (Standard) | true

    Gibt an, ob erkannte Objekte in groben Kategorien klassifiziert werden sollen. Wenn diese Option aktiviert ist, klassifiziert die Objekterkennung Objekte in der folgenden Kategorien: Modeartikel, Lebensmittel, Haushaltswaren, Orte, Pflanzen und unbekannte Gebiete.

    Die Objekterkennungs- und Objekterkennungs-API ist für diese beiden Hauptzwecke optimiert. Cases:

    • Live-Erkennung und Verfolgung des auffälligsten Objekts in der Kamera Sucher
    • Erkennung mehrerer Objekte in einem statischen Bild

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

    Swift

    // 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. Rufen Sie eine Instanz von FirebaseVisionObjectDetector ab:

    Swift

    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. Objektdetektor ausführen

Gehen Sie für jedes Bild oder jeden Frame des Videos folgendermaßen vor, um Objekte zu erkennen und zu verfolgen: Wenn Sie den Streammodus aktiviert haben, müssen Sie VisionImage-Objekte erstellen aus CMSampleBufferRef.

  1. Erstellen Sie ein VisionImage-Objekt mithilfe von UIImage oder einem CMSampleBufferRef

    So verwendest du UIImage:

    1. Drehen Sie das Bild gegebenenfalls so, dass es imageOrientation Property ist .up.
    2. Erstellen Sie ein VisionImage-Objekt mithilfe der korrekt gedrehten UIImage. Geben Sie keine Rotationsmetadaten an. Dies ist die Standardeinstellung. Wert .topLeft muss verwendet werden.

      Swift

      let image = VisionImage(image: uiImage)

      Objective-C

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

    So verwendest du CMSampleBufferRef:

    1. Erstellen Sie ein VisionImageMetadata-Objekt, das die Ausrichtung der Bilddaten im CMSampleBufferRef-Zwischenspeicher.

      So ermitteln Sie die Bildausrichtung:

      Swift

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

      Erstellen Sie dann das Metadatenobjekt:

      Swift

      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. Erstellen Sie ein VisionImage-Objekt mithilfe der CMSampleBufferRef-Objekt und die Rotationsmetadaten:

      Swift

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

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. Übergib VisionImage an einen der Bildverarbeitungsprogramme des Objektdetektors . Sie können entweder die asynchrone process(image:)-Methode oder die synchrone Methode results().

    So erkennen Sie Objekte asynchron:

    Swift

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

    So erkennen Sie Objekte synchron:

    Swift

    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. Wenn der Aufruf an den Bildprozessor erfolgreich ist, wird entweder eine Liste mit VisionObjects an den Abschluss-Handler oder gibt die Liste zurück, je nachdem, unabhängig davon, ob Sie die asynchrone oder die synchrone Methode aufgerufen haben.

    Jedes VisionObject enthält die folgenden Attribute:

    frame Ein CGRect, der die Position des Objekts im Bild.
    trackingID Eine Ganzzahl, die das Objekt in Bildern identifiziert. Null in Einzel im Bildmodus.
    classificationCategory Die grobe Kategorie des Objekts. Wenn die Objekterkennung Klassifizierung aktiviert haben, ist dies immer .unknown.
    confidence Der Konfidenzwert der Objektklassifizierung. Wenn die Klassifizierung für den Objekt-Detektor nicht aktiviert ist oder das Objekt als unbekannt klassifiziert wird, ist das nil.

    Swift

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

Nutzerfreundlichkeit und Leistung verbessern

Beachten Sie für eine optimale Nutzererfahrung in Ihrer App die folgenden Richtlinien:

  • Die erfolgreiche Objekterkennung hängt von der visuellen Komplexität des Objekts ab. Objekte mit wenigen visuellen Features möglicherweise einen größeren Teil des das zu erkennende Bild ist. Sie sollten Nutzenden dabei helfen, die sich gut für die Art von Objekten eignet, die Sie erkennen möchten.
  • Wenn Sie bei der Klassifizierung Objekte erkennen möchten, die nicht fallen in die unterstützten Kategorien einzuordnen, spezielle Behandlungen für unbekannte Objekte.

Sehen Sie sich auch die [ML Kit Material Design Showcase-App][showcase-link]{: .external } und die Material Design Sammlung Muster für Funktionen, die auf maschinellem Lernen basieren

Wenn Sie den Streamingmodus in einer Echtzeitanwendung verwenden, beachten Sie die folgenden Richtlinien, um die beste Framerate zu erzielen:

  • Verwenden Sie im Streamingmodus nicht die Mehrfachobjekterkennung, da die meisten Geräte dies angemessene Framerates zu erzielen.

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

  • Drosselung von Aufrufen an den Detektor. Wenn ein neuer Videoframe wenn der Detektor ausgeführt wird, lassen Sie den Frame weg.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken Eingabebild, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie das Bild in einem Schritt übereinanderlegen. Dadurch rendern Sie auf der Anzeigeoberfläche für jeden Eingabe-Frame nur einmal. Weitere Informationen finden Sie unter previewOverlayView. und FIRDetectionOverlayView in der Showcase-Beispiel-App als Beispiel.