Scanner des codes-barres avec ML Kit sur iOS

Vous pouvez utiliser ML Kit pour reconnaître et décoder les codes-barres.

Essayer

Avant de commencer

  1. Incluez les pods ML Kit suivants dans votre Podfile:
    pod 'GoogleMLKit/BarcodeScanning', '15.5.0'
    
  2. Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide de son .xcworkspace ML Kit est compatible avec Xcode 12.4 ou version ultérieure.

Consignes pour les images d'entrée

  • Pour que ML Kit puisse lire avec précision les codes-barres, les images d'entrée doivent contenir des codes-barres représentés par suffisamment de données de pixels.

    Les exigences spécifiques concernant les données de pixels dépendent à la fois du type code-barres et la quantité de données qui y sont encodées, puisque de nombreux codes-barres acceptent une charge utile de taille variable. En général, la plus petite l'unité du code-barres doit être d'au moins 2 pixels de large et pour Codes bidimensionnels, hauteur de 2 pixels.

    Par exemple, les codes-barres EAN-13 sont composés de barres et d'espaces 1, 2, 3 ou 4 unités de large, donc une image de code-barres EAN-13 idéalement a des barres et espaces d'au moins 2, 4, 6 et 8 pixels de largeur. Étant donné qu'un code EAN-13 le code-barres fait 95 unités de large au total, le code-barres doit être d'au moins 190 pixels.

    Les formats de densité (tels que PDF417) nécessitent des dimensions en pixels supérieures pour ML Kit pour les lire de manière fiable. Par exemple, un code PDF417 peut contenir jusqu'à 34 "mots" de 17 unités de large sur une même ligne, qui devrait idéalement être au moins Largeur de 1 156 pixels.

  • Une mauvaise mise au point de l'image peut nuire à la précision de la numérisation. Si votre application ne reçoit pas des résultats acceptables, demandez à l'utilisateur de reprendre l'image.

  • Pour les applications classiques, il est recommandé de fournir une résolution d'image, par exemple 1 280 x 720 ou 1 920 x 1 080, qui génère des codes-barres à scanner à une plus grande distance de l'appareil photo.

    Toutefois, dans les applications où la latence est essentielle, vous pouvez améliorer en collectant des images à une résolution inférieure, le code-barres constituent la majorité de l'image d'entrée. Voir aussi Conseils pour améliorer les performances en temps réel

1. Configurer le lecteur de code-barres

Si vous connaissez les formats de code-barres que vous comptez lire, vous pouvez améliorer la vitesse de lecture du lecteur de code-barres en le configurant pour ne lire que ces formats.

Par exemple, pour scanner uniquement du code Aztec et des codes QR, créez un objet BarcodeScannerOptions comme dans l'exemple suivant:

Swift

let format = .all
let barcodeOptions = BarcodeScannerOptions(formats: format)
  

Les formats suivants sont acceptés :

  • code128
  • code39
  • code93
  • codaBar
  • dataMatrix
  • EAN13
  • EAN8
  • ITF
  • qrCode
  • UPCA
  • UPCE
  • PDF417
  • Aztec

Objective-C

MLKBarcodeScannerOptions *options =
  [[MLKBarcodeScannerOptions alloc]
   initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];

Les formats suivants sont acceptés :

  • Code 128 (MLKBarcodeFormatCode128)
  • Code 39 (MLKBarcodeFormatCode39)
  • Code-93 (MLKBarcodeFormatCode93)
  • Codabar (MLKBarcodeFormatCodaBar)
  • Matrice de données (MLKBarcodeFormatDataMatrix)
  • EAN-13 (MLKBarcodeFormatEAN13)
  • EAN-8 (MLKBarcodeFormatEAN8)
  • ITF (MLKBarcodeFormatITF)
  • Code QR (MLKBarcodeFormatQRCode)
  • UPC-A (MLKBarcodeFormatUPCA)
  • UPC-E (MLKBarcodeFormatUPCE)
  • PDF-417 (MLKBarcodeFormatPDF417)
  • Code aztèque (MLKBarcodeFormatAztec)

2. Préparer l'image d'entrée

Pour scanner le code-barres d'une image, transmettez-la en tant que UIImage ou CMSampleBufferRef sur process() ou results(in:) de BarcodeScanner méthode:

Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBuffer

Si vous utilisez un UIImage, procédez comme suit:

  • Créez un objet VisionImage avec UIImage. Veillez à spécifier le bon .orientation.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Si vous utilisez un CMSampleBuffer, procédez comme suit:

  • Spécifiez l'orientation des données d'image contenues dans le CMSampleBuffer

    Pour obtenir l'orientation de l'image:

    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;
      }
    }
          
  • Créez un objet VisionImage à l'aide de la méthode Objet CMSampleBuffer et orientation:

    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. Obtenir une instance de BarcodeScanner

Obtenez une instance de 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. Traiter l'image

Transmettez ensuite l'image à la méthode 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. Obtenir des informations à partir des codes-barres

Si l'opération de lecture du code-barres aboutit, le lecteur renvoie un tableau des Objets Barcode. Chaque objet Barcode représente le code-barres détecté dans l'image. Pour chaque code-barres, vous pouvez obtenir les coordonnées de délimitation dans l'image d'entrée, ainsi que les données brutes encodées par code-barres. De plus, si le lecteur de code-barres a pu déterminer le type de données encodé par le code-barres, vous pouvez obtenir un objet contenant des données analysées.

Exemple :

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;
   }
 }

Conseils pour améliorer les performances en temps réel

Si vous souhaitez scanner des codes-barres dans une application en temps réel, suivez ces pour obtenir des fréquences d'images optimales:

  • Ne enregistrez pas d'entrée à la résolution native de l'appareil photo. Sur certains appareils, la capture d'entrée à la résolution native produit des images extrêmement volumineuses (plus de 10 de pixels), ce qui entraîne une latence très faible et ne présente aucun avantage précision. Demandez plutôt la taille à la caméra requise pour la lecture de codes-barres, qui ne dépasse généralement pas 2 mégapixels.

    Les préréglages de la session de capture nommée : AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium, etc.), elles ne sont pas recommandées, car elles peuvent correspondre les résolutions inappropriées sur certains appareils. Utilisez plutôt les préréglages spécifiques comme AVCaptureSessionPreset1280x720.

    Si la vitesse de numérisation est importante, vous pouvez réduire davantage la capture d'image. la résolution de problèmes. Toutefois, tenez compte des exigences minimales de taille des codes-barres décrites ci-dessus.

    Si vous essayez de reconnaître des codes-barres à partir d'une séquence de flux images vidéo, le programme de reconnaissance peut produire des résultats différents d'une image à l'autre cadre. Attendez d'obtenir des séries consécutives identiques valeur pour être sûr de renvoyer un bon résultat.

    Le chiffre de la somme de contrôle n'est pas accepté pour ITF et CODE-39.

  • Pour traiter les images vidéo, utilisez l'API synchrone results(in:) du détecteur. Appeler cette méthode à partir de AVCaptureVideoDataOutputSampleBufferDelegate <ph type="x-smartling-placeholder"></ph> captureOutput(_, didOutput:from:) pour obtenir les résultats d'une vidéo donnée de manière synchrone. cadre. Conserver <ph type="x-smartling-placeholder"></ph> de AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames en tant que true afin de limiter les appels au détecteur. Si un nouveau l'image vidéo devient disponible pendant l'exécution du détecteur, elle est ignorée.
  • Si vous utilisez la sortie du détecteur pour superposer des graphiques sur l'image d'entrée, récupérez d'abord le résultat à partir de ML Kit, puis effectuez le rendu de l'image. et les superposer en une seule étape. Cela vous permet d'afficher sur la surface d'affichage une seule fois pour chaque trame d'entrée traitée. Affichez la vue updatePreviewOverlayViewWithLastFrame. dans l'exemple de démarrage rapide de ML Kit.