Puoi utilizzare ML Kit per riconoscere e decodificare i codici a barre.
Prima di iniziare
- Se non hai ancora aggiunto Firebase alla tua app, segui i passaggi descritti nella guida introduttiva.
- Includi le librerie ML Kit nel tuo Podfile:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
Dopo aver installato o aggiornato i pod del progetto, assicurati di aprire il progetto Xcode utilizzando il relativo.xcworkspace
. - Nell'app, importa Firebase:
Swift
import Firebase
Objective-C
@import Firebase;
Linee guida per le immagini di input
-
Affinché ML Kit legga con precisione i codici a barre, le immagini di input devono contenere codici a barre rappresentati da dati di pixel sufficienti.
I requisiti specifici dei dati dei pixel dipendono sia dal tipo di codice a barre sia dalla quantità di dati codificati al suo interno (poiché la maggior parte dei codici a barre supporta un payload di lunghezza variabile). In generale, l'unità minima significativa del codice a barre deve avere una larghezza di almeno 2 pixel (e per i codici 2D, un'altezza di 2 pixel).
Ad esempio, i codici a barre EAN-13 sono costituiti da barre e spazi di larghezza 1, 2, 3 o 4 unità, pertanto un'immagine di un codice a barre EAN-13 dovrebbe avere barre e spazi di almeno 2, 4, 6 e 8 pixel di larghezza. Poiché un codice a barre EAN-13 ha una larghezza totale di 95 unità, deve avere una larghezza di almeno 190 pixel.
I formati più densi, come PDF417, richiedono dimensioni dei pixel maggiori per consentire a ML Kit di leggerli in modo affidabile. Ad esempio, un codice PDF417 può avere fino a 34 "parole" di 17 unità di larghezza in una singola riga, che idealmente dovrebbe essere di almeno 1156 pixel di larghezza.
-
Una messa a fuoco scadente dell'immagine può influire sulla precisione della scansione. Se non ottieni risultati accettabili, prova a chiedere all'utente di acquisire di nuovo l'immagine.
-
Per le applicazioni standard, è consigliabile fornire un'immagine con una risoluzione superiore (ad esempio 1280 x 720 o 1920 x 1080), che rende i codici a barre rilevabili da una distanza maggiore dalla videocamera.
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 Suggerimenti per migliorare il rendimento in tempo reale.
1. Configurare il rilevatore di codici a barre
Se sai quali formati di codici a barre prevedi di leggere, puoi migliorare la velocità del rilevatore di codici a barre configurandolo in modo da rilevare solo questi formati.Ad esempio, per rilevare solo codici Aztec e QR, crea un oggetto
VisionBarcodeDetectorOptions
come nell'esempio seguente:
Swift
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
Sono supportati i seguenti formati:
- Code128
- Code39
- Code93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- Codice QR
- PDF417
- Azteco
- DataMatrix
Objective-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
Sono supportati i seguenti formati:
- Code 128 (
FIRVisionBarcodeFormatCode128
) - Code 39 (
FIRVisionBarcodeFormatCode39
) - Codice 93 (
FIRVisionBarcodeFormatCode93
) - Codabar (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ITF (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - Codice QR (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - Aztec (
FIRVisionBarcodeFormatAztec
) - Data Matrix (
FIRVisionBarcodeFormatDataMatrix
)
2. Esegui il rilevamento dei codici a barre
Per scansionare i codici a barre in un'immagine, passa l'immagine comeUIImage
o
CMSampleBufferRef
al metodo detect(in:)
di VisionBarcodeDetector
:
- Recupera un'istanza di
VisionBarcodeDetector
:Swift
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
Objective-C
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
-
Crea un oggetto
VisionImage
utilizzando unUIImage
o unCMSampleBufferRef
.Per utilizzare un
UIImage
:- Se necessario, ruota l'immagine in modo che la sua proprietà
imageOrientation
sia.up
. - Crea un oggetto
VisionImage
utilizzando ilUIImage
ruotato correttamente. Non specificare metadati di rotazione. Deve essere utilizzato il valore predefinito.topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Per utilizzare un
CMSampleBufferRef
:-
Crea un oggetto
VisionImageMetadata
che specifichi l'orientamento dei dati immagine contenuti nel bufferCMSampleBufferRef
.Per ottenere l'orientamento dell'immagine:
Swift
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 } }
Objective-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; } }
Quindi, crea l'oggetto dei metadati:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-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];
- Crea un oggetto
VisionImage
utilizzando l'oggettoCMSampleBufferRef
e i metadati di rotazione:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Se necessario, ruota l'immagine in modo che la sua proprietà
-
Quindi, passa l'immagine al metodo
detect(in:)
:Swift
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
Objective-C
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. Ottenere informazioni dai codici a barre
Se l'operazione di riconoscimento del codice a barre va a buon fine, il rilevatore restituisce un array di oggettiVisionBarcode
. Ogni oggetto VisionBarcode
rappresenta un codice a barre rilevato nell'immagine. Per ogni codice a barre, puoi ottenere le sue coordinate di confine nell'immagine di input, nonché i dati non elaborati codificati dal codice a barre. Inoltre, se il rilevatore di codici a barre è stato in grado di 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 (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; } }
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 frame migliori:
-
Non acquisire l'input alla risoluzione nativa della fotocamera. Su alcuni dispositivi, l'acquisizione dell'input alla risoluzione nativa produce immagini estremamente grandi (più di 10 megapixel), il che si traduce in una latenza molto bassa senza alcun vantaggio per la precisione. Richiedi invece alla fotocamera solo le dimensioni richieste per il rilevamento del codice a barre: in genere non più di 2 megapixel.
Tuttavia, le preimpostazioni delle sessioni di acquisizione denominate (
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
e così via) non sono consigliate, in quanto possono essere mappate a risoluzioni non idonee 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 relativi alle dimensioni del codice a barre descritti sopra.
- Regola le chiamate al rilevatore. Se un nuovo frame video diventa disponibile mentre il rilevatore è in esecuzione, inseriscilo.
- Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, ottieni prima il risultato da ML Kit, poi esegui il rendering dell'immagine e la sovrapposizione in un unico passaggio. In questo modo, esegui il rendering sulla superficie di visualizzazione solo una volta per ogni frame di input. Per un esempio, consulta le classi previewOverlayView e FIRDetectionOverlayView nell'app di esempio della vetrina.