Barkodları tanımak ve kodlarını çözmek için ML Kit'i kullanabilirsiniz.
Deneyin
- Bu API'nin örnek bir kullanımını görmek için örnek uygulamayı inceleyin.
Başlamadan önce
- Aşağıdaki ML Kiti kapsüllerini Podfile'ınıza ekleyin:
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- Projenizin Kapsüllerini yükledikten veya güncelledikten sonra Xcode projenizi,
.xcworkspace
ile açın. ML Kit, Xcode 12.4 veya üzeri sürümlerde desteklenir.
Resim kuralları girin
-
ML Kit'in barkodları doğru şekilde okuyabilmesi için giriş görüntülerinin yeterli sayıda piksel verisiyle temsil edilen barkodlar içermesi gerekir.
Birçok barkod değişken boyutlu yükü destekler. Bu nedenle, belirli piksel verisi gereksinimleri hem barkodun türüne hem de içinde kodlanan veri miktarına bağlıdır. Genel olarak, barkodun en küçük anlamlı birimi en az 2 piksel genişliğinde, 2 boyutlu kodlar için 2 piksel yüksekliğinde olmalıdır.
Örneğin, EAN-13 barkodları 1, 2, 3 veya 4 birim genişliğindeki çubuklardan ve boşluklardan oluşur. Bu nedenle, EAN-13 barkod resminde en az 2, 4, 6 ve 8 piksel genişliğinde çubuklar ve boşluklar bulunur. EAN-13 barkodu toplamda 95 birim genişliğinde olduğundan, barkod en az 190 piksel genişliğinde olmalıdır.
PDF417 gibi daha yoğun biçimler, ML Kit'in güvenilir bir şekilde okuyabilmesi için daha fazla piksel boyutuna ihtiyaç duyar. Örneğin, bir PDF417 kodu, tek bir satırda en az 1156 piksel genişliğinde olacak şekilde en fazla 34 adet 17 birim genişliğinde "kelime" içerebilir.
-
Kötü odaklama, tarama doğruluğunu etkileyebilir. Uygulamanız kabul edilebilir sonuçlar almıyorsa kullanıcıdan resmi tekrar yakalamasını isteyin.
-
Tipik uygulamalarda, 1280x720 veya 1920x1080 gibi daha yüksek çözünürlüklü bir görüntü kullanılması önerilir. Bu sayede, kameradan daha uzak mesafeden barkodlar taranabilir.
Bununla birlikte, gecikmenin kritik olduğu uygulamalarda, daha düşük çözünürlükte resimler çekerek performansı artırabilirsiniz. Ancak, giriş görüntüsünün büyük kısmını barkodun içermesi gerekir. Gerçek zamanlı performansı iyileştirmek için ipuçları bölümünü de inceleyin.
1. Barkod tarayıcıyı yapılandırma
Hangi barkod biçimlerini okumayı beklediğinizi biliyorsanız sadece bu biçimleri tarayacak şekilde yapılandırarak barkod tarayıcının hızını artırabilirsiniz.Örneğin, yalnızca Aztek kodunu ve QR kodlarını taramak için aşağıdaki örnekte gösterildiği gibi bir BarcodeScannerOptions
nesnesi oluşturun:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Aşağıdaki biçimler desteklenir:
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- İTŞ
- qrCode
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Aşağıdaki biçimler desteklenir:
- Kod-128 (
MLKBarcodeFormatCode128
) - Kod-39 (
MLKBarcodeFormatCode39
) - Kod-93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Veri Matrisi (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - QR Kodu (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Aztek Kodu (
MLKBarcodeFormatAztec
)
2. Giriş görüntüsünü hazırlama
Bir görüntüdeki barkodları taramak için resmiBarcodeScanner
process()
veya results(in:)
yöntemine UIImage
veya CMSampleBufferRef
olarak iletin:
UIImage
veya CMSampleBuffer
kullanarak VisionImage
nesnesi oluşturun.
UIImage
kullanıyorsanız aşağıdaki adımları uygulayın:
UIImage
ile birVisionImage
nesnesi oluşturun. Doğru.orientation
değerini belirttiğinizden emin olun.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
CMSampleBuffer
kullanıyorsanız aşağıdaki adımları uygulayın:
-
CMSampleBuffer
içinde yer alan resim verilerinin yönünü belirtin.Resmin yönünü öğrenmek için:
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; } }
CMSampleBuffer
nesnesini ve yönünü kullanarak birVisionImage
nesnesi oluşturun: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. BarcodeScanner örneği alın
BarcodeScanner
örneği alın:
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. Resmi işle
Ardından resmiprocess()
yöntemine iletin:
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. Barkodlardan bilgi alma
Barkod tarama işlemi başarılı olursa tarayıcı, bir diziBarcode
nesnesi döndürür. Her Barcode
nesnesi, resimde algılanan bir barkodu temsil eder. Her barkod için giriş görüntüsündeki sınırlayıcı koordinatlarının yanı sıra barkodla kodlanan ham verileri de alabilirsiniz. Ayrıca, barkod tarayıcı barkod tarafından kodlanan veri türünü belirleyebiliyorsa ayrıştırılmış veriler içeren bir nesne elde edebilirsiniz.
Örneğin:
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; } }
Gerçek zamanlı performansı iyileştirmeye yönelik ipuçları
Barkodları gerçek zamanlı bir uygulamada taramak istiyorsanız en iyi kare hızlarını elde etmek için aşağıdaki yönergeleri uygulayın:
-
Girişleri kameranın yerel çözünürlüğünde yakalamayın. Bazı cihazlarda girişlerin yerel çözünürlükte yakalanması çok büyük (10 megapiksel) görüntüler üretir. Bu da çok düşük gecikmeye neden olur ve doğruluk açısından avantaj sağlamaz. Bunun yerine, kameradan yalnızca barkod tarama için gerekli olan boyutu isteyin. Bu boyut genellikle 2 megapikselden yüksek değildir.
Ancak, adlandırılmış yakalama oturumu hazır ayarları (
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
vb.) bazı cihazlarda uygun olmayan çözünürlüklere eşlenebileceğinden önerilmez. Bunun yerine,AVCaptureSessionPreset1280x720
gibi belirli hazır ayarları kullanın.Tarama hızı önemliyse görüntü çekim çözünürlüğünü daha da düşürebilirsiniz. Bununla birlikte, yukarıda belirtilen minimum barkod boyutu gereksinimlerini göz önünde bulundurun.
Bir dizi akışlı video karesinden barkodları tanımaya çalışıyorsanız tanıyıcı, kareden kareye farklı sonuçlar verebilir. İyi bir sonuç döndürdüğünüzden emin olmak için aynı değere sahip ardışık bir seri elde edene kadar beklemeniz gerekir.
Sağlama hanesi, ITF ve CODE-39 için desteklenmez.
- Video karelerini işlemek için algılayıcının
results(in:)
eşzamanlı API'sini kullanın. Belirtilen video karesinden sonuçları eşzamanlı olarak almak için bu yöntemiAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
işlevinden çağırın. Çağrıları algılayıcıya kısıtlamak içinAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
özelliğinitrue
olarak bırakın. Algılayıcı çalışırken yeni bir video karesi kullanılabilir hale gelirse atlanır. - Algılayıcının çıkışını giriş görüntüsünün üzerine grafik yerleştirmek için kullanırsanız önce sonucu ML Kit'ten alın, ardından görüntüyü tek bir adımda oluşturun ve yer paylaşımlı yapın. Bu şekilde, işlenen her giriş çerçevesi için görüntü yüzeyinde yalnızca bir kez görüntü oluşturursunuz. Örneği görmek için ML Kit hızlı başlangıç örneğindeki updatePreviewOverlayViewWithLastFrame) örneğine bakın.