คุณใช้ ML Kit เพื่อจดจำและถอดรหัสบาร์โค้ดได้
ลองเลย
- ลองใช้แอปตัวอย่างเพื่อ ดูตัวอย่างการใช้ API นี้
ก่อนเริ่มต้น
- ใส่พ็อด ML Kit ต่อไปนี้ใน Podfile
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- หลังจากที่คุณติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspace
ทั้งนี้ ML Kit รองรับ Xcode เวอร์ชัน 12.4 ขึ้นไป
หลักเกณฑ์เกี่ยวกับรูปภาพที่ป้อน
-
เพื่อให้ ML Kit อ่านบาร์โค้ดได้อย่างถูกต้อง รูปภาพที่ป้อนต้องมี บาร์โค้ดที่แสดงด้วยข้อมูลพิกเซลที่เพียงพอ
สำหรับข้อกำหนดด้านข้อมูลพิกเซลที่เจาะจงจะขึ้นอยู่กับทั้ง กับปริมาณของข้อมูลที่เข้ารหัสไว้ เนื่องจากบาร์โค้ดจำนวนมาก รองรับเพย์โหลดขนาดที่เปลี่ยนแปลงได้ โดยทั่วไป ตัวแปรที่น้อยที่สุด หน่วยบาร์โค้ดควรกว้างอย่างน้อย 2 พิกเซลและ โค้ด 2 มิติ ความสูง 2 พิกเซล
ตัวอย่างเช่น บาร์โค้ด EAN-13 ประกอบด้วยแท่งและการเว้นวรรคที่ 1 ความกว้าง 2, 3 หรือ 4 หน่วย ดังนั้นรูปภาพบาร์โค้ด EAN-13 จะมีแถบและ ช่องว่างที่มีความกว้างอย่างน้อย 2, 4, 6 และ 8 พิกเซล เนื่องจาก EAN-13 บาร์โค้ดมีความกว้างรวม 95 หน่วย บาร์โค้ดควรมีอย่างน้อย 190 พิกเซล
รูปแบบที่หนาแน่นกว่า เช่น PDF417 ต้องมีขนาดพิกเซลมากขึ้น ML Kit ให้อ่านได้อย่างน่าเชื่อถือ ตัวอย่างเช่น รหัส PDF417 สามารถมีได้สูงสุด "คำ" กว้าง 17 หน่วย 34 คำ ในแถวเดียว ซึ่งอย่างน้อยก็ กว้าง 1156 พิกเซล
-
การโฟกัสของรูปภาพไม่ดีอาจส่งผลต่อความแม่นยำในการสแกน หากแอปไม่ได้รับ ผลลัพธ์ที่ยอมรับได้ ขอให้ผู้ใช้เรียกคืนรูปภาพอีกครั้ง
-
สำหรับแอปพลิเคชันทั่วไป ขอแนะนำให้เพิ่ม รูปภาพที่มีความละเอียด เช่น 1280x720 หรือ 1920x1080 ซึ่งทำให้บาร์โค้ด สแกนได้ในระยะที่ห่างจากกล้องมากขึ้น
อย่างไรก็ตาม ในแอปพลิเคชันที่เวลาในการตอบสนองเป็นสิ่งที่สำคัญ คุณสามารถ ด้วยการจับภาพด้วยความละเอียดที่ต่ำลง บาร์โค้ดนั้นทำให้พื้นที่ส่วนใหญ่ของภาพป้อนข้อมูล ดูนี่ด้วย เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
1. กำหนดค่าเครื่องสแกนบาร์โค้ด
หากคุณทราบว่าจะอ่านบาร์โค้ดรูปแบบใด คุณสามารถเร่งความเร็ว ของเครื่องสแกนบาร์โค้ดโดยกำหนดค่าให้สแกนเฉพาะรูปแบบเหล่านั้นได้ตัวอย่างเช่น หากต้องการสแกนเฉพาะโค้ดแอซเท็กและคิวอาร์โค้ด ให้สร้าง
BarcodeScannerOptions
เช่นเดียวกับใน
ตัวอย่างต่อไปนี้
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
รูปแบบที่รองรับมีดังนี้
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
รูปแบบที่รองรับมีดังนี้
- รหัส-128 (
MLKBarcodeFormatCode128
) - รหัส-39 (
MLKBarcodeFormatCode39
) - รหัส-93 (
MLKBarcodeFormatCode93
) - คอดาบาร์ (
MLKBarcodeFormatCodaBar
) - เมทริกซ์ข้อมูล (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - คิวอาร์โค้ด (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - รหัสแอซเท็ก (
MLKBarcodeFormatAztec
)
2. เตรียมรูปภาพอินพุต
หากต้องการสแกนบาร์โค้ดในรูปภาพ ให้ส่งรูปภาพเป็นUIImage
หรือ
CMSampleBufferRef
ไปยัง process()
หรือ results(in:)
ของ BarcodeScanner
วิธีการ:
สร้างออบเจ็กต์ VisionImage
โดยใช้ UIImage
หรือ
CMSampleBuffer
หากคุณใช้ UIImage
ให้ทำตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์
VisionImage
ด้วยUIImage
ตรวจสอบว่าได้ระบุ.orientation
ที่ถูกต้องSwift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
หากคุณใช้ CMSampleBuffer
ให้ทำตามขั้นตอนต่อไปนี้
-
ระบุการวางแนวของข้อมูลภาพที่มีอยู่ใน
CMSampleBuffer
วิธีดูการวางแนวรูปภาพ
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; } }
- สร้างออบเจ็กต์
VisionImage
โดยใช้CMSampleBuffer
วัตถุและการวางแนว: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
รับอินสแตนซ์ของBarcodeScanner
:
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. ประมวลผลรูปภาพ
จากนั้นส่งรูปภาพไปยังเมธอดprocess()
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. รับข้อมูลจากบาร์โค้ด
หากการสแกนบาร์โค้ดสำเร็จ เครื่องสแกนจะแสดงผลอาร์เรย์ของBarcode
ออบเจ็กต์ ออบเจ็กต์ Barcode
แต่ละรายการแสดงถึง
บาร์โค้ดที่ตรวจพบในรูปภาพ สำหรับบาร์โค้ดแต่ละรายการ คุณสามารถดู
พิกัดขอบเขตในภาพอินพุต รวมถึงข้อมูลดิบที่เข้ารหัสโดย
บาร์โค้ด นอกจากนี้ หากเครื่องสแกนบาร์โค้ดระบุประเภทข้อมูลได้
ที่เข้ารหัสโดยบาร์โค้ด คุณจะสามารถรับออบเจ็กต์ที่มีข้อมูลที่แยกวิเคราะห์แล้ว
เช่น
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; } }
เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
หากต้องการสแกนบาร์โค้ดในแอปพลิเคชันแบบเรียลไทม์ โปรดทำตามขั้นตอนต่อไปนี้ เพื่อให้ได้อัตราเฟรมที่ดีที่สุด
-
อย่าจับภาพอินพุตที่ความละเอียดดั้งเดิมของกล้อง ในอุปกรณ์บางรุ่น การบันทึกอินพุตที่ความละเอียดดั้งเดิมทำให้เกิดขนาดใหญ่มาก (10+ (เมกะพิกเซล) ซึ่งส่งผลให้เวลาในการตอบสนองต่ำมาก โดยที่ไม่เกิดประโยชน์ใดๆ ความแม่นยำ ให้ขอเฉพาะขนาดจากกล้องที่จำเป็นแทน สำหรับการสแกนบาร์โค้ด ซึ่งโดยปกติจะไม่เกิน 2 เมกะพิกเซล
ค่าที่กำหนดล่วงหน้าของเซสชันการบันทึกที่มีชื่อ -
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
AVCaptureSessionPresetMedium
และอื่นๆ) แต่ไม่แนะนำเนื่องจากสามารถจับคู่กับ ความละเอียดที่ไม่เหมาะสมในบางอุปกรณ์ ให้ใช้ค่าที่กำหนดล่วงหน้าแทน เช่นAVCaptureSessionPreset1280x720
หากความเร็วในการสแกนเป็นสิ่งสำคัญ คุณจะลดการจับภาพลงได้ ความละเอียดสูงสุดของคุณ แต่โปรดคำนึงถึงข้อกำหนดเกี่ยวกับขนาดบาร์โค้ดขั้นต่ำ ตามที่ระบุไว้ข้างต้น
หากคุณพยายามจำแนกบาร์โค้ดจากลำดับการสตรีม เครื่องมือจดจำอาจสร้างผลการค้นหาที่แตกต่างกันจากเฟรม เฟรม รอจนกว่าจะได้รับซีรีส์เดียวกัน เพื่อให้มั่นใจได้ว่าคุณได้ผลลัพธ์ที่ดี
ITF และ CODE-39 ไม่รองรับหมายเลข Checksum
- สำหรับการประมวลผลเฟรมวิดีโอ ให้ใช้ API แบบซิงโครนัสของ
results(in:)
ในตัวตรวจจับ โทร เมธอดนี้จาก ของAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
เพื่อให้ได้ผลลัพธ์จากวิดีโอที่ระบุแบบพร้อมกัน เฟรม เก็บ ของAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
เป็นtrue
เพื่อควบคุมการโทรหาตัวตรวจจับ หาก เฟรมวิดีโอจะพร้อมใช้งานขณะที่ตัวตรวจจับทำงานอยู่ เฟรมนั้นจะหายไป - หากคุณใช้เอาต์พุตของเครื่องมือตรวจจับเพื่อวางซ้อนกราฟิก รูปภาพอินพุต รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพ ซ้อนทับในขั้นตอนเดียว การดำเนินการดังกล่าวจะแสดงบนพื้นผิวจอแสดงผล เพียงครั้งเดียวสำหรับแต่ละเฟรมอินพุตที่ประมวลผลแล้ว ดู updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มต้นอย่างรวดเร็วใน ML Kit