Puedes usar ML Kit para reconocer y decodificar códigos de barras.
Probar
- Prueba la app de ejemplo para ver un ejemplo de uso de esta API.
Antes de comenzar
- Incluye los siguientes pods del ML Kit en tu Podfile:
pod 'GoogleMLKit/BarcodeScanning', '15.5.0'
- Después de instalar o actualizar los Pods de tu proyecto, abre el proyecto de Xcode a través de su
.xcworkspace
El Kit de AA es compatible con Xcode 12.4 o versiones posteriores.
Lineamientos para imágenes de entrada
-
Para que el Kit de AA lea correctamente los códigos de barras, las imágenes de entrada deben contener códigos de barras representados con datos de píxeles suficientes.
Los requisitos específicos de los datos de los píxeles dependen del tipo de código de barras y la cantidad de datos codificados en él, ya que muchos de los admiten una carga útil de tamaño variable. En general, la parte más pequeña del código de barras debe tener al menos 2 píxeles de ancho y, para Códigos bidimensionales de 2 píxeles de altura
Por ejemplo, los códigos de barras EAN-13 se componen de barras y espacios 1, 2, 3 o 4 unidades de ancho, por lo que una imagen de código de barras EAN-13 tiene, idealmente, barras y espacios que tengan al menos 2, 4, 6 y 8 píxeles de ancho. Debido a que un EAN-13 el código de barras 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 para leerlas de forma confiable. Por ejemplo, un código PDF417 puede tener hasta 34 “words” de 17 unidades en una sola fila, lo que idealmente sería al menos 1,156 píxeles de ancho
-
Un enfoque de imagen deficiente puede afectar la exactitud del escaneo. Si tu app no se carga resultados aceptables, pide al usuario que vuelva a capturar la imagen.
-
Para aplicaciones típicas, se recomienda proporcionar una protección resolución de la imagen, como 1280 x 720 o 1920 x 1080, para que los códigos escaneables a una mayor distancia de la cámara.
Sin embargo, en las aplicaciones en las que la latencia es fundamental, de alto rendimiento mediante la captura de imágenes con una resolución más baja, pero que y el código de barras constituyen la mayor parte de la imagen de entrada. Consulta también Sugerencias para mejorar el rendimiento en tiempo real.
1. Configura el escáner de código de barras
Si sabes qué formatos de códigos de barras leerás, puedes mejorar la velocidad del escáner de código de barras configurándolo para que solo escanee esos formatos.Por ejemplo, para escanear solo códigos QR y Aztec, crea una
objeto BarcodeScannerOptions
, como en
siguiente ejemplo:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Se admiten los siguientes formatos:
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- UPCA
- UPCE
- PDF417
- azteca
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Se admiten los siguientes formatos:
- Código 128 (
MLKBarcodeFormatCode128
) - Código 39 (
MLKBarcodeFormatCode39
) - Código 93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Data Matrix (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - Código QR (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Aztec Code (
MLKBarcodeFormatAztec
)
2. Prepara la imagen de entrada
Para escanear códigos de barras en una imagen, pasa la imagen como un objetoUIImage
o
CMSampleBufferRef
al process()
o results(in:)
de BarcodeScanner
método:
Crea un objeto VisionImage
con un objeto UIImage
o
CMSampleBuffer
Si usas un UIImage
, sigue estos pasos:
- Crea un objeto
VisionImage
conUIImage
. Asegúrate de especificar el.orientation
correcto.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Si usas un CMSampleBuffer
, sigue estos pasos:
-
Especificar la orientación de los datos de imagen que se incluyen en la
CMSampleBuffer
Para obtener la orientación de la imagen, haz lo siguiente:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> UIImage.Orientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftMirrored : .right case .landscapeLeft: return cameraPosition == .front ? .downMirrored : .up case .portraitUpsideDown: return cameraPosition == .front ? .rightMirrored : .left case .landscapeRight: return cameraPosition == .front ? .upMirrored : .down case .faceDown, .faceUp, .unknown: return .up } }
Objective-C
- (UIImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- Crea un objeto
VisionImage
con el elemento ObjetoCMSampleBuffer
y orientación:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Cómo obtener una instancia de BarcodeScanner
Obtén una instancia deBarcodeScanner
:
Swift
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
Objective-C
MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner]; // Or, to change the default settings: // MLKBarcodeScanner *barcodeScanner = // [MLKBarcodeScanner barcodeScannerWithOptions:options];
4. Procesa la imagen
Por último, pasa la imagen al métodoprocess()
:
Swift
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
Objective-C
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
5. Obtén información de códigos de barras
Si la operación de escaneo de códigos de barras se realiza correctamente, el escáner devuelve un array de ObjetosBarcode
Cada objeto Barcode
representa un
código de barras que se detectó en la imagen. Para cada código de barras, puedes obtener su
coordenadas límite en la imagen de entrada, así como los datos sin procesar codificados
código de barras. Además, si el escáner de código de barras pudiera determinar el tipo de datos
codificado por el código de barras, puedes obtener un objeto que contenga datos analizados.
Por ejemplo:
Swift
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 } }
Objective-C
for (MLKBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; MLKBarcodeValueType valueType = barcode.valueType; switch (valueType) { case MLKBarcodeValueTypeWiFi: ssid = barcode.wifi.ssid; password = barcode.wifi.password; encryptionType = barcode.wifi.type; break; case MLKBarcodeValueTypeURL: url = barcode.URL.url; title = barcode.URL.title; break; // ... default: break; } }
Sugerencias para mejorar el rendimiento en tiempo real
Si quieres escanear códigos de barras en una aplicación en tiempo real, sigue estos pasos: pautas para lograr la mejor velocidad de fotogramas:
-
No captures imágenes de entrada con la resolución nativa de la cámara. En algunos dispositivos, capturar entradas con la resolución nativa produce errores extremadamente grandes (más de 10 megapíxeles) con imágenes, lo que genera una latencia muy deficiente sin beneficio para exactitud. En su lugar, solicita únicamente el tamaño necesario a la cámara para escanear códigos de barras, que en general no supera los 2 megapíxeles.
Los ajustes predeterminados de la sesión de captura con nombre:
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
etcétera) no se recomiendan, ya que pueden asignarse a resoluciones inadecuadas en algunos dispositivos. En su lugar, usa los ajustes predeterminados específicos comoAVCaptureSessionPreset1280x720
.Si la velocidad de escaneo es importante, puedes reducir aún más la captura de imágenes resolución. Sin embargo, ten en cuenta los requisitos de tamaño mínimo de los códigos de barras. descrita anteriormente.
Si intentas reconocer los códigos de barras de una secuencia de transmisión fotogramas de video, el reconocedor podría producir resultados diferentes marco. Debes esperar hasta obtener una serie consecutiva de la misma para tener la certeza de que obtendrás un buen resultado.
El dígito de suma de comprobación no es compatible con ITF ni CODE-39.
- Para procesar fotogramas de video, usa la API síncrona
results(in:)
del detector. Llamada este método desde el DeAVCaptureVideoDataOutputSampleBufferDelegate
La funcióncaptureOutput(_, didOutput:from:)
para obtener resultados de un video determinado de forma síncrona marco. Mantener deAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
comotrue
para limitar las llamadas al detector Si un nuevo cliente El fotograma estará disponible mientras se ejecute el detector, que se descartará. - Si usas la salida del detector para superponer gráficos la imagen de entrada, primero obtén el resultado del Kit de AA y, luego, renderiza la imagen y superponerla en un solo paso. De esta manera, renderizas en la superficie de visualización. solo una vez por cada trama de entrada procesada. Consulta updatePreviewOverlayViewWithLastFrame. en la muestra de inicio rápido del Kit de AA para ver un ejemplo.