Puoi utilizzare ML Kit per riconoscere e decodificare i codici a barre.
Prova
- Prova l'app di esempio per per vedere un esempio di utilizzo di questa API.
Prima di iniziare
- Includi i seguenti pod ML Kit nel podfile:
pod 'GoogleMLKit/BarcodeScanning', '7.0.0'
- Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando la relativa
.xcworkspace
. ML Kit è supportato in Xcode versione 12.4 o successiva.
Linee guida per l'immagine di input
-
Affinché ML Kit possa leggere accuratamente i codici a barre, le immagini di input devono contenere codici a barre rappresentati da un numero sufficiente di dati di pixel.
I requisiti specifici dei dati relativi ai pixel dipendono da entrambi i tipi di il codice a barre e la quantità di dati codificati al suo interno, dato che molti codici a barre per supportare un payload di dimensione variabile. In generale, la variante più piccola dell'unità di misura del codice a barre deve essere larga almeno 2 pixel e, per Codici bidimensionali, altezza di 2 pixel.
Ad esempio, i codici a barre EAN-13 sono composti da barre e spazi che sono 1, 2, 3 o 4 unità di larghezza, quindi un'immagine con codice a barre EAN-13 idealmente contiene barre e spazi di almeno 2, 4, 6 e 8 pixel di larghezza. Poiché un EAN-13 il codice a barre è largo in totale 95 unità, il codice a barre deve essere almeno 190 pixel di larghezza.
I formati più densi, come PDF417, richiedono dimensioni in pixel maggiori per ML Kit per leggerli in modo affidabile. Ad esempio, un codice PDF417 può avere fino a 34 "parole" di 17 unità di un'unica riga, il che sarebbe idealmente Larghezza 1156 pixel.
-
Una scarsa messa a fuoco dell'immagine può influire sulla precisione della scansione. Se la tua app non riceve accettabili, chiedi all'utente di recuperare l'immagine.
-
Per le applicazioni tipiche, consigliamo di fornire una maggiore un'immagine con risoluzione massima, ad esempio 1280 x 720 o 1920 x 1080, che consente di creare codici a barre scansionabili da una distanza maggiore dalla fotocamera.
Tuttavia, nelle applicazioni in cui la latenza è fondamentale, puoi migliorare rendimento delle immagini acquisendo immagini a una risoluzione più bassa, ma richiedendo il codice a barre costituisce la maggior parte dell'immagine di input. Vedi anche Suggerimenti per migliorare il rendimento in tempo reale.
1. Configura il lettore di codici a barre
Se sai quali formati di codici a barre ti aspetti di leggere, puoi migliorare la velocità del lettore di codici a barre configurandolo per scansionare solo quei formati.Ad esempio, per scansionare solo il codice Azteca e i codici QR, crea un
BarcodeScannerOptions
come nell'oggetto
nell'esempio seguente:
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
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
ai BarcodeScanner
di process()
o results(in:)
:
Crea un oggetto VisionImage
utilizzando un UIImage
o un
CMSampleBuffer
.
Se usi un UIImage
, segui questi passaggi:
- Crea un oggetto
VisionImage
conUIImage
. Assicurati di specificare il valore.orientation
corretto.let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Se usi un CMSampleBuffer
, segui questi passaggi:
-
Specifica l'orientamento dei dati dell'immagine contenuti nei
CMSampleBuffer
.Per ottenere l'orientamento dell'immagine:
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 } }
- (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 il metodoCMSampleBuffer
oggetto e orientamento:let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Recupera un'istanza del lettore di codici a barre
Recupera un'istanza diBarcodeScanner
:
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
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()
:
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
5. Ricevere informazioni da codici a barre
Se la scansione del codice a barre ha esito positivo, lo scanner restituisce un array diBarcode
oggetti. Ogni oggetto Barcode
rappresenta un
del codice a barre rilevato nell'immagine. Per ogni codice a barre, puoi ottenere il suo
le coordinate di delimitazione nell'immagine di input, nonché i dati non elaborati codificati
codice a barre. Inoltre, se il lettore di codici a barre è riuscito a determinare il tipo di dati,
codificato dal codice a barre, puoi ottenere un oggetto contenente i dati analizzati.
Ad esempio:
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 } }
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 desideri eseguire la scansione dei codici a barre in un'applicazione in tempo reale, procedi nel seguente modo: linee guida per ottenere le migliori frequenze fotogrammi:
-
Non acquisire input alla risoluzione nativa della videocamera. Su alcuni dispositivi, l'input alla risoluzione nativa produce risultati estremamente grandi (10+ megapixel), il che genera una latenza molto scarsa senza alcun vantaggio la precisione. Richiedi invece alla fotocamera solo la dimensione necessaria per la scansione dei codici a barre, che di solito non supera i 2 megapixel.
Le preimpostazioni della sessione di acquisizione denominate:
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
e così via), tuttavia, non sono consigliati in quanto possono essere mappati risoluzioni non adatte su alcuni dispositivi. Usa invece i predefiniti specifici ad esempioAVCaptureSessionPreset1280x720
.Se la velocità di scansione è importante, puoi ridurre ulteriormente l'acquisizione delle immagini risoluzione del problema. Tuttavia, tieni presente i requisiti minimi per le dimensioni del codice a barre. descritti sopra.
Se stai cercando di riconoscere i codici a barre da una sequenza di flussi di dati fotogrammi video, il riconoscimento potrebbe produrre risultati diversi da frame a frame. Devi attendere di ricevere una serie consecutiva dello stesso per avere la certezza di restituire un buon risultato.
La cifra di checksum non è supportata per ITF e CODE-39.
- Per elaborare i fotogrammi video, utilizza l'API sincrona
results(in:)
del rilevatore. Chiama questo metodo dal diAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
per ottenere in modo sincrono i risultati dal video specificato frame. Mantieni diAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
cometrue
per limitare le chiamate al rilevatore. Se un nuovo il fotogramma video diventa disponibile mentre il rilevatore è in esecuzione, quindi verrà eliminato. - Se utilizzi l'output del rilevatore per sovrapporre elementi grafici l'immagine di input, occorre prima ottenere il risultato da ML Kit, quindi eseguire il rendering dell'immagine e la sovrapposizione in un solo passaggio. In questo modo, visualizzi la pagina solo una volta per ogni frame di input elaborato. Vedi la pagina updatePreviewOverlayViewWithLastFrame. nell'esempio della guida rapida di ML Kit.