Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Rileva e traccia oggetti con ML Kit su iOS

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Puoi utilizzare ML Kit per rilevare e tenere traccia di oggetti attraverso i fotogrammi del video.

Quando si passano le immagini di ML Kit, ML Kit restituisce, per ogni immagine, un elenco di un massimo di cinque oggetti rilevati e la loro posizione nell'immagine. Quando si rilevano oggetti nei flussi video, ogni oggetto ha un ID che è possibile utilizzare per tracciare l'oggetto attraverso le immagini. Puoi anche abilitare facoltativamente la classificazione degli oggetti grossolana, che etichetta gli oggetti con descrizioni di categorie ampie.

Prima di iniziare

  1. Se non hai già aggiunto Firebase alla tua app, fallo seguendo i passaggi nella Guida introduttiva .
  2. Includi le librerie ML Kit nel tuo Podfile:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    Dopo aver installato o aggiornato i Pod del tuo progetto, assicurati di aprire il tuo progetto Xcode usando il suo .xcworkspace .
  3. Nella tua app, importa Firebase:

    Veloce

    import Firebase

    Obiettivo-C

    @import Firebase;

1. Configurare il rilevatore di oggetti

Per iniziare a rilevare e tracciare oggetti, creare prima un'istanza di VisionObjectDetector , specificando facoltativamente le impostazioni del rilevatore che si desidera modificare rispetto a quelle predefinite.

  1. Configura il rilevatore di oggetti per il tuo caso d'uso con un oggetto VisionObjectDetectorOptions . È possibile modificare le seguenti impostazioni:

    Impostazioni del rilevatore di oggetti
    Modalità di rilevamento .stream (predefinito) | .singleImage

    In modalità flusso (impostazione predefinita), il rilevatore di oggetti viene eseguito con una latenza molto bassa, ma potrebbe produrre risultati incompleti (come riquadri o categorie di delimitazione non specificati) alle prime chiamate del rilevatore. Inoltre, in modalità flusso, il rilevatore assegna ID di tracciamento agli oggetti, che è possibile utilizzare per tracciare gli oggetti attraverso i frame. Utilizzare questa modalità quando si desidera tenere traccia di oggetti o quando è importante una bassa latenza, ad esempio durante l'elaborazione di flussi video in tempo reale.

    In modalità immagine singola, il rilevatore di oggetti attende che il riquadro di delimitazione di un oggetto rilevato e la categoria (se è stata abilitata la classificazione) sono disponibili prima di restituire un risultato. Di conseguenza, la latenza di rilevamento è potenzialmente maggiore. Inoltre, nella modalità immagine singola, gli ID di tracciamento non vengono assegnati. Usa questa modalità se la latenza non è critica e non vuoi gestire risultati parziali.

    Rileva e traccia più oggetti false (predefinito) | true

    Se rilevare e tracciare fino a cinque oggetti o solo l'oggetto più prominente (impostazione predefinita).

    Classifica gli oggetti false (predefinito) | true

    Se classificare o meno gli oggetti rilevati in categorie grossolane. Quando abilitato, il rilevatore di oggetti classifica gli oggetti nelle seguenti categorie: articoli di moda, cibo, articoli per la casa, luoghi, piante e sconosciuti.

    L'API di rilevamento e tracciamento degli oggetti è ottimizzata per questi due casi d'uso principali:

    • Rilevamento e tracciamento in tempo reale dell'oggetto più importante nel mirino della fotocamera
    • Rilevamento di più oggetti in un'immagine statica

    Per configurare l'API per questi casi d'uso:

    Veloce

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

    Obiettivo-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. Ottieni un'istanza di FirebaseVisionObjectDetector :

    Veloce

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

    Obiettivo-C

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

2. Avviare il rilevatore di oggetti

Per rilevare e tenere traccia degli oggetti, procedi come segue per ogni immagine o fotogramma del video. Se hai abilitato la modalità flusso, devi creare oggetti VisionImage da CMSampleBufferRef s.

  1. Crea un oggetto VisionImage usando un UIImage o un CMSampleBufferRef .

    Per utilizzare UIImage :

    1. Se necessario, ruota l'immagine in modo che la sua proprietà imageOrientation sia .up .
    2. Crea un oggetto VisionImage utilizzando l' UIImage ruotato correttamente. Non specificare metadati di rotazione: è necessario utilizzare il valore predefinito, .topLeft .

      Veloce

      let image = VisionImage(image: uiImage)

      Obiettivo-C

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

    Per utilizzare un CMSampleBufferRef :

    1. Creare un oggetto VisionImageMetadata che specifichi l'orientamento dei dati dell'immagine contenuti nel buffer CMSampleBufferRef .

      Per ottenere l'orientamento dell'immagine:

      Veloce

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

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

      Quindi, crea l'oggetto metadati:

      Veloce

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

      Obiettivo-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. Crea un oggetto VisionImage utilizzando l'oggetto CMSampleBufferRef e i metadati di rotazione:

      Veloce

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

      Obiettivo-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. Passare VisionImage a uno dei metodi di elaborazione delle immagini del rilevatore di oggetti. È possibile utilizzare il metodo asincrono process(image:) o il metodo sincrono results() .

    Per rilevare gli oggetti in modo asincrono:

    Veloce

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

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

    Per rilevare gli oggetti in modo sincrono:

    Veloce

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

    Obiettivo-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. Se la chiamata al processore di immagini riesce, passa un elenco di VisionObject al gestore di completamento o restituisce l'elenco, a seconda che sia stato chiamato il metodo asincrono o sincrono.

    Ogni VisionObject contiene le seguenti proprietà:

    frame Un CGRect che indica la posizione dell'oggetto nell'immagine.
    trackingID Un numero intero che identifica l'oggetto attraverso le immagini. Zero in modalità immagine singola.
    classificationCategory La categoria grossolana dell'oggetto. Se il rilevatore di oggetti non ha la classificazione abilitata, questo è sempre .unknown .
    confidence Il valore di confidenza dell'oggetto classificaton. Se il rilevatore di oggetti non ha la classificazione abilitata, o l'oggetto è classificato come sconosciuto, questo è nil .

    Veloce

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

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

Miglioramento dell'usabilità e delle prestazioni

Per la migliore esperienza utente, segui queste linee guida nella tua app:

  • Il successo del rilevamento degli oggetti dipende dalla complessità visiva dell'oggetto. Gli oggetti con un numero ridotto di caratteristiche visive potrebbero dover occupare una parte più ampia dell'immagine per essere rilevati. Dovresti fornire agli utenti una guida sull'acquisizione di input che funzioni bene con il tipo di oggetti che desideri rilevare.
  • Quando si utilizza la classificazione, se si desidera rilevare oggetti che non rientrano chiaramente nelle categorie supportate, implementare una gestione speciale per gli oggetti sconosciuti.

Inoltre, dai un'occhiata all'[app vetrina ML Kit Material Design][showcase-link]{: .external } e alla raccolta di funzionalità basate sull'apprendimento automatico dei modelli di progettazione dei materiali.

Quando utilizzi la modalità streaming in un'applicazione in tempo reale, segui queste linee guida per ottenere i framerate migliori:

  • Non utilizzare il rilevamento di più oggetti in modalità streaming, poiché la maggior parte dei dispositivi non sarà in grado di produrre framerate adeguati.

  • Disabilita la classificazione se non ne hai bisogno.

  • Accelera le chiamate al rilevatore. Se un nuovo fotogramma video diventa disponibile mentre il rilevatore è in funzione, rilasciare il fotogramma.
  • Se si utilizza l'output del rilevatore per sovrapporre la grafica all'immagine di input, ottenere prima il risultato da ML Kit, quindi eseguire il rendering dell'immagine e sovrapporre in un unico passaggio. In questo modo, si esegue il rendering sulla superficie di visualizzazione solo una volta per ciascun frame di input. Per un esempio, vedere le classi previewOverlayView e FIRDetectionOverlayView nell'app di esempio della vetrina.