คุณใช้ ML Kit เพื่อจดจำและถอดรหัสบาร์โค้ดได้
ลองเลย
- ลองใช้แอปตัวอย่างเพื่อดูตัวอย่างการใช้งาน API นี้
ก่อนเริ่มต้น
- รวมพ็อด ML Kit ต่อไปนี้ใน Podfile:
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspace
ของโปรเจ็กต์นั้น Xcode เวอร์ชัน 12.4 ขึ้นไปรองรับ ML Kit
หลักเกณฑ์เกี่ยวกับรูปภาพอินพุต
-
เพื่อให้ 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. กำหนดค่าเครื่องสแกนบาร์โค้ด
หากคุณทราบว่าคุณคาดว่าจะอ่านรูปแบบบาร์โค้ดใด คุณสามารถปรับปรุงความเร็วของเครื่องสแกนบาร์โค้ดโดยการกำหนดค่าให้สแกนเฉพาะรูปแบบดังกล่าวตัวอย่างเช่น หากต้องการสแกนเฉพาะโค้ด Aztec และคิวอาร์โค้ด ให้สร้างออบเจ็กต์ BarcodeScannerOptions
ตามตัวอย่างต่อไปนี้
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
รูปแบบที่รองรับมีดังต่อไปนี้
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ไอที
- qrCode
- รหัส UPCA
- UPCE
- PDF417
- Aztec
Objective-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
รูปแบบที่รองรับมีดังต่อไปนี้
- โค้ด-128 (
MLKBarcodeFormatCode128
) - Code-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
หากความเร็วในการสแกนเป็นสิ่งสำคัญ คุณอาจลดความละเอียดในการจับภาพได้อีก แต่โปรดคำนึงถึงข้อกำหนดด้านขนาดบาร์โค้ดขั้นต่ำที่ระบุไว้ข้างต้น
หากคุณกำลังพยายามจดจำบาร์โค้ดจากลำดับของเฟรมสตรีมวิดีโอ เครื่องมือจดจำอาจแสดงผลลัพธ์ที่แตกต่างกันในแต่ละเฟรม คุณควรรอจนกว่าจะได้รับชุดค่าเดียวกันติดต่อกัน เพื่อให้มั่นใจว่ากำลังแสดงผลลัพธ์ที่ดี
ไม่รองรับหมายเลข Checksum สำหรับ ITF และ CODE-39
- สำหรับการประมวลผลเฟรมวิดีโอ ให้ใช้ API แบบซิงโครนัส
results(in:)
ของตัวตรวจจับ เรียกใช้เมธอดนี้จากฟังก์ชันcaptureOutput(_, didOutput:from:)
ของAVCaptureVideoDataOutputSampleBufferDelegate
เพื่อรับผลการค้นหาจากเฟรมวิดีโอที่ระบุแบบพร้อมกัน คงalwaysDiscardsLateVideoFrames
ของAVCaptureVideoDataOutput
เป็นtrue
เพื่อควบคุมการโทรไปยังตัวตรวจจับ หากเฟรมวิดีโอใหม่พร้อมใช้งานขณะที่ตัวตรวจจับทำงานอยู่ เฟรมจะหายไป - หากคุณใช้เอาต์พุตจากตัวตรวจจับเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ให้รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพและการวางซ้อนในขั้นตอนเดียว การทำเช่นนี้จะทำให้คุณแสดงผลบนพื้นผิวแสดงผลเพียงครั้งเดียวต่อเฟรมอินพุตที่ประมวลผลแต่ละเฟรม ดู updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มใช้งานอย่างรวดเร็วของ ML Kit