Scansione dei codici a barre con ML Kit su iOS

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

  1. Includi i seguenti pod ML Kit nel podfile:
    pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
    
  2. 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:

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 scansionare i codici a barre in un'immagine, passa l'immagine come UIImage 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 con UIImage. 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 dell'immagine contenuti nei 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 il metodo CMSampleBuffer oggetto e 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. Recupera un'istanza del lettore di codici a barre

Recupera un'istanza di BarcodeScanner:

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 metodo process():

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. Ricevere informazioni da codici a barre

Se la scansione del codice a barre ha esito positivo, lo scanner restituisce un array di Barcode 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:

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 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 esempio AVCaptureSessionPreset1280x720.

    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 di AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) per ottenere in modo sincrono i risultati dal video specificato frame. Mantieni di AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames come true 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.