Puoi utilizzare ML Kit per riconoscere e decodificare i codici a barre.
Prova subito
- Prova l'app di esempio per vedere un esempio di utilizzo di questa API.
Prima di iniziare
- Includi i seguenti pod di ML Kit nel tuo podfile:
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando
.xcworkspace
. ML Kit è supportato in Xcode versione 12.4 o successiva.
Linee guida sull'immagine di input
-
Affinché ML Kit possa leggere con precisione i codici a barre, le immagini di input devono contenere codici a barre rappresentati da dati pixel sufficienti.
I requisiti specifici per i dati dei pixel dipendono sia dal tipo di codice a barre sia dalla quantità di dati codificati al suo interno, dato che molti codici a barre supportano un payload di dimensioni variabili. In generale, l'unità più piccola significativa del codice a barre deve essere larga almeno 2 pixel, mentre per i codici bidimensionali è alta 2 pixel.
Ad esempio, i codici a barre EAN-13 sono composti da barre e spazi larghi 1, 2, 3 o 4 unità, quindi un'immagine codice a barre EAN-13 ha idealmente barre e spazi con una larghezza di almeno 2, 4, 6 e 8 pixel. Poiché un codice a barre EAN-13 ha una larghezza totale di 95 unità, il codice a barre deve avere una larghezza di almeno 190 pixel.
I formati più densi, come PDF417, richiedono dimensioni maggiori in pixel affinché ML Kit possa leggerli in modo affidabile. Ad esempio, un codice PDF417 può avere fino a 34 "parole" larghe 17 unità in una singola riga, che sarebbe idealmente larga almeno 1156 pixel.
-
Una messa a fuoco dell'immagine scadente può influire sulla precisione della scansione. Se la tua app non ottiene risultati accettabili, chiedi all'utente di riprendere l'immagine.
-
Per le applicazioni tipiche, consigliamo di fornire un'immagine con risoluzione più elevata, ad esempio 1280 x 720 o 1920 x 1080, in modo da poter scansionare i codici a barre da una distanza maggiore dalla fotocamera.
Tuttavia, nelle applicazioni in cui la latenza è fondamentale, puoi migliorare le prestazioni acquisendo immagini a una risoluzione inferiore, ma richiedendo che il codice a barre rappresenti la maggior parte dell'immagine di input. Consulta anche i suggerimenti per migliorare le prestazioni in tempo reale.
1. Configurare il lettore di codici a barre
Se sai quali formati di codici a barre prevedi di leggere, puoi migliorare la velocità dello scanner configurandolo per eseguire la scansione solo di tali formati.Ad esempio, per scansionare solo il codice azteco e i codici QR, crea un oggetto BarcodeScannerOptions
come nell'esempio seguente:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Sono supportati i seguenti formati:
- codice128
- codice39
- codice93
- codabar
- DataMatrix
- EAN13
- EAN8
- ITF
- Codice qr
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Sono supportati i seguenti formati:
- Codice-128 (
MLKBarcodeFormatCode128
) - Codice-39 (
MLKBarcodeFormatCode39
) - Codice-93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Matrice di dati (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - Codice QR (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Codice azteco (
MLKBarcodeFormatAztec
)
2. Prepara l'immagine di input
Per scansionare i codici a barre in un'immagine, passa l'immagine comeUIImage
o CMSampleBufferRef
al metodo process()
o results(in:)
di BarcodeScanner
:
Crea un oggetto VisionImage
utilizzando un UIImage
o un
CMSampleBuffer
.
Se utilizzi un UIImage
, segui questi passaggi:
- Crea un oggetto
VisionImage
con ilUIImage
. Assicurati di specificare il.orientation
corretto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Se utilizzi un CMSampleBuffer
, segui questi passaggi:
-
Specifica l'orientamento dei dati dell'immagine contenuti in
CMSampleBuffer
.Per ottenere l'orientamento dell'immagine:
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; } }
- Crea un oggetto
VisionImage
utilizzando l'oggetto e l'orientamentoCMSampleBuffer
: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. Ottieni un'istanza di BarcodeScanner
Ottieni un'istanza diBarcodeScanner
:
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. Elabora immagine
Quindi, passa l'immagine al metodoprocess()
:
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. Ricevi informazioni dai codici a barre
Se l'operazione di scansione del codice a barre ha esito positivo, lo scanner restituisce un array di oggettiBarcode
. Ogni oggetto Barcode
rappresenta un
codice a barre rilevato nell'immagine. Per ogni codice a barre, puoi ottenere le coordinate di delimitazione nell'immagine di input, nonché i dati non elaborati codificati dal codice a barre. Inoltre, se lo scanner di codici a barre è in grado di determinare il tipo di dati codificati dal codice a barre, puoi ottenere un oggetto contenente dati analizzati.
Ad esempio:
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; } }
Suggerimenti per migliorare il rendimento in tempo reale
Se vuoi scansionare i codici a barre in un'applicazione in tempo reale, segui queste linee guida per ottenere la migliore frequenza fotogrammi:
-
Non acquisire l'input con la risoluzione nativa della videocamera. Su alcuni dispositivi, l'acquisizione degli input con la risoluzione nativa produce immagini estremamente grandi (oltre 10 megapixel), il che si traduce in una latenza molto bassa senza vantaggi per la precisione. Richiedere invece alla fotocamera solo le dimensioni necessarie per la scansione dei codici a barre, che di solito non superano i 2 megapixel.
Tuttavia, i valori predefiniti per le sessioni di acquisizione (
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
e così via) non sono consigliati, in quanto possono essere mappati a risoluzioni non adatte su alcuni dispositivi. Utilizza invece le preimpostazioni specifiche, comeAVCaptureSessionPreset1280x720
.Se la velocità di scansione è importante, puoi ridurre ulteriormente la risoluzione di acquisizione delle immagini. Tuttavia, tieni presente i requisiti minimi per le dimensioni dei codici a barre indicati sopra.
Se stai cercando di riconoscere i codici a barre da una sequenza di frame video in streaming, il riconoscimento potrebbe produrre risultati diversi da un frame all'altro. Devi attendere finché non ottieni una serie consecutivi di valori uguali per assicurarti di restituire un buon risultato.
La cifra di checksum non è supportata per ITF e CODE-39.
- Per l'elaborazione dei frame video, utilizza l'API sincrona
results(in:)
del rilevatore. Richiama questo metodo dalla funzionecaptureOutput(_, didOutput:from:)
diAVCaptureVideoDataOutputSampleBufferDelegate
per ottenere in modo sincrono i risultati dal frame video specificato. MantienialwaysDiscardsLateVideoFrames
diAVCaptureVideoDataOutput
cometrue
per limitare le chiamate al rilevatore. Se un nuovo video diventa disponibile mentre il rilevatore è in esecuzione, viene eliminato. - Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, prima ottieni il risultato da ML Kit, quindi visualizza l'immagine e l'overlay in un solo passaggio. In questo modo, visualizzerai nella piattaforma display solo una volta per ogni frame di input elaborato. Guarda un esempio di updateAnteprimaOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.