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

Digitalize códigos de barras com o ML Kit no iOS

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Você pode usar o ML Kit para reconhecer e decodificar códigos de barras.

Antes de você começar

  1. Se você ainda não adicionou o Firebase ao seu aplicativo, faça isso seguindo as etapas do guia de primeiros passos .
  2. Inclua as bibliotecas do ML Kit em seu Podfile:
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    Depois de instalar ou atualizar os Pods do seu projeto, certifique-se de abrir seu projeto Xcode usando seu .xcworkspace .
  3. No seu aplicativo, importe o Firebase:

    Rápido

    import Firebase

    Objetivo-C

    @import Firebase;

Diretrizes de imagem de entrada

  • Para que o ML Kit leia códigos de barras com precisão, as imagens de entrada devem conter códigos de barras representados por dados de pixel suficientes.

    Os requisitos específicos de dados de pixel dependem do tipo de código de barras e da quantidade de dados nele codificados (já que a maioria dos códigos de barras suporta uma carga útil de comprimento variável). Em geral, a menor unidade significativa do código de barras deve ter pelo menos 2 pixels de largura (e para códigos bidimensionais, 2 pixels de altura).

    Por exemplo, os códigos de barras EAN-13 são compostos de barras e espaços com 1, 2, 3 ou 4 unidades de largura, portanto, uma imagem de código de barras EAN-13 idealmente tem barras e espaços com pelo menos 2, 4, 6 e 8 pixels de largura. Como um código de barras EAN-13 tem 95 unidades de largura no total, o código de barras deve ter pelo menos 190 pixels de largura.

    Formatos mais densos, como PDF417, precisam de dimensões de pixel maiores para que o ML Kit os leia de forma confiável. Por exemplo, um código PDF417 pode ter até 34 "palavras" de 17 unidades de largura em uma única linha, que idealmente teria pelo menos 1156 pixels de largura.

  • O foco de imagem ruim pode prejudicar a precisão da digitalização. Se você não estiver obtendo resultados aceitáveis, tente pedir ao usuário para recapturar a imagem.

  • Para aplicações típicas, recomenda-se fornecer uma imagem de resolução mais alta (como 1280x720 ou 1920x1080), o que torna os códigos de barras detectáveis ​​a uma distância maior da câmera.

    No entanto, em aplicativos em que a latência é crítica, você pode melhorar o desempenho capturando imagens em uma resolução mais baixa, mas exigindo que o código de barras constitua a maior parte da imagem de entrada. Consulte também Dicas para melhorar o desempenho em tempo real .

1. Configure o detector de código de barras

Se você souber quais formatos de código de barras espera ler, poderá melhorar a velocidade do detector de código de barras configurando-o para detectar apenas esses formatos.

Por exemplo, para detectar apenas código asteca e códigos QR, crie um objeto VisionBarcodeDetectorOptions como no exemplo a seguir:

Rápido

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

Os seguintes formatos são suportados:

  • Código 128
  • Código 39
  • Código 93
  • CodaBarGenericName
  • EAN13
  • EAN8
  • ITF
  • UPCA
  • UPCE
  • Código QR
  • PDF417
  • asteca
  • Matriz de dados

Objetivo-C

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

Os seguintes formatos são suportados:

  • 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 ( FIRVisionBarcodeFormatPDF417 )
  • Aztec ( FIRVisionBarcodeFormatAztec )
  • Matriz de dados ( FIRVisionBarcodeFormatDataMatrix )

2. Execute o detector de código de barras

Para digitalizar códigos de barras em uma imagem, passe a imagem como UIImage ou CMSampleBufferRef para o método detect(in:) do VisionBarcodeDetector :

  1. Obtenha uma instância de VisionBarcodeDetector :

    Rápido

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

    Objetivo-C

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

    Para usar uma UIImage :

    1. Se necessário, gire a imagem para que sua propriedade imageOrientation seja .up .
    2. Crie um objeto VisionImage usando o UIImage girado corretamente. Não especifique nenhum metadados de rotação — o valor padrão, .topLeft , deve ser usado.

      Rápido

      let image = VisionImage(image: uiImage)

      Objetivo-C

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

    Para usar um CMSampleBufferRef :

    1. Crie um objeto VisionImageMetadata que especifica a orientação dos dados de imagem contidos no buffer CMSampleBufferRef .

      Para obter a orientação da imagem:

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

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

      Em seguida, crie o objeto de metadados:

      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
      )

      Objetivo-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. Crie um objeto VisionImage usando o objeto CMSampleBufferRef e os metadados de rotação:

      Rápido

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

      Objetivo-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Em seguida, passe a imagem para o método detect(in:) :

    Rápido

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

    Objetivo-C

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

3. Obtenha informações de códigos de barras

Se a operação de reconhecimento de código de barras for bem-sucedida, o detector retornará uma matriz de objetos VisionBarcode . Cada objeto VisionBarcode representa um código de barras que foi detectado na imagem. Para cada código de barras, você pode obter suas coordenadas delimitadoras na imagem de entrada, bem como os dados brutos codificados pelo código de barras. Além disso, se o detector de código de barras foi capaz de determinar o tipo de dados codificados pelo código de barras, você pode obter um objeto contendo dados analisados.

Por exemplo:

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

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

Dicas para melhorar o desempenho em tempo real

Se você deseja escanear códigos de barras em um aplicativo em tempo real, siga estas diretrizes para obter as melhores taxas de quadros:

  • Não capture a entrada na resolução nativa da câmera. Em alguns dispositivos, a captura de entrada na resolução nativa produz imagens extremamente grandes (mais de 10 megapixels), o que resulta em latência muito baixa, sem benefício para a precisão. Em vez disso, solicite à câmera apenas o tamanho necessário para a detecção do código de barras: geralmente não mais que 2 megapixels.

    As predefinições de sessão de captura nomeadas — AVCaptureSessionPresetDefault , AVCaptureSessionPresetLow , AVCaptureSessionPresetMedium e assim por diante) — não são recomendadas, pois podem mapear para resoluções inadequadas em alguns dispositivos. Em vez disso, use as predefinições específicas, como AVCaptureSessionPreset1280x720 .

    Se a velocidade de digitalização for importante, você pode diminuir ainda mais a resolução de captura da imagem. No entanto, tenha em mente os requisitos mínimos de tamanho do código de barras descritos acima.

  • Acelere as chamadas para o detector. Se um novo quadro de vídeo ficar disponível enquanto o detector estiver em execução, descarte o quadro.
  • Se você estiver usando a saída do detector para sobrepor gráficos na imagem de entrada, primeiro obtenha o resultado do ML Kit e, em seguida, renderize a imagem e a sobreposição em uma única etapa. Ao fazer isso, você renderiza para a superfície de exibição apenas uma vez para cada quadro de entrada. Consulte as classes previewOverlayView e FIRDetectionOverlayView no aplicativo de amostra de demonstração para obter um exemplo.