Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Scanner des codes-barres avec ML Kit sur iOS

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

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

Avant que tu commences

  1. Si vous n'avez pas encore ajouté Firebase à votre application, faites-le en suivant les étapes du guide de démarrage .
  2. Incluez les bibliothèques ML Kit dans votre Podfile :
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    Après avoir installé ou mis à jour les pods de votre projet, assurez-vous d'ouvrir votre projet Xcode à l'aide de son .xcworkspace .
  3. Dans votre application, importez Firebase :

    Rapide

    import Firebase

    Objectif c

    @import Firebase;

Directives pour les images d'entrée

  • Pour que ML Kit lise 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 en matière de données de pixels dépendent à la fois du type de code-barres et de la quantité de données qui y sont encodées (puisque la plupart des codes-barres prennent en charge une charge utile de longueur variable). En général, la plus petite unité significative du code-barres doit mesurer au moins 2 pixels de large (et pour les codes bidimensionnels, 2 pixels de haut).

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

    Les formats plus denses, tels que PDF417, nécessitent des dimensions de pixel plus importantes pour que ML Kit les lise de manière fiable. Par exemple, un code PDF417 peut avoir jusqu'à 34 "mots" de 17 unités de large sur une seule ligne, ce qui devrait idéalement avoir une largeur d'au moins 1156 pixels.

  • Une mauvaise mise au point de l'image peut nuire à la précision de la numérisation. Si vous n'obtenez pas de résultats acceptables, essayez de demander à l'utilisateur de reprendre l'image.

  • Pour les applications typiques, il est recommandé de fournir une image de plus haute résolution (telle que 1280x720 ou 1920x1080), ce qui rend les codes-barres détectables à une plus grande distance de la caméra.

    Cependant, dans les applications où la latence est critique, vous pouvez améliorer les performances en capturant des images à une résolution inférieure, mais en exigeant que le code-barres constitue la majorité de l'image d'entrée. Consultez également Conseils pour améliorer les performances en temps réel .

1. Configurer le détecteur de code-barres

Si vous savez quels formats de code-barres vous comptez lire, vous pouvez améliorer la vitesse du détecteur de code-barres en le configurant pour ne détecter que ces formats.

Par exemple, pour détecter uniquement le code aztèque et les codes QR, créez un objet VisionBarcodeDetectorOptions comme dans l'exemple suivant :

Rapide

let format = VisionBarcodeFormat.all
let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)

Les formats suivants sont pris en charge :

  • Code128
  • Code39
  • Code93
  • CodaBar
  • EAN13
  • EAN8
  • FIT
  • UPCA
  • SEPC
  • QR Code
  • PDF417
  • Aztèque
  • Matrice de données

Objectif c

FIRVisionBarcodeDetectorOptions *options =
    [[FIRVisionBarcodeDetectorOptions alloc]
     initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];

Les formats suivants sont pris en charge :

  • Code 128 ( FIRVisionBarcodeFormatCode128 )
  • Code 39 ( FIRVisionBarcodeFormatCode39 )
  • Code 93 ( FIRVisionBarcodeFormatCode93 )
  • Codabar ( FIRVisionBarcodeFormatCodaBar )
  • EAN-13 ( FIRVisionBarcodeFormatEAN13 )
  • EAN-8 ( FIRVisionBarcodeFormatEAN8 )
  • ITF ( FIRVisionBarcodeFormatITF )
  • UPC-A ( FIRVisionBarcodeFormatUPCA )
  • UPC-E ( FIRVisionBarcodeFormatUPCE )
  • QR Code ( FIRVisionBarcodeFormatQRCode )
  • PDF417 ( FIRVisionBarcodeFormatPDF417 )
  • Aztec ( FIRVisionBarcodeFormatAztec )
  • Matrice de données ( FIRVisionBarcodeFormatDataMatrix )

2. Exécutez le détecteur de code-barres

Pour numériser des codes-barres dans une image, transmettez l'image en tant que UIImage ou CMSampleBufferRef à la VisionBarcodeDetector detect(in:) de VisionBarcodeDetector :

  1. Obtenez une instance de VisionBarcodeDetector :

    Rapide

    lazy var vision = Vision.vision()
    
    let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
    

    Objectif c

    FIRVision *vision = [FIRVision vision];
    FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector];
    // Or, to change the default settings:
    // FIRVisionBarcodeDetector *barcodeDetector =
    //     [vision barcodeDetectorWithOptions:options];
    
  2. Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBufferRef .

    Pour utiliser une UIImage :

    1. Si nécessaire, faites pivoter l'image afin que sa propriété imageOrientation soit .up .
    2. Créez un objet VisionImage à l'aide de l'objet UIImage correctement pivoté. Ne spécifiez aucune métadonnée de rotation—la valeur par défaut, .topLeft , doit être utilisée.

      Rapide

      let image = VisionImage(image: uiImage)

      Objectif c

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    Pour utiliser un CMSampleBufferRef :

    1. Créez un objet VisionImageMetadata qui spécifie l'orientation des données d'image contenues dans le tampon CMSampleBufferRef .

      Pour obtenir l'orientation de l'image :

      Rapide

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

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

      Créez ensuite l'objet de métadonnées :

      Rapide

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      Objectif 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];
    2. Créez un objet VisionImage à l'aide de l'objet CMSampleBufferRef et des métadonnées de rotation :

      Rapide

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      Objectif c

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Ensuite, passez l'image à la méthode detect(in:) :

    Rapide

    barcodeDetector.detect(in: visionImage) { features, error in
      guard error == nil, let features = features, !features.isEmpty else {
        // ...
        return
      }
    
      // ...
    }
    

    Objectif c

    [barcodeDetector detectInImage:image
                        completion:^(NSArray<FIRVisionBarcode *> *barcodes,
                                     NSError *error) {
      if (error != nil) {
        return;
      } else if (barcodes != nil) {
        // Recognized barcodes
        // ...
      }
    }];
    

3. Obtenez des informations à partir des codes-barres

Si l'opération de reconnaissance du code-barres réussit, le détecteur renvoie un tableau d'objets VisionBarcode . Chaque objet VisionBarcode représente un code-barres qui a été détecté dans l'image. Pour chaque code-barres, vous pouvez obtenir ses coordonnées de délimitation dans l'image d'entrée, ainsi que les données brutes encodées par le code-barres. De plus, si le détecteur de code-barres a pu déterminer le type de données encodées par le code-barres, vous pouvez obtenir un objet contenant des données analysées.

Par exemple:

Rapide

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

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

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

Si vous souhaitez numériser des codes-barres dans une application en temps réel, suivez ces instructions pour obtenir les meilleures fréquences d'images :

  • Ne capturez pas l'entrée à la résolution native de la caméra. Sur certains appareils, la capture d'entrée à la résolution native produit des images extrêmement grandes (plus de 10 mégapixels), ce qui entraîne une très faible latence sans avantage pour la précision. Au lieu de cela, demandez uniquement à la caméra la taille requise pour la détection des codes-barres : généralement pas plus de 2 mégapixels.

    Cependant, les préréglages de session de capture nommés ( AVCaptureSessionPresetDefault , AVCaptureSessionPresetLow , AVCaptureSessionPresetMedium , etc.) ne sont pas recommandés, car ils peuvent correspondre à des résolutions inappropriées sur certains appareils. Utilisez plutôt les préréglages spécifiques tels que AVCaptureSessionPreset1280x720 .

    Si la vitesse de numérisation est importante, vous pouvez encore réduire la résolution de capture d'image. Cependant, gardez à l'esprit les exigences de taille minimale de code-barres décrites ci-dessus.

  • Throttle appelle le détecteur. Si une nouvelle image vidéo devient disponible pendant que le détecteur fonctionne, supprimez l'image.
  • Si vous utilisez la sortie du détecteur pour superposer des graphiques sur l'image d'entrée, obtenez d'abord le résultat de ML Kit, puis effectuez le rendu de l'image et de la superposition en une seule étape. Ce faisant, vous effectuez le rendu sur la surface d'affichage une seule fois pour chaque image d'entrée. Voir les classes previewOverlayView et FIRDetectionOverlayView dans l'exemple d'application vitrine pour un exemple.