Puede usar ML Kit para reconocer y decodificar códigos de barras.
Antes de que empieces
- Si aún no ha agregado Firebase a su aplicación, hágalo siguiendo los pasos de la guía de inicio .
- 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
. - 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 comoUIImage
o CMSampleBufferRef
al VisionBarcodeDetector
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
usandoUIImage
oCMSampleBufferRef
.Para usar una
UIImage
:- Si es necesario, gire la imagen para que su propiedad
imageOrientation
sea.up
. - Cree un objeto
VisionImage
usando laUIImage
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
:Cree un objeto
VisionImageMetadata
que especifique la orientación de los datos de 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. 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 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 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, 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 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.