אתה יכול להשתמש ב-ML Kit כדי לזהות ולפענח ברקודים.
לפני שאתה מתחיל
- אם עדיין לא הוספת את Firebase לאפליקציה שלך, עשה זאת על ידי ביצוע השלבים במדריך לתחילת העבודה .
- כלול את ספריות ML Kit ב-Podfile שלך:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
לאחר שתתקין או תעדכן את ה-Pods של הפרויקט שלך, הקפד לפתוח את פרויקט Xcode שלך באמצעות.xcworkspace
שלו. - באפליקציה שלך, ייבא את Firebase:
מָהִיר
import Firebase
Objective-C
@import Firebase;
הנחיות לקלט תמונה
כדי ש-ML Kit תקרא במדויק ברקודים, תמונות קלט חייבות להכיל ברקודים המיוצגים על ידי מספיק נתוני פיקסלים.
הדרישות הספציפיות לנתוני הפיקסלים תלויות הן בסוג הברקוד והן בכמות הנתונים המקודדת בו (שכן רוב הברקודים תומכים במטען באורך משתנה). באופן כללי, היחידה המשמעותית הקטנה ביותר של הברקוד צריכה להיות ברוחב של 2 פיקסלים לפחות (ועבור קודים דו-ממדיים, גובה של 2 פיקסלים).
לדוגמה, ברקודים של EAN-13 מורכבים מפס ורווחים ברוחב של 1, 2, 3 או 4 יחידות, כך שלתמונת ברקוד EAN-13 יש באופן אידיאלי פסים ורווחים שהם לפחות 2, 4, 6 ו רוחב 8 פיקסלים. מכיוון ברוחב של ברקוד EAN-13 הוא 95 יחידות בסך הכל, על הברקוד להיות ברוחב של 190 פיקסלים לפחות.
פורמטים צפופים יותר, כגון PDF417, צריכים ממדי פיקסלים גדולים יותר כדי ש-ML Kit יקרא אותם בצורה מהימנה. לדוגמה, קוד PDF417 יכול לכלול עד 34 "מילים" ברוחב של 17 יחידות בשורה אחת, שבאופן אידיאלי יהיו ברוחב של לפחות 1156 פיקסלים.
מיקוד לקוי של התמונה עלול לפגוע בדיוק הסריקה. אם אינך מקבל תוצאות מקובלות, נסה לבקש מהמשתמש לצלם מחדש את התמונה.
עבור יישומים טיפוסיים, מומלץ לספק תמונה ברזולוציה גבוהה יותר (כגון 1280x720 או 1920x1080), מה שהופך ברקודים לזיהוי ממרחק גדול יותר מהמצלמה.
עם זאת, ביישומים שבהם זמן האחזור הוא קריטי, אתה יכול לשפר את הביצועים על ידי לכידת תמונות ברזולוציה נמוכה יותר, אך דורש שהברקוד יהווה את רוב תמונת הקלט. ראה גם טיפים לשיפור הביצועים בזמן אמת .
1. הגדר את גלאי הברקוד
אם אתה יודע אילו פורמטים של ברקוד אתה מצפה לקרוא, אתה יכול לשפר את המהירות של גלאי הברקוד על ידי הגדרתו לזהות רק פורמטים אלה. לדוגמה, כדי לזהות רק קוד אצטקי וקודי QR, בנו אובייקט VisionBarcodeDetectorOptions
כמו בדוגמה הבאה:
מָהִיר
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
הפורמטים הבאים נתמכים:
- קוד128
- קוד39
- קוד93
- CodaBar
- EAN13
- EAN8
- ITF
- UPCA
- UPCE
- QRCode
- PDF417
- אצטקי
- מטריצת נתונים
Objective-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
הפורמטים הבאים נתמכים:
- קוד 128 (
FIRVisionBarcodeFormatCode128
) - קוד 39 (
FIRVisionBarcodeFormatCode39
) - קוד 93 (
FIRVisionBarcodeFormatCode93
) - Codabar (
FIRVisionBarcodeFormatCodaBar
) - EAN-13 (
FIRVisionBarcodeFormatEAN13
) - EAN-8 (
FIRVisionBarcodeFormatEAN8
) - ITF (
FIRVisionBarcodeFormatITF
) - UPC-A (
FIRVisionBarcodeFormatUPCA
) - UPC-E (
FIRVisionBarcodeFormatUPCE
) - קוד QR (
FIRVisionBarcodeFormatQRCode
) - PDF417 (
FIRVisionBarcodeFormatPDF417
) - אצטקי (
FIRVisionBarcodeFormatAztec
) - מטריצת נתונים (
FIRVisionBarcodeFormatDataMatrix
)
2. הפעל את גלאי הברקוד
כדי לסרוק ברקודים בתמונה, העבר את התמונה כ-UIImage
או CMSampleBufferRef
לשיטת detect(in:)
של VisionBarcodeDetector
:- קבל מופע של
VisionBarcodeDetector
:מָהִיר
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];
צור אובייקט
VisionImage
באמצעותUIImage
אוCMSampleBufferRef
.כדי להשתמש
UIImage
:- במידת הצורך, סובב את התמונה כך
imageOrientation
שלה יהיה.up
. - צור אובייקט
VisionImage
באמצעותUIImage
המסובב כהלכה. אל תציין מטא נתונים כלשהם של סיבוב - יש להשתמש בערך ברירת המחדל,.topLeft
.מָהִיר
let image = VisionImage(image: uiImage)
Objective-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 } }
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; } }
לאחר מכן, צור את אובייקט המטא נתונים:
מָהִיר
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];
- צור אובייקט
VisionImage
באמצעות האובייקטCMSampleBufferRef
והמטא נתונים של הסיבוב:מָהִיר
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-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 } // ... }
Objective-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 } }
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; } }
טיפים לשיפור הביצועים בזמן אמת
אם ברצונך לסרוק ברקודים ביישום בזמן אמת, עקוב אחר ההנחיות הבאות כדי להשיג את קצבי המסגרות הטובים ביותר:
אל תלכוד קלט ברזולוציה המקורית של המצלמה. במכשירים מסוימים, לכידת קלט ברזולוציה המקורית מייצרת תמונות גדולות במיוחד (10+ מגה פיקסל), מה שגורם להשהייה נמוכה מאוד ללא תועלת לדיוק. במקום זאת, בקש רק מהמצלמה את הגודל הנדרש לזיהוי ברקוד: בדרך כלל לא יותר מ-2 מגה-פיקסל.
עם זאת, ההגדרות המוגדרות מראש של הפעלת הלכידה -
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
וכן הלאה) - אינן מומלצות, מכיוון שהן עלולות למפות לרזולוציות לא מתאימות במכשירים מסוימים. במקום זאת, השתמש בהגדרות המוגדרות מראש הספציפיות כגוןAVCaptureSessionPreset1280x720
.אם מהירות הסריקה חשובה, תוכל להוריד עוד יותר את רזולוציית לכידת התמונה. עם זאת, זכור את דרישות גודל הברקוד המינימלי המפורטות לעיל.
- מצערת קוראת לגלאי. אם מסגרת וידאו חדשה הופכת לזמינה בזמן שהגלאי פועל, שחרר את המסגרת.
- אם אתה משתמש בפלט של הגלאי כדי לשכב גרפיקה על תמונת הקלט, תחילה קבל את התוצאה מ-ML Kit, ולאחר מכן עבד את התמונה ואת שכבת העל בצעד אחד. על ידי כך, אתה מעבד למשטח התצוגה רק פעם אחת עבור כל מסגרת קלט. ראה את המחלקות previewOverlayView ו- FIRDetectionOverlayView באפליקציה לדוגמה לראווה לדוגמא.