Bạn có thể sử dụng ML Kit để nhận dạng và giải mã mã vạch.
Trước khi bắt đầu
- Nếu bạn chưa thêm Firebase vào ứng dụng của mình, hãy làm như vậy bằng cách làm theo các bước trong hướng dẫn bắt đầu .
- Bao gồm các thư viện ML Kit trong Podfile của bạn:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
Sau khi bạn cài đặt hoặc cập nhật Pods của dự án, hãy nhớ mở dự án Xcode của bạn bằng cách sử dụng.xcworkspace
của nó. - Trong ứng dụng của bạn, hãy nhập Firebase:
Nhanh
import Firebase
Objective-C
@import Firebase;
Nguyên tắc đầu vào hình ảnh
Để ML Kit có thể đọc chính xác mã vạch, hình ảnh đầu vào phải chứa mã vạch được thể hiện bằng đủ dữ liệu pixel.
Các yêu cầu về dữ liệu pixel cụ thể phụ thuộc vào cả loại mã vạch và số lượng dữ liệu được mã hóa trong đó (vì hầu hết các mã vạch đều hỗ trợ trọng tải có độ dài thay đổi). Nói chung, đơn vị có ý nghĩa nhỏ nhất của mã vạch phải rộng ít nhất 2 pixel (và đối với mã 2 chiều, cao 2 pixel).
Ví dụ: mã vạch EAN-13 được tạo thành từ các thanh và khoảng trắng rộng 1, 2, 3 hoặc 4 đơn vị, vì vậy hình ảnh mã vạch EAN-13 lý tưởng có các thanh và khoảng trống ít nhất là 2, 4, 6 và Rộng 8 pixel. Vì mã vạch EAN-13 có tổng chiều rộng là 95 đơn vị, nên mã vạch phải có chiều rộng ít nhất là 190 pixel.
Các định dạng dày đặc hơn, chẳng hạn như PDF417, cần kích thước pixel lớn hơn để ML Kit có thể đọc chúng một cách đáng tin cậy. Ví dụ: mã PDF417 có thể có tối đa 34 "từ" rộng 17 đơn vị trong một hàng, lý tưởng là rộng ít nhất 1156 pixel.
Lấy nét hình ảnh kém có thể làm ảnh hưởng đến độ chính xác của quá trình quét. Nếu bạn không nhận được kết quả chấp nhận được, hãy thử yêu cầu người dùng lấy lại hình ảnh.
Đối với các ứng dụng điển hình, bạn nên cung cấp hình ảnh có độ phân giải cao hơn (chẳng hạn như 1280x720 hoặc 1920x1080), giúp mã vạch có thể phát hiện được từ khoảng cách xa máy ảnh hơn.
Tuy nhiên, trong các ứng dụng có độ trễ là quan trọng, bạn có thể cải thiện hiệu suất bằng cách chụp ảnh ở độ phân giải thấp hơn, nhưng yêu cầu mã vạch chiếm phần lớn hình ảnh đầu vào. Ngoài ra, hãy xem Mẹo để cải thiện hiệu suất thời gian thực .
1. Định cấu hình máy dò mã vạch
Nếu bạn biết định dạng mã vạch nào bạn muốn đọc, bạn có thể cải thiện tốc độ của máy dò mã vạch bằng cách định cấu hình nó để chỉ phát hiện các định dạng đó. Ví dụ: để chỉ phát hiện mã Aztec và mã QR, hãy xây dựng đối tượng VisionBarcodeDetectorOptions
như trong ví dụ sau:
Nhanh
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
Các định dạng sau được hỗ trợ:
- Mã128
- Mã39
- Mã số93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- LÊN
- Mã QR
- PDF417
- Aztec
- Ma trận dữ liệu
Objective-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
Các định dạng sau được hỗ trợ:
- Mã 128 (
FIRVisionBarcodeFormatCode128
) - Mã 39 (
FIRVisionBarcodeFormatCode39
) - Mã 93 (
FIRVisionBarcodeFormatCode93
) - Codabar (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ITF (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - Mã QR (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - Aztec (
FIRVisionBarcodeFormatAztec
) - Ma trận dữ liệu (
FIRVisionBarcodeFormatDataMatrix
)
2. Chạy máy dò mã vạch
Để quét mã vạch trong hình ảnh, hãy chuyển hình ảnh dưới dạngUIImage
hoặc CMSampleBufferRef
đến phương thức detect(in:)
của VisionBarcodeDetector
:- Nhận một phiên bản của
VisionBarcodeDetector
:Nhanh
lazy var vision = Vision.vision() let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
Objective-C
FIRVision *vision = [FIRVision vision]; FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector]; // Or, to change the default settings: // FIRVisionBarcodeDetector *barcodeDetector = // [vision barcodeDetectorWithOptions:options];
Tạo đối tượng
VisionImage
bằngUIImage
hoặcCMSampleBufferRef
.Để sử dụng
UIImage
:- Nếu cần, hãy xoay hình ảnh để thuộc tính
imageOrientation
của nó là.up
. - Tạo một đối tượng
VisionImage
bằng cách sử dụngUIImage
được xoay chính xác. Không chỉ định bất kỳ siêu dữ liệu xoay vòng nào — phải sử dụng giá trị mặc định,.topLeft
.Nhanh
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Để sử dụng
CMSampleBufferRef
:Tạo một đối tượng
VisionImageMetadata
chỉ định hướng của dữ liệu hình ảnh có trong bộ đệmCMSampleBufferRef
.Để có được hướng hình ảnh:
Nhanh
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 } }
Objective-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; } }
Sau đó, tạo đối tượng siêu dữ liệu:
Nhanh
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-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];
- Tạo đối tượng
VisionImage
bằng đối tượngCMSampleBufferRef
và siêu dữ liệu xoay:Nhanh
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Nếu cần, hãy xoay hình ảnh để thuộc tính
- Sau đó, chuyển hình ảnh vào phương thức
detect(in:)
:Nhanh
barcodeDetector.detect(in: visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // ... return } // ... }
Objective-C
[barcodeDetector detectInImage:image completion:^(NSArray<FIRVisionBarcode *> *barcodes, NSError *error) { if (error != nil) { return; } else if (barcodes != nil) { // Recognized barcodes // ... } }];
3. Nhận thông tin từ mã vạch
Nếu hoạt động nhận dạng mã vạch thành công, bộ dò sẽ trả về một mảng các đối tượngVisionBarcode
. Mỗi đối tượng VisionBarcode
đại diện cho một mã vạch đã được phát hiện trong hình ảnh. Đối với mỗi mã vạch, bạn có thể lấy tọa độ giới hạn của nó trong hình ảnh đầu vào, cũng như dữ liệu thô được mã hóa bởi mã vạch. Ngoài ra, nếu máy dò mã vạch có thể xác định loại dữ liệu được mã hóa bởi mã vạch, bạn có thể nhận được một đối tượng chứa dữ liệu được phân tích cú pháp.Ví dụ:
Nhanh
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 (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; } }
Mẹo để cải thiện hiệu suất thời gian thực
Nếu bạn muốn quét mã vạch trong ứng dụng thời gian thực, hãy làm theo các nguyên tắc sau để đạt được tốc độ khung hình tốt nhất:
Không chụp đầu vào ở độ phân giải gốc của máy ảnh. Trên một số thiết bị, chụp đầu vào ở độ phân giải gốc tạo ra hình ảnh cực lớn (10+ megapixel), dẫn đến độ trễ rất kém mà không có lợi cho độ chính xác. Thay vào đó, chỉ yêu cầu kích thước từ máy ảnh được yêu cầu để phát hiện mã vạch: thường không quá 2 megapixel.
Các cài đặt trước phiên chụp được đặt tên—
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
, v.v.) - không được khuyến nghị, tuy nhiên, chúng có thể ánh xạ tới các độ phân giải không phù hợp trên một số thiết bị. Thay vào đó, hãy sử dụng các cài đặt trước cụ thể nhưAVCaptureSessionPreset1280x720
.Nếu tốc độ quét là quan trọng, bạn có thể giảm thêm độ phân giải chụp ảnh. Tuy nhiên, hãy nhớ các yêu cầu về kích thước mã vạch tối thiểu được nêu ở trên.
- Các cuộc gọi từ bướm ga đến máy dò. Nếu có một khung video mới trong khi trình dò đang chạy, hãy thả khung đó xuống.
- Nếu bạn đang sử dụng đầu ra của máy dò để phủ đồ họa lên hình ảnh đầu vào, trước tiên hãy lấy kết quả từ Bộ công cụ ML, sau đó hiển thị hình ảnh và lớp phủ trong một bước duy nhất. Bằng cách đó, bạn chỉ hiển thị trên bề mặt hiển thị một lần cho mỗi khung hình đầu vào. Xem các lớp previewOverlayView và FIRDetectionOverlayView trong ứng dụng mẫu trưng bày để làm ví dụ.