Anda dapat menggunakan ML Kit untuk mengenali dan mendekode kode batang.
Cobalah
- Cobalah aplikasi contoh untuk melihat contoh penggunaan API ini.
Sebelum memulai
- Sertakan pod ML Kit berikut di Podfile Anda:
pod 'GoogleMLKit/BarcodeScanning', '15.5.0'
- Setelah Anda menginstal atau mengupdate Pod project, buka project Xcode menggunakan
.xcworkspace
. ML Kit didukung di Xcode versi 12.4 atau yang lebih baru.
Panduan gambar input
-
Agar ML Kit dapat membaca kode batang secara akurat, gambar input harus berisi kode batang yang diwakili oleh data piksel yang memadai.
Persyaratan data piksel yang spesifik tergantung pada jenis kode batang dan jumlah data yang dikodekan di dalamnya, karena banyak kode batang mendukung payload ukuran variabel. Secara umum, nilai terkecil yang unit kode batang harus setidaknya selebar 2 piksel, dan untuk kode 2 dimensi, tinggi 2 piksel.
Misalnya, kode batang EAN-13 terdiri dari batang dan spasi yang bernilai 1, Lebarnya 2, 3, atau 4 unit, sehingga gambar kode batang EAN-13 idealnya memiliki batang dan spasi minimal berukuran 2, 4, 6, dan 8 piksel. Karena EAN-13 kode batang memiliki lebar total 95 unit, kode batang minimal harus 190 selebar piksel.
Format yang lebih padat, seperti PDF417, membutuhkan dimensi piksel yang lebih besar untuk ML Kit untuk membacanya dengan andal. Misalnya, kode PDF417 dapat memiliki hingga 34 "kata-kata" lebar 17 unit dalam satu baris, yang idealnya akan berukuran minimal Lebar 1156 piksel.
-
Fokus gambar yang buruk dapat memengaruhi akurasi pemindaian. Jika aplikasi Anda tidak mendapatkan akan memberikan hasil yang dapat diterima, meminta pengguna untuk mengambil ulang gambar.
-
Untuk aplikasi biasa, sebaiknya berikan akses gambar beresolusi, seperti 1280x720 atau 1920x1080, yang akan membuat kode batang dapat dipindai dari jarak jauh dari kamera.
Namun, pada aplikasi yang sangat membutuhkan latensi, Anda dapat meningkatkan performa tinggi dengan mengambil gambar pada resolusi yang lebih rendah, tetapi memerlukan kode batang membentuk mayoritas gambar input. Lihat juga Tips untuk meningkatkan performa real-time.
1. Mengonfigurasi pemindai kode batang
Jika mengetahui format kode batang yang ingin dibaca, Anda dapat meningkatkan kecepatan pemindai kode batang dengan mengkonfigurasinya agar hanya memindai format tersebut.Misalnya, untuk memindai kode Aztec dan kode QR saja, buat
BarcodeScannerOptions
seperti dalam
contoh berikut:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Format berikut ini didukung:
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Format berikut ini didukung:
- Kode-128 (
MLKBarcodeFormatCode128
) - Kode-39 (
MLKBarcodeFormatCode39
) - Kode-93 (
MLKBarcodeFormatCode93
) - Codabar (
MLKBarcodeFormatCodaBar
) - Matriks Data (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - Kode QR (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Kode Aztec (
MLKBarcodeFormatAztec
)
2. Menyiapkan gambar input
Untuk memindai kode batang dalam gambar, teruskan gambar sebagaiUIImage
atau
CMSampleBufferRef
ke process()
atau results(in:)
BarcodeScanner
berikut:
Buat objek VisionImage
menggunakan UIImage
atau objek
CMSampleBuffer
.
Jika Anda menggunakan UIImage
, ikuti langkah-langkah berikut:
- Buat objek
VisionImage
denganUIImage
. Pastikan untuk menentukan.orientation
yang benar.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Jika Anda menggunakan CMSampleBuffer
, ikuti langkah-langkah berikut:
-
Tentukan orientasi data gambar yang terdapat dalam
CMSampleBuffer
.Untuk mendapatkan orientasi gambar:
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; } }
- Buat objek
VisionImage
menggunakan Objek dan orientasiCMSampleBuffer
: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. Mendapatkan instance BarcodeScanner
Dapatkan instanceBarcodeScanner
:
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. Memproses gambar
Lalu, teruskan gambar ke metodeprocess()
:
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. Mendapatkan informasi dari kode batang
Jika operasi pemindaian kode batang berhasil, pemindai akan mengembalikan array ObjekBarcode
. Setiap objek Barcode
mewakili
kode batang yang terdeteksi dalam gambar. Untuk setiap kode batang, Anda bisa mendapatkan
koordinat pembatas pada gambar input, serta data mentah yang dienkode oleh
kode batang. Juga, jika pemindai kode batang
mampu menentukan jenis data
yang dienkode oleh kode batang, Anda bisa mendapatkan objek yang berisi data yang diuraikan.
Contoh:
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; } }
Tips untuk meningkatkan performa real-time
Jika Anda ingin memindai kode batang dalam aplikasi real-time, ikuti panduan untuk mencapai kecepatan frame terbaik:
-
Jangan mengambil input pada resolusi native kamera. Pada beberapa perangkat, menangkap input dengan resolusi native menghasilkan output yang sangat besar (10+ megapiksel), yang menghasilkan latensi yang sangat buruk tanpa manfaat untuk tingkat akurasi. Sebagai gantinya, hanya minta ukuran dari kamera yang diperlukan untuk pemindaian kode batang, yang biasanya berukuran tidak lebih dari 2 megapiksel.
Preset sesi pengambilan bernama—
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
, dan seterusnya)—tidak disarankan, karena dapat dipetakan ke resolusi yang tidak sesuai pada beberapa perangkat. Sebagai gantinya, gunakan preset spesifik misalnyaAVCaptureSessionPreset1280x720
.Jika kecepatan pemindaian penting, Anda dapat menurunkan pengambilan gambar resolusi. Namun, perhatikan persyaratan ukuran kode batang minimum yang diuraikan di atas.
Jika Anda mencoba mengenali kode batang dari urutan streaming {i>frame<i} video, pengenal mungkin menghasilkan hasil yang berbeda dari {i>frame<i} ke {i>frame<i} {i>frame<i}. Anda harus menunggu sampai Anda mendapatkan rangkaian nilai untuk yakin bahwa Anda memberikan hasil yang baik.
Digit Checksum tidak didukung untuk ITF dan CODE-39.
- Untuk memproses frame video, gunakan API sinkron
results(in:)
dari detektor. Telepon metode ini dari classAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
untuk mendapatkan hasil dari video yang diberikan secara sinkron {i>frame<i}. SimpanAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
sebagaitrue
untuk men-throttle panggilan ke detektor. Jika frame video tersedia saat detektor sedang berjalan, dan frame tersebut akan dihapus. - Jika Anda menggunakan output detektor untuk menempatkan grafik gambar input, pertama-tama dapatkan hasilnya dari ML Kit, lalu render gambar dan overlay dalam satu langkah. Dengan demikian, Anda merender ke permukaan tampilan hanya sekali untuk setiap {i> frame<i} input yang diproses. Lihat updatePreviewOverlayViewWithLastFrame dalam contoh panduan memulai ML Kit sebagai contoh.