Vous pouvez utiliser ML Kit pour reconnaître et décoder les codes-barres.
Essayer
- Testez l'application exemple pour voir un exemple d'utilisation de cette API.
Avant de commencer
- Incluez les pods ML Kit suivants dans votre Podfile :
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- Après avoir installé ou mis à jour les pods de votre projet, ouvrez votre projet Xcode à l'aide de son fichier
.xcworkspace
. ML Kit est compatible avec Xcode 12.4 ou version ultérieure.
Consignes pour les images d'entrée
-
Pour que ML Kit puisse lire avec précision les codes-barres, les images d'entrée doivent contenir des codes-barres représentés par une quantité de données de pixels suffisante.
Les exigences spécifiques en termes de données de pixels dépendent à la fois du type de code-barres et de la quantité de données encodées dans celui-ci, car de nombreux codes-barres acceptent une charge utile de taille variable. En général, la plus petite unité significative du code-barres doit être d'au moins 2 pixels de large et, pour les codes bidimensionnels, de 2 pixels de haut.
Par exemple, les codes-barres EAN-13 sont constitués de barres et d'espaces d'une largeur de 1, 2, 3 ou 4 unités. Une image de code-barres EAN-13 doit donc idéalement comporter des barres et des espaces d'au moins 2, 4, 6 et 8 pixels de large. Étant donné qu'un code-barres EAN-13 fait au total 95 unités de large, sa largeur doit être d'au moins 190 pixels.
Les formats Denser, tels que PDF417, nécessitent des dimensions en pixels plus importantes pour que ML Kit puisse les lire de manière fiable. Par exemple, un code PDF417 peut comporter jusqu'à 34 "mots" de 17 unités sur une seule ligne, d'une largeur minimale de 1 156 pixels.
-
Une mise au point médiocre peut affecter la précision de la numérisation. Si votre application n'obtient pas de résultats acceptables, demandez à l'utilisateur de reprendre l'image.
-
Pour les applications classiques, il est recommandé de fournir une image de meilleure résolution (1 280 x 720 ou 1 920 x 1 080, par exemple), ce qui permet de scanner les codes-barres à une plus grande distance de la caméra.
Toutefois, dans les applications où la latence est essentielle, vous pouvez améliorer les performances en capturant des images à une résolution inférieure, mais en exigeant que le code-barres représente la majorité de l'image d'entrée. Consultez également la page Conseils pour améliorer les performances en temps réel.
1. Configurer le lecteur de code-barres
Si vous savez quels formats de codes-barres vous souhaitez lire, vous pouvez améliorer la vitesse du lecteur de codes-barres en le configurant pour qu'il n'analyse que ces formats.Par exemple, pour ne scanner que le code aztec et les codes QR, créez un objet BarcodeScannerOptions
comme dans l'exemple suivant:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Les formats suivants sont acceptés :
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- Italie
- qrCode
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Les formats suivants sont acceptés :
- Code 128 (
MLKBarcodeFormatCode128
) - Code 39 (
MLKBarcodeFormatCode39
) - Code 93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Matrice de données (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - Code QR (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Code Aztec (
MLKBarcodeFormatAztec
)
2. Préparer l'image d'entrée
Pour scanner les codes-barres d'une image, transmettez l'image en tant queUIImage
ou CMSampleBufferRef
à la méthode process()
ou results(in:)
de BarcodeScanner
:
Créez un objet VisionImage
à l'aide d'un UIImage
ou d'un CMSampleBuffer
.
Si vous utilisez un UIImage
, procédez comme suit:
- Créez un objet
VisionImage
avecUIImage
. Veillez à spécifier le bon.orientation
.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Si vous utilisez un CMSampleBuffer
, procédez comme suit:
-
Spécifiez l'orientation des données d'image contenues dans le fichier
CMSampleBuffer
.Pour obtenir l'orientation de l'image:
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; } }
- Créez un objet
VisionImage
à l'aide de l'objetCMSampleBuffer
et de l'orientation: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. Obtenir une instance de BarcodeScanner
Obtenez une instance 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. Traiter l'image
Transmettez ensuite l'image à la méthodeprocess()
:
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. Obtenir des informations à partir d'un code-barres
Si la lecture de code-barres aboutit, le lecteur renvoie un tableau d'objetsBarcode
. Chaque objet Barcode
représente un code-barres détecté dans l'image. Vous pouvez obtenir les coordonnées de délimitation de chaque code-barres dans l'image d'entrée, ainsi que les données brutes encodées par le code-barres. De plus, si le lecteur de code-barres a pu déterminer le type de données encodées par le code-barres, vous pouvez obtenir un objet contenant des données analysées.
Exemple :
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; } }
Conseils pour améliorer les performances en temps réel
Si vous souhaitez scanner des codes-barres dans une application en temps réel, suivez ces consignes pour obtenir les meilleures fréquences d'images:
-
N'enregistrez pas l'entrée avec la résolution native de la caméra. Sur certains appareils, la capture d'entrée à la résolution native produit des images extrêmement grandes (plus de 10 mégapixels), ce qui se traduit par une latence très faible sans aucun avantage en termes de précision. Demandez uniquement la taille à l'appareil photo requis pour la lecture des codes-barres, qui ne dépasse généralement pas 2 mégapixels.
Toutefois, les préréglages de session de capture nommés (
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
, etc.) ne sont pas recommandés, car ils peuvent être mappés à des résolutions inappropriées sur certains appareils. Utilisez plutôt des préréglages spécifiques tels queAVCaptureSessionPreset1280x720
.Si la vitesse de numérisation est importante, vous pouvez réduire davantage la résolution de capture de l'image. Toutefois, tenez compte des exigences minimales de taille des codes-barres décrites ci-dessus.
Si vous essayez de reconnaître les codes-barres d'une séquence d'images vidéo en flux continu, le programme de reconnaissance peut produire des résultats différents d'une image à l'autre. Vous devez attendre d'obtenir une série consécutive de la même valeur pour être sûr de renvoyer un bon résultat.
Le chiffre de la somme de contrôle n'est pas pris en charge pour ITF et CODE-39.
- Pour traiter les images vidéo, utilisez l'API synchrone
results(in:)
du détecteur. Appelez cette méthode à partir de la fonctioncaptureOutput(_, didOutput:from:)
deAVCaptureVideoDataOutputSampleBufferDelegate
pour obtenir de manière synchrone les résultats de l'image vidéo donnée. Conservez la valeuralwaysDiscardsLateVideoFrames
deAVCaptureVideoDataOutput
définie surtrue
pour limiter les appels au détecteur. Si une nouvelle image vidéo devient disponible alors que le détecteur est en cours d'exécution, elle sera ignorée. - Si vous utilisez la sortie du détecteur pour superposer des graphiques sur l'image d'entrée, obtenez d'abord le résultat de ML Kit, puis affichez l'image et la superposition en une seule étape. Ainsi, vous n'effectuez le rendu sur la surface d'affichage qu'une seule fois pour chaque trame d'entrée traitée. Consultez la section updatePreviewOverlayViewWithLastFrame dans l'exemple de démarrage rapide de ML Kit pour en voir un exemple.