Sie können ML Kit verwenden, um Barcodes zu erkennen und zu decodieren.
Bevor Sie beginnen
- Wenn Sie Ihrer App Firebase noch nicht hinzugefügt haben, befolgen Sie dazu die Schritte im Leitfaden „Erste Schritte“ .
- Schließen Sie die ML Kit-Bibliotheken in Ihre Poddatei ein:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, müssen Sie Ihr Xcode-Projekt mit seiner.xcworkspace
. - Importieren Sie in Ihrer App Firebase:
Schnell
import Firebase
Ziel c
@import Firebase;
Bildrichtlinien eingeben
Damit ML Kit Strichcodes genau lesen kann, müssen Eingabebilder Strichcodes enthalten, die durch ausreichend Pixeldaten dargestellt werden.
Die spezifischen Pixeldatenanforderungen hängen sowohl vom Strichcodetyp als auch von der darin codierten Datenmenge ab (da die meisten Strichcodes eine Nutzlast mit variabler Länge unterstützen). Im Allgemeinen sollte die kleinste sinnvolle Einheit des Barcodes mindestens 2 Pixel breit sein (und bei 2-dimensionalen Codes 2 Pixel hoch).
Beispielsweise bestehen EAN-13-Barcodes aus Strichen und Zwischenräumen mit einer Breite von 1, 2, 3 oder 4 Einheiten, sodass ein EAN-13-Barcodebild idealerweise Striche und Zwischenräume mit einer Breite von mindestens 2, 4, 6 und hat 8 Pixel breit. Da ein EAN-13-Barcode insgesamt 95 Einheiten breit ist, sollte der Barcode mindestens 190 Pixel breit sein.
Dichtere Formate wie PDF417 benötigen größere Pixelabmessungen, damit ML Kit sie zuverlässig lesen kann. Beispielsweise kann ein PDF417-Code bis zu 34 17-Einheiten breite "Wörter" in einer einzelnen Zeile haben, die idealerweise mindestens 1156 Pixel breit wäre.
Ein schlechter Bildfokus kann die Scangenauigkeit beeinträchtigen. Wenn Sie keine akzeptablen Ergebnisse erzielen, bitten Sie den Benutzer, das Bild erneut aufzunehmen.
Für typische Anwendungen wird empfohlen, ein Bild mit höherer Auflösung (z. B. 1280 x 720 oder 1920 x 1080) bereitzustellen, wodurch Barcodes aus größerer Entfernung von der Kamera erkennbar sind.
Bei Anwendungen, bei denen die Latenzzeit kritisch ist, können Sie die Leistung jedoch verbessern, indem Sie Bilder mit einer niedrigeren Auflösung erfassen, aber erfordern, dass der Barcode den Großteil des Eingabebildes ausmacht. Siehe auch Tipps zur Verbesserung der Echtzeitleistung .
1. Konfigurieren Sie den Barcode-Detektor
Wenn Sie wissen, welche Barcode-Formate Sie lesen möchten, können Sie die Geschwindigkeit des Barcode-Detektors verbessern, indem Sie ihn so konfigurieren, dass er nur diese Formate erkennt. Um beispielsweise nur Aztec-Code und QR-Codes zu erkennen, erstellen Sie ein VisionBarcodeDetectorOptions
-Objekt wie im folgenden Beispiel:
Schnell
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
Folgende Formate werden unterstützt:
- Code128
- Code39
- Code93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- QR-Code
- PDF417
- aztekisch
- Datenmatrix
Ziel c
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
Folgende Formate werden unterstützt:
- Code 128 (
FIRVisionBarcodeFormatCode128
) - Code 39 (
FIRVisionBarcodeFormatCode39
) - Code 93 (
FIRVisionBarcodeFormatCode93
) - Codabar (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ITF (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - QR-Code (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - Aztec (
FIRVisionBarcodeFormatAztec
) - Datenmatrix (
FIRVisionBarcodeFormatDataMatrix
)
2. Führen Sie den Barcode-Detektor aus
Um Barcodes in einem Bild zu scannen, übergeben Sie das Bild alsUIImage
oder CMSampleBufferRef
an die Methode detect(in:)
von VisionBarcodeDetector
:- Holen Sie sich eine Instanz von
VisionBarcodeDetector
:Schnell
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
Ziel c
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
Erstellen Sie ein
VisionImage
Objekt mit einemUIImage
oder einemCMSampleBufferRef
.So verwenden Sie ein
UIImage
:- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
imageOrientation
.up
. - Erstellen Sie ein
VisionImage
-Objekt mit dem korrekt gedrehtenUIImage
. Geben Sie keine Rotationsmetadaten an – der Standardwert.topLeft
muss verwendet werden.Schnell
let image = VisionImage(image: uiImage)
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
So verwenden Sie eine
CMSampleBufferRef
:Erstellen Sie ein
VisionImageMetadata
Objekt, das die Ausrichtung der imCMSampleBufferRef
Puffer enthaltenen Bilddaten angibt.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];
- Erstellen Sie ein
VisionImage
Objekt mit demCMSampleBufferRef
Objekt und den Rotationsmetadaten:Schnell
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
- Übergeben Sie das Bild dann an die Methode
detect(in:)
:Schnell
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
Ziel c
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. Erhalten Sie Informationen von Barcodes
Wenn die Barcode-Erkennungsoperation erfolgreich ist, gibt der Detektor ein Array vonVisionBarcode
-Objekten zurück. Jedes VisionBarcode
-Objekt stellt einen Barcode dar, der im Bild erkannt wurde. Für jeden Barcode können Sie seine Begrenzungskoordinaten im Eingabebild sowie die durch den Barcode codierten Rohdaten abrufen. Wenn der Strichcode-Detektor den Typ der durch den Strichcode codierten Daten bestimmen konnte, können Sie auch ein Objekt erhalten, das geparste Daten enthält.Zum Beispiel:
Schnell
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 } }
Ziel c
for (FIRVisionBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; FIRVisionBarcodeValueType valueType = barcode.valueType; switch (valueType) { case FIRVisionBarcodeValueTypeWiFi: // ssid = barcode.wifi.ssid; // password = barcode.wifi.password; // encryptionType = barcode.wifi.type; break; case FIRVisionBarcodeValueTypeURL: // 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, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:
Nehmen Sie Eingaben nicht mit der nativen Auflösung der Kamera auf. Bei einigen Geräten erzeugt die Erfassung von Eingaben mit der nativen Auflösung extrem große Bilder (10+ Megapixel), was zu einer sehr geringen Latenz führt, ohne dass die Genauigkeit verbessert wird. Fordern Sie stattdessen nur die Größe von der Kamera an, die für die Barcode-Erkennung benötigt wird: in der Regel nicht mehr als 2 Megapixel.
Die genannten 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 wieAVCaptureSessionPreset1280x720
.Wenn die Scangeschwindigkeit wichtig ist, können Sie die Bilderfassungsauflösung weiter verringern. Beachten Sie jedoch die oben beschriebenen Anforderungen an die Mindestgröße von Barcodes.
- Drosselrufe an den Detektor. Wenn ein neuer Videoframe verfügbar wird, während der Detektor läuft, löschen Sie den Frame.
- Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf das Eingabebild zu legen, rufen Sie zuerst das Ergebnis von ML Kit ab, rendern Sie dann das Bild und überlagern Sie es in einem einzigen Schritt. Dadurch rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche. Ein Beispiel finden Sie in den Klassen previewOverlayView und FIRDetectionOverlayView in der Showcase-Beispiel-App.