Barcodes mit ML Kit für iOS scannen

Sie können mit ML Kit Barcodes erkennen und decodieren.

Ausprobieren

  • Probieren Sie die Beispiel-App aus, um ein Beispiel für die Verwendung dieser API zu sehen.

Hinweis

  1. Nehmen Sie die folgenden ML Kit-Pods in Ihre Podfile-Datei auf:
    pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
    
  2. Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie Ihr Xcode-Projekt mit der zugehörigen .xcworkspace. ML Kit wird in Xcode ab Version 12.4 unterstützt.

Richtlinien für Eingabebilder

  • Damit ML Kit Barcodes genau lesen kann, müssen Eingabebilder Barcodes enthalten, die durch genügend Pixeldaten dargestellt werden.

    Die spezifischen Pixeldatenanforderungen hängen sowohl vom Barcodetyp als auch von der darin codierten Datenmenge ab, da viele Barcodes eine Nutzlast mit variabler Größe unterstützen. Im Allgemeinen sollte die kleinste sinnvolle Einheit des Barcodes mindestens 2 Pixel breit und bei zweidimensionalen Codes 2 Pixel hoch sein.

    EAN-13-Barcodes bestehen beispielsweise aus Balken und Leerzeichen, die 1, 2, 3 oder 4 Einheiten breit sind. Ein EAN-13-Barcodebild hat daher idealerweise Balken und Leerzeichen, die mindestens 2, 4, 6 und 8 Pixel breit sind. Da ein EAN-13-Barcode insgesamt 95 Einheiten breit ist, sollte der Barcode mindestens 190 Pixel breit sein.

    Kompaktere Formate wie PDF417 benötigen größere Pixelabmessungen, damit ML Kit sie zuverlässig lesen kann. Ein PDF417-Code kann beispielsweise bis zu 34 „Wörter“ mit einer Breite von 17 Einheiten in einer einzelnen Zeile enthalten, die im Idealfall mindestens 1.156 Pixel breit sind.

  • Ein schlechter Bildfokus kann die Scangenauigkeit beeinträchtigen. Wenn deine App keine akzeptablen Ergebnisse erzielt, bitte den Nutzer, das Bild noch einmal aufzunehmen.

  • Für typische Anwendungen wird empfohlen, Bilder mit höherer Auflösung wie 1280 × 720 oder 1920 × 1080 bereitzustellen, damit Barcodes auch aus größerer Entfernung von der Kamera gescannt werden können.

    In Anwendungen, bei denen die Latenz jedoch von entscheidender Bedeutung ist, können Sie die Leistung verbessern, indem Sie Bilder mit einer niedrigeren Auflösung aufnehmen, bei denen der Barcode aber den Großteil des Eingabebilds ausmachen muss. Weitere Informationen finden Sie unter Tipps zur Verbesserung der Echtzeitleistung.

1. Barcode-Scanner konfigurieren

Wenn Sie wissen, welche Barcodeformate Sie lesen möchten, können Sie die Geschwindigkeit des Barcodescanners verbessern, indem Sie ihn so konfigurieren, dass er nur diese Formate scannt.

Wenn Sie beispielsweise nur Aztec-Code und QR-Codes scannen möchten, erstellen Sie ein BarcodeScannerOptions-Objekt wie im folgenden Beispiel:

Swift

let format = .all
let barcodeOptions = BarcodeScannerOptions(formats: format)
  

Die folgenden Formate werden unterstützt:

  • code128
  • code39
  • code93
  • codaBar
  • dataMatrix
  • EAN13
  • EAN8
  • Logo: ITF
  • qrCode
  • UPCA
  • UPCE
  • PDF417
  • Aztec

Objective-C

MLKBarcodeScannerOptions *options =
  [[MLKBarcodeScannerOptions alloc]
   initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];

Die folgenden Formate werden unterstützt:

  • Code-128 (MLKBarcodeFormatCode128)
  • Code-39 (MLKBarcodeFormatCode39)
  • Code-93 (MLKBarcodeFormatCode93)
  • Codabar (MLKBarcodeFormatCodaBar)
  • Datenmatrix (MLKBarcodeFormatDataMatrix)
  • EAN-13-Nummer (MLKBarcodeFormatEAN13)
  • EAN-8 (MLKBarcodeFormatEAN8)
  • ITF (MLKBarcodeFormatITF)
  • QR-Code (MLKBarcodeFormatQRCode)
  • UPC-A (MLKBarcodeFormatUPCA)
  • UPC-E (MLKBarcodeFormatUPCE)
  • PDF-417 (MLKBarcodeFormatPDF417)
  • Aztec-Code (MLKBarcodeFormatAztec)

2. Eingabebild vorbereiten

Um Barcodes in einem Bild zu scannen, übergeben Sie das Bild als UIImage oder CMSampleBufferRef an die Methode process() oder results(in:) des BarcodeScanner:

Erstellen Sie mit UIImage oder CMSampleBuffer ein VisionImage-Objekt.

Wenn Sie ein UIImage verwenden, gehen Sie so vor:

  • Erstellen Sie mit UIImage ein VisionImage-Objekt. Achten Sie darauf, den richtigen .orientation anzugeben.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Wenn Sie ein CMSampleBuffer verwenden, gehen Sie so vor:

  • Gibt die Ausrichtung der Bilddaten an, die in CMSampleBuffer enthalten sind.

    So rufen Sie die Bildausrichtung ab:

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Erstelle ein VisionImage-Objekt mit dem Objekt CMSampleBuffer und der Ausrichtung:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Instanz von BarcodeScanner abrufen

Rufen Sie eine Instanz von BarcodeScanner ab:

Swift

let barcodeScanner = BarcodeScanner.barcodeScanner()
// Or, to change the default settings:
// let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)

Objective-C

MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner];
// Or, to change the default settings:
// MLKBarcodeScanner *barcodeScanner =
//     [MLKBarcodeScanner barcodeScannerWithOptions:options];

4. Bild verarbeiten

Übergeben Sie das Bild dann an die Methode process():

Swift

barcodeScanner.process(visionImage) { features, error in
  guard error == nil, let features = features, !features.isEmpty else {
    // Error handling
    return
  }
  // Recognized barcodes
}

Objective-C

[barcodeScanner processImage:image
                  completion:^(NSArray<MLKBarcode *> *_Nullable barcodes,
                               NSError *_Nullable error) {
  if (error != nil) {
    // Error handling
    return;
  }
  if (barcodes.count > 0) {
    // Recognized barcodes
  }
}];

5. Informationen aus Barcodes abrufen

Wenn der Barcode-Scan erfolgreich ist, gibt der Scanner ein Array von Barcode-Objekten zurück. Jedes Barcode-Objekt stellt einen Barcode dar, der im Bild erkannt wurde. Für jeden Barcode können Sie seine Begrenzungskoordinaten im Eingabebild sowie die vom Barcode codierten Rohdaten abrufen. Wenn der Barcode-Scanner die Art der vom Barcode codierten Daten ermitteln konnte, können Sie außerdem ein Objekt abrufen, das geparste Daten enthält.

Beispiel:

Swift

for barcode in barcodes {
  let corners = barcode.cornerPoints

  let displayValue = barcode.displayValue
  let rawValue = barcode.rawValue

  let valueType = barcode.valueType
  switch valueType {
  case .wiFi:
    let ssid = barcode.wifi?.ssid
    let password = barcode.wifi?.password
    let encryptionType = barcode.wifi?.type
  case .URL:
    let title = barcode.url!.title
    let url = barcode.url!.url
  default:
    // See API reference for all supported value types
  }
}

Objective-C

for (MLKBarcode *barcode in barcodes) {
   NSArray *corners = barcode.cornerPoints;

   NSString *displayValue = barcode.displayValue;
   NSString *rawValue = barcode.rawValue;

   MLKBarcodeValueType valueType = barcode.valueType;
   switch (valueType) {
     case MLKBarcodeValueTypeWiFi:
       ssid = barcode.wifi.ssid;
       password = barcode.wifi.password;
       encryptionType = barcode.wifi.type;
       break;
     case MLKBarcodeValueTypeURL:
       url = barcode.URL.url;
       title = barcode.URL.title;
       break;
     // ...
     default:
       break;
   }
 }

Tipps zur Verbesserung der Echtzeitleistung

Wenn Sie Barcodes in einer Echtzeitanwendung scannen möchten, beachten Sie die folgenden Richtlinien, um die besten Framerates zu erzielen:

  • Erfassen Sie Eingaben nicht mit der nativen Auflösung der Kamera. Auf einigen Geräten werden Eingaben in nativer Auflösung erfasst und extrem große Bilder (mehr als 10 Megapixel) erzeugt. Dies führt zu einer sehr schlechten Latenz, ohne dass die Genauigkeit verbessert wird. Fordern Sie stattdessen nur die Größe von der Kamera an, die zum Scannen des Barcodes erforderlich ist (normalerweise nicht mehr als 2 Megapixel).

    Die benannten Voreinstellungen für Aufnahmesitzungen (AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium usw.) werden jedoch nicht empfohlen, da sie auf einigen Geräten ungeeigneten Auflösungen zugeordnet werden können. Verwenden Sie stattdessen die spezifischen Voreinstellungen wie AVCaptureSessionPreset1280x720.

    Wenn die Scangeschwindigkeit wichtig ist, können Sie die Auflösung der Bilderfassung weiter senken. Beachten Sie jedoch die oben genannten Mindestanforderungen an die Barcodegröße.

    Wenn Sie versuchen, Barcodes aus einer Abfolge von gestreamten Videoframes zu erkennen, kann die Erkennung von Frame zu Frame unterschiedliche Ergebnisse liefern. Sie sollten warten, bis Sie eine aufeinanderfolgende Reihe mit demselben Wert erhalten, um sicher zu sein, dass Sie ein gutes Ergebnis liefern.

    Die Prüfsummenziffer wird für ITF und CODE-39 nicht unterstützt.

  • Verwenden Sie zum Verarbeiten von Videobildern die synchrone results(in:)-API des Detektors. Rufen Sie diese Methode über die captureOutput(_, didOutput:from:)-Funktion von AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe zu erhalten. Behalten Sie die alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput als true bei, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er gelöscht.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken über das Eingabebild einzublenden, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie dann das Bild und Overlay in einem einzigen Schritt. Dadurch wird für jeden verarbeiteten Eingabeframe nur einmal ein Rendering auf der Anzeigeoberfläche ausgeführt. Ein Beispiel finden Sie unter updatePreviewOverlayViewWithLastFrame im ML Kit-Schnellstartbeispiel.