Puoi utilizzare ML Kit per riconoscere e decodificare i codici a barre.
Prova
- Prova l'app di esempio per vedere un utilizzo di esempio di questa API.
Prima di iniziare
- Includi i seguenti pod ML Kit nel podfile:
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando il relativo
.xcworkspace
. ML Kit è supportato in Xcode versione 12.4 o successiva.
Linee guida per l'immagine di input
-
Affinché ML Kit legga accuratamente i codici a barre, le immagini di input devono contenere codici a barre rappresentati da una quantità sufficiente di dati di pixel.
I requisiti specifici dei dati relativi ai pixel dipendono dal tipo di codice a barre e dalla quantità di dati codificati al suo interno, poiché molti codici a barre supportano un payload di dimensioni variabili. In generale, l'unità significativa più piccola del codice a barre deve essere di almeno 2 pixel in larghezza, mentre per i codici bidimensionali deve essere alta 2 pixel.
Ad esempio, i codici a barre EAN-13 sono costituiti da barre e spazi larghi di 1, 2, 3 o 4 unità, pertanto un'immagine dei codici a barre EAN-13 presenta idealmente barre e spazi di almeno 2, 4, 6 e 8 pixel di larghezza. Poiché un codice a barre EAN-13 è largo in totale 95 unità, deve avere una larghezza di almeno 190 pixel.
I formati più densi, come i PDF417, richiedono dimensioni in pixel maggiori affinché ML Kit possa leggerli in modo affidabile. Ad esempio, un codice PDF417 può contenere fino a 34 "parole" larghe 17 unità in una singola riga, idealmente almeno 1156 pixel.
-
Una scarsa messa a fuoco dell'immagine può influire sulla precisione della scansione. Se la tua app non sta ottenendo risultati accettabili, chiedi all'utente di acquisire nuovamente l'immagine.
-
Per le applicazioni tipiche, consigliamo di fornire un'immagine a risoluzione più elevata, ad esempio 1280 x 720 o 1920 x 1080, che consente di leggere i codici a barre da una distanza maggiore dalla fotocamera.
Tuttavia, nelle applicazioni in cui la latenza è fondamentale, è possibile migliorare le prestazioni acquisendo immagini a una risoluzione inferiore, ma è necessario che il codice a barre copra la maggior parte dell'immagine di input. Consulta anche la sezione Suggerimenti per migliorare le prestazioni in tempo reale.
1. Configura il lettore di codici a barre
Se conosci i formati di codici a barre che prevedi di leggere, puoi migliorare la velocità del lettore di codici a barre configurandolo per la scansione dei soli formati.Ad esempio, per scansionare solo codici aztechi e codici QR, crea un oggetto BarcodeScannerOptions
come nell'esempio seguente:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Sono supportati i seguenti formati:
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- 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 eseguire la scansione dei codici a barre in un'immagine, trasmetti l'immagine comeUIImage
o CMSampleBufferRef
al metodo process()
o results(in:)
di BarcodeScanner
:
Crea un oggetto VisionImage
utilizzando UIImage
o CMSampleBuffer
.
Se usi un UIImage
, segui questi passaggi:
- Crea un oggetto
VisionImage
con ilUIImage
. Assicurati di specificare il valore.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 usi un CMSampleBuffer
, segui questi passaggi:
-
Specifica l'orientamento dei dati 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'oggettoCMSampleBuffer
e l'orientamento: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 l'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. Ottieni 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 sue coordinate di delimitazione nell'immagine di input, così come i dati non elaborati codificati dal codice a barre. Inoltre, se lo scanner di codici a barre è riuscito a determinare il tipo di dati
codificati dal codice a barre, puoi ottenere un oggetto contenente i 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 le frequenze fotogrammi migliori:
-
Non acquisire l'input alla risoluzione originale della fotocamera. Su alcuni dispositivi, l'acquisizione dell'input con la risoluzione nativa produce immagini estremamente grandi (oltre 10 megapixel), il che comporta una latenza molto bassa senza alcun vantaggio per l'accuratezza. Richiedi invece solo le dimensioni della fotocamera necessarie per la scansione dei codici a barre, che in genere non superano i 2 megapixel.
Tuttavia, le preimpostazioni della sessione di acquisizione denominate
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
e così via non sono consigliate perché potrebbero essere mappate a risoluzioni non adatte su alcuni dispositivi. Usa invece i valori preimpostati specifici, 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 del codice a barre descritti sopra.
Se stai tentando di riconoscere i codici a barre da una sequenza di fotogrammi video in streaming, il riconoscimento potrebbe produrre risultati diversi da un fotogramma all'altro. Dovresti attendere di ottenere una serie consecutiva dello stesso valore per avere la certezza di restituire un risultato positivo.
La cifra di checksum non è supportata per ITF e CODE-39.
- Per elaborare i fotogrammi 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. Mantieni il valoretrue
peralwaysDiscardsLateVideoFrames
diAVCaptureVideoDataOutput
per limitare le chiamate al rilevatore. Se un nuovo frame video diventa disponibile mentre il rilevatore è in esecuzione, questo verrà eliminato. - Se utilizzi l'output del rilevatore per sovrapporre gli elementi grafici all'immagine di input, recupera prima il risultato da ML Kit, quindi esegui il rendering dell'immagine e dell'overlay in un solo passaggio. In questo modo, esegui il rendering sulla piattaforma di visualizzazione solo una volta per ogni frame di input elaborato. Per un esempio, vedi updatePreviewOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.