Puede utilizar ML Kit para reconocer y decodificar códigos de barras.
Antes de que empieces
- Si aún no has agregado Firebase a tu aplicación, hazlo siguiendo los pasos de la guía de introducción .
- Incluya las bibliotecas del kit ML 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
. - En tu aplicación, importa Firebase:
Rápido
import Firebase
C objetivo
@import Firebase;
Pautas de imagen de entrada
Para que ML Kit lea códigos de barras con precisión, las imágenes de entrada deben contener códigos de barras 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 4 unidades. 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, 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 con una resolución más baja, pero exigiendo 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ódigos 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 que solo detecte esos formatos. Por ejemplo, para detectar solo códigos Aztec 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ódigo 128
- 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 (
FIRVisionBarcodeFormatPDF417
) - Azteca (
FIRVisionBarcodeFormatAztec
) - Matriz de datos (
FIRVisionBarcodeFormatDataMatrix
)
2. Ejecute el detector de códigos de barras
Para escanear códigos de barras en una imagen, pase la imagen comoUIImage
o CMSampleBufferRef
al método detect(in:)
de VisionBarcodeDetector
:- 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];
Cree un objeto
VisionImage
utilizandoUIImage
oCMSampleBufferRef
.Para usar una
UIImage
:- Si es necesario, gire la imagen para que su propiedad
imageOrientation
sea.up
. - Cree un objeto
VisionImage
utilizandoUIImage
girado correctamente. No especifique ningún metadato de rotación; se debe utilizar el valor predeterminado,.topLeft
.Rápido
let image = VisionImage(image: uiImage)
C objetivo
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para utilizar
CMSampleBufferRef
:Cree un objeto
VisionImageMetadata
que especifique la orientación de los datos de la imagen contenidos en el búferCMSampleBufferRef
.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];
- Cree un objeto
VisionImage
utilizando el objetoCMSampleBufferRef
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;
- Si es necesario, gire la imagen para que su propiedad
- 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. Obtener información de códigos de barras
Si la operación de reconocimiento del código de barras tiene éxito, el detector devuelve una matriz de objetosVisionBarcode
. 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 delimitadoras 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ódigos 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; } }
Consejos 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 velocidades de fotogramas:
No capture entradas con la resolución nativa de la cámara. En algunos dispositivos, capturar la entrada con la resolución nativa produce imágenes extremadamente grandes (más de 10 megapíxeles), lo que resulta en una latencia muy pobre sin ningún beneficio para la precisión. En su lugar, solicite a la cámara únicamente el tamaño necesario para la detección de códigos de barras: normalmente 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 ajustes preestablecidos específicos comoAVCaptureSessionPreset1280x720
.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 hay un nuevo cuadro de video disponible mientras el detector está en ejecución, suelte el cuadro.
- Si está utilizando la salida del detector para superponer gráficos en la imagen de entrada, primero obtenga el resultado del ML Kit, luego renderice la imagen y superpóngala en un solo paso. Al hacerlo, renderiza en la superficie de visualización solo una vez por cada cuadro de entrada. Consulte las clases previaOverlayView y FIRDetectionOverlayView en la aplicación de muestra de presentación para ver un ejemplo.