Entérate de todos los anuncios de Firebase Summit y descubre cómo Firebase puede ayudarte a acelerar el desarrollo de las apps y a ejecutarlas con confianza. Más información

Escanear códigos de barras con ML Kit en iOS

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Puede usar ML Kit para reconocer y decodificar códigos de barras.

Antes de que empieces

  1. Si aún no ha agregado Firebase a su aplicación, hágalo siguiendo los pasos de la guía de inicio .
  2. Incluya las bibliotecas de ML Kit en su Podfile:
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    Después de instalar o actualizar los Pods de su proyecto, asegúrese de abrir su proyecto Xcode usando su .xcworkspace .
  3. En su aplicación, importe Firebase:

    Rápido

    import Firebase

    C objetivo

    @import Firebase;

Directrices de la imagen de entrada

  • Para que ML Kit lea con precisión los códigos de barras, las imágenes de entrada deben contener códigos de barras que estén representados por suficientes datos de píxeles.

    Los requisitos de datos de píxeles específicos dependen tanto del tipo de código de barras como de la cantidad de datos codificados en él (ya que la mayoría de los códigos de barras admiten una carga útil de longitud variable). En general, la unidad significativa más pequeña del código de barras debe tener al menos 2 píxeles de ancho (y para códigos bidimensionales, 2 píxeles de alto).

    Por ejemplo, los códigos de barras EAN-13 se componen de barras y espacios de 1, 2, 3 o 4 unidades de ancho, por lo que una imagen de código de barras EAN-13 idealmente tiene barras y espacios de al menos 2, 4, 6 y 8 píxeles de ancho. Debido a que un código de barras EAN-13 tiene 95 unidades de ancho en total, el código de barras debe tener al menos 190 píxeles de ancho.

    Los formatos más densos, como PDF417, necesitan mayores dimensiones de píxeles para que ML Kit los lea de manera confiable. Por ejemplo, un código PDF417 puede tener hasta 34 "palabras" de 17 unidades de ancho en una sola fila, lo que idealmente tendría al menos 1156 píxeles de ancho.

  • Un enfoque deficiente de la imagen puede afectar la precisión del escaneo. Si no obtiene resultados aceptables, intente pedirle al usuario que vuelva a capturar la imagen.

  • Para aplicaciones típicas, se recomienda proporcionar una imagen de mayor resolución (como 1280x720 o 1920x1080), lo que hace que los códigos de barras sean detectables desde una distancia mayor de la cámara.

    Sin embargo, en aplicaciones donde la latencia es crítica, puede mejorar el rendimiento capturando imágenes a una resolución más baja, pero requiriendo que el código de barras constituya la mayor parte de la imagen de entrada. Consulte también Sugerencias para mejorar el rendimiento en tiempo real .

1. Configurar el detector de código de barras

Si sabe qué formatos de códigos de barras espera leer, puede mejorar la velocidad del detector de códigos de barras configurándolo para detectar solo esos formatos.

Por ejemplo, para detectar solo código azteca y códigos QR, cree un objeto VisionBarcodeDetectorOptions como en el siguiente ejemplo:

Rápido

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

Se admiten los siguientes formatos:

  • código128
  • código39
  • código93
  • CodaBar
  • EAN13
  • EAN8
  • ITF
  • UPCA
  • UPCE
  • Código QR
  • PDF417
  • azteca
  • Matriz de datos

C objetivo

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

Se admiten los siguientes formatos:

  • Código 128 ( FIRVisionBarcodeFormatCode128 )
  • Código 39 ( FIRVisionBarcodeFormatCode39 )
  • Código 93 ( FIRVisionBarcodeFormatCode93 )
  • Codabar ( FIRVisionBarcodeFormatCodaBar )
  • EAN-13 ( FIRVisionBarcodeFormatEAN13 )
  • EAN-8 ( FIRVisionBarcodeFormatEAN8 )
  • ITF ( FIRVisionBarcodeFormatITF )
  • UPC-A ( FIRVisionBarcodeFormatUPCA )
  • UPC-E ( FIRVisionBarcodeFormatUPCE )
  • Código QR ( FIRVisionBarcodeFormatQRCode )
  • PDF417 (Formato de código FIRVisionBarcodeFormatPDF417 )
  • Azteca ( FIRVisionBarcodeFormatAztec )
  • Matriz de datos ( FIRVisionBarcodeFormatDataMatrix )

2. Ejecute el detector de código de barras

Para escanear códigos de barras en una imagen, pase la imagen como UIImage o CMSampleBufferRef al VisionBarcodeDetector detect(in:) de VisionBarcodeDetector:

  1. Obtenga una instancia de VisionBarcodeDetector :

    Rápido

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

    C objetivo

    FIRVision *vision = [FIRVision vision];
    FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector];
    // Or, to change the default settings:
    // FIRVisionBarcodeDetector *barcodeDetector =
    //     [vision barcodeDetectorWithOptions:options];
    
  2. Cree un objeto VisionImage usando UIImage o CMSampleBufferRef .

    Para usar una UIImage :

    1. Si es necesario, gire la imagen para que su propiedad imageOrientation sea .up .
    2. Cree un objeto VisionImage usando la UIImage girada correctamente. No especifique ningún metadato de rotación; se debe usar el valor predeterminado, .topLeft .

      Rápido

      let image = VisionImage(image: uiImage)

      C objetivo

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

    Para usar un CMSampleBufferRef :

    1. Cree un objeto VisionImageMetadata que especifique la orientación de los datos de imagen contenidos en el búfer CMSampleBufferRef .

      Para obtener la orientación de la imagen:

      Rápido

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

      C objetivo

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

      Luego, crea el objeto de metadatos:

      Rápido

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

      C objetivo

      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. Cree un objeto VisionImage utilizando el objeto CMSampleBufferRef y los metadatos de rotación:

      Rápido

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

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Luego, pasa la imagen al método detect(in:) :

    Rápido

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

    C objetivo

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

3. Obtenga información de los códigos de barras

Si la operación de reconocimiento del código de barras tiene éxito, el detector devuelve una matriz de objetos VisionBarcode . Cada objeto VisionBarcode representa un código de barras que se detectó en la imagen. Para cada código de barras, puede obtener sus coordenadas de límite en la imagen de entrada, así como los datos sin procesar codificados por el código de barras. Además, si el detector de código de barras pudo determinar el tipo de datos codificados por el código de barras, puede obtener un objeto que contenga datos analizados.

Por ejemplo:

Rápido

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

C objetivo

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

Sugerencias para mejorar el rendimiento en tiempo real

Si desea escanear códigos de barras en una aplicación en tiempo real, siga estas pautas para lograr las mejores tasas de cuadros:

  • No capture la entrada en la resolución nativa de la cámara. En algunos dispositivos, la captura de entrada a la resolución nativa produce imágenes extremadamente grandes (más de 10 megapíxeles), lo que da como resultado una latencia muy baja sin ningún beneficio para la precisión. En su lugar, solo solicite el tamaño de la cámara que se requiere para la detección del código de barras: por lo general, no más de 2 megapíxeles.

    Sin embargo, no se recomiendan los ajustes preestablecidos de sesión de captura con nombre ( AVCaptureSessionPresetDefault , AVCaptureSessionPresetLow , AVCaptureSessionPresetMedium , etc.), ya que pueden asignarse a resoluciones inadecuadas en algunos dispositivos. En su lugar, utilice los ajustes preestablecidos específicos, como AVCaptureSessionPreset1280x720 .

    Si la velocidad de escaneo es importante, puede reducir aún más la resolución de captura de imágenes. Sin embargo, tenga en cuenta los requisitos de tamaño mínimo de código de barras descritos anteriormente.

  • Llamadas del acelerador al detector. Si un nuevo cuadro de video está disponible mientras el detector está funcionando, suelte el cuadro.
  • Si está utilizando la salida del detector para superponer gráficos en la imagen de entrada, primero obtenga el resultado de ML Kit, luego renderice la imagen y superponga en un solo paso. Al hacerlo, renderiza en la superficie de visualización solo una vez para cada cuadro de entrada. Consulte las clases previewOverlayView y FIRDetectionOverlayView en la aplicación de ejemplo de presentación para ver un ejemplo.