คุณสามารถใช้ ML Kit เพื่อจดจำและถอดรหัสบาร์โค้ดได้
ก่อนที่คุณจะเริ่ม
- หากคุณยังไม่ได้เพิ่ม Firebase ลงในแอปของคุณ ให้ทำตามขั้นตอนใน คู่มือการเริ่มต้นใช้งาน
- รวมไลบรารี ML Kit ไว้ใน Podfile ของคุณ:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
หลังจากที่คุณติดตั้งหรืออัปเดต Pod ของโปรเจ็กต์แล้ว อย่าลืมเปิดโปรเจ็กต์ Xcode โดยใช้.xcworkspace
- ในแอปของคุณ ให้นำเข้า Firebase:
สวิฟท์
import Firebase
วัตถุประสงค์-C
@import Firebase;
แนวทางการป้อนรูปภาพ
เพื่อให้ 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 และรหัส QR ให้สร้างวัตถุ VisionBarcodeDetectorOptions
ดังตัวอย่างต่อไปนี้:
สวิฟท์
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
รองรับรูปแบบต่อไปนี้:
- รหัส128
- รหัส39
- รหัส93
- โคดาบาร์
- EAN13
- EAN8
- ไอทีเอฟ
- UPCA
- อัพซีอี
- คิวอาร์โค้ด
- PDF417
- แอซเท็ก
- ดาต้าเมทริกซ์
วัตถุประสงค์-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
รองรับรูปแบบต่อไปนี้:
- รหัส 128 (
FIRVisionBarcodeFormatCode128
) - รหัส 39 (
FIRVisionBarcodeFormatCode39
) - รหัส 93 (
FIRVisionBarcodeFormatCode93
) - โคดาบาร์ (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ไอทีเอฟ (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - รหัส QR (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - แอซเท็ก (
FIRVisionBarcodeFormatAztec
) - เมทริกซ์ข้อมูล (
FIRVisionBarcodeFormatDataMatrix
)
2. เรียกใช้ตัวตรวจจับบาร์โค้ด
หากต้องการสแกนบาร์โค้ดในรูปภาพ ให้ส่งรูปภาพเป็นUIImage
หรือ CMSampleBufferRef
ไปยังวิธีการตรวจจับของ VisionBarcodeDetector
detect(in:)
:- รับอินสแตนซ์ของ
VisionBarcodeDetector
:สวิฟท์
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
วัตถุประสงค์-C
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
สร้างวัตถุ
VisionImage
โดยใช้UIImage
หรือCMSampleBufferRef
วิธีใช้
UIImage
:- หากจำเป็น ให้หมุนรูปภาพเพื่อให้คุณสมบัติ
imageOrientation
เป็น.up
- สร้างวัตถุ
VisionImage
โดยใช้UIImage
ที่หมุนอย่างถูกต้อง อย่าระบุข้อมูลเมตาการหมุนเวียนใดๆ ต้องใช้ค่าเริ่มต้น ..topLeft
สวิฟท์
let image = VisionImage(image: uiImage)
วัตถุประสงค์-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
วิธีใช้
CMSampleBufferRef
:สร้างออบเจ็กต์
VisionImageMetadata
ที่ระบุการวางแนวของข้อมูลรูปภาพที่มีอยู่ในบัฟเฟอร์CMSampleBufferRef
เพื่อให้ได้การวางแนวของภาพ:
สวิฟท์
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
วัตถุประสงค์-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
จากนั้นสร้างวัตถุข้อมูลเมตา:
สวิฟท์
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
วัตถุประสงค์-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- สร้างวัตถุ
VisionImage
โดยใช้วัตถุCMSampleBufferRef
และข้อมูลเมตาการหมุน:สวิฟท์
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
วัตถุประสงค์-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- หากจำเป็น ให้หมุนรูปภาพเพื่อให้คุณสมบัติ
- จากนั้นส่งภาพไปยังวิธี
detect(in:)
:สวิฟท์
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
วัตถุประสงค์-C
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. รับข้อมูลจากบาร์โค้ด
หากการดำเนินการจดจำบาร์โค้ดสำเร็จ อุปกรณ์ตรวจจับจะส่งคืนอาร์เรย์ของออบเจ็กต์VisionBarcode
แต่ละวัตถุ VisionBarcode
แสดงถึงบาร์โค้ดที่ตรวจพบในภาพ สำหรับบาร์โค้ดแต่ละอัน คุณสามารถรับพิกัดขอบเขตในรูปภาพอินพุต รวมถึงข้อมูลดิบที่เข้ารหัสด้วยบาร์โค้ด นอกจากนี้ หากตัวตรวจจับบาร์โค้ดสามารถระบุประเภทของข้อมูลที่เข้ารหัสด้วยบาร์โค้ดได้ คุณก็สามารถรับออบเจ็กต์ที่มีข้อมูลที่แยกวิเคราะห์ได้ตัวอย่างเช่น:
สวิฟท์
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 } }
วัตถุประสงค์-C
for (FIRVisionBarcode *barcode in barcodes) { NSArray *corners = barcode.cornerPoints; NSString *displayValue = barcode.displayValue; NSString *rawValue = barcode.rawValue; FIRVisionBarcodeValueType valueType = barcode.valueType; switch (valueType) { case FIRVisionBarcodeValueTypeWiFi: // ssid = barcode.wifi.ssid; // password = barcode.wifi.password; // encryptionType = barcode.wifi.type; break; case FIRVisionBarcodeValueTypeURL: // url = barcode.URL.url; // title = barcode.URL.title; break; // ... default: break; } }
เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
หากคุณต้องการสแกนบาร์โค้ดในแอปพลิเคชันแบบเรียลไทม์ ให้ปฏิบัติตามคำแนะนำเหล่านี้เพื่อให้ได้เฟรมเรตที่ดีที่สุด:
อย่าจับภาพอินพุตที่ความละเอียดดั้งเดิมของกล้อง ในอุปกรณ์บางชนิด การจับอินพุตที่ความละเอียดมาตรฐานจะทำให้ได้ภาพที่มีขนาดใหญ่มาก (10+ ล้านพิกเซล) ซึ่งส่งผลให้มีเวลาแฝงต่ำมากและไม่มีประโยชน์ต่อความแม่นยำ แต่ให้ขอเฉพาะขนาดจากกล้องที่จำเป็นสำหรับการตรวจจับบาร์โค้ดเท่านั้น ซึ่งโดยปกติแล้วจะไม่เกิน 2 เมกะพิกเซล
อย่างไรก็ตาม ไม่แนะนำให้ใช้การตั้งค่าล่วงหน้าของเซสชันการจับภาพที่มีชื่อ เช่น
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
เนื่องจากสามารถแมปกับความละเอียดที่ไม่เหมาะสมบนอุปกรณ์บางตัวได้ ให้ใช้ค่าที่ตั้งล่วงหน้าเฉพาะ เช่นAVCaptureSessionPreset1280x720
แทนหากความเร็วในการสแกนเป็นสิ่งสำคัญ คุณสามารถลดความละเอียดในการจับภาพลงได้อีก อย่างไรก็ตาม โปรดคำนึงถึงข้อกำหนดขนาดบาร์โค้ดขั้นต่ำที่ระบุไว้ข้างต้น
- คันเร่งเรียกไปที่เครื่องตรวจจับ หากมีเฟรมวิดีโอใหม่ในขณะที่ตัวตรวจจับกำลังทำงานอยู่ ให้ปล่อยเฟรมนั้น
- หากคุณใช้เอาต์พุตของตัวตรวจจับเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต อันดับแรกรับผลลัพธ์จาก ML Kit จากนั้นเรนเดอร์รูปภาพและโอเวอร์เลย์ในขั้นตอนเดียว การทำเช่นนี้ คุณจะเรนเดอร์ไปยังพื้นผิวจอแสดงผลเพียงครั้งเดียวสำหรับแต่ละเฟรมอินพุต ดูตัวอย่างคลาส PreviewOverlayView และ FIRDetectionOverlayView ในแอปตัวอย่าง Showcase