میتوانید از ML Kit برای تشخیص و رمزگشایی بارکدها استفاده کنید.
امتحان کنید
- با برنامه نمونه بازی کنید تا نمونهای از کاربرد این API را ببینید.
قبلاز شروع
- غلافهای ML Kit زیر را در Podfile خود بگنجانید:
pod 'GoogleMLKit/BarcodeScanning', '8.0.0'
- پساز نصب یا بهروزرسانی Pods پروژه، پروژه Xcode خود را بااستفاده از
.xcworkspaceباز کنید. ML Kit در Xcode نسخه ۱۲.۴ یا بالاتر پشتیبانی میشود.
دستورالعملهای تصویر ورودی
-
برای اینکه ML Kit بارکدها را بهدقت بخواند، تصاویر ورودی باید حاوی بارکدهایی باشند که با دادههای پیکسل کافی نشان داده شدهاند.
الزامات خاص دادههای پیکسل هم به نوع بارکد و هم به مقدار دادههایی که در آن کدگذاری شده است بستگی دارد، زیرا بسیاری از بارکدها از اندازه متغیر بار مفید پشتیبانی میکنند. بهطورکلی، کوچکترین واحد معنادار بارکد باید حداقل ۲ پیکسل عرض داشته باشد، و برای کدهای ۲ بعدی، ۲ پیکسل ارتفاع داشته باشد.
برای مثال، بارکدهای EAN-13 از خطوط و فاصلههایی تشکیل شدهاند که ۱، ۲، ۳، یا ۴ واحد پهنا دارند، بنابراین تصویر بارکد EAN-13 بهطور ایدهآل دارای خطوط و فاصلههایی است که حداقل ۲، ۴، ۶، و ۸ پیکسل پهنا دارند. چون بارکد EAN-13 در مجموع ۹۵ واحد پهنا دارد، بارکد باید حداقل ۱۹۰ پیکسل پهنا داشته باشد.
قالبهای متراکمتر، مانند PDF417، برای اینکه ML Kit بتواند آنها را بهطور قابلاعتمادی بخواند، به ابعاد پیکسلی بزرگتری نیاز دارند. برای مثال، یک کد PDF417 میتواند حداکثر ۳۴ «کلمه» با عرض ۱۷ واحد در یک ردیف داشته باشد که در حالت ایدهآل باید حداقل ۱۱۵۶ پیکسل عرض داشته باشد.
-
فوکوس ضعیف تصویر میتواند بر دقت اسکن تأثیر بگذارد. اگر برنامهتان نتایج قابلقبولی دریافت نمیکند، از کاربر بخواهید تصویر را دوباره ضبط کند.
-
برای برنامههای معمولی، توصیه میشود تصویری با وضوح بالاتر ارائه شود، مثلاً ۱۲۸۰×۷۲۰ یا ۱۹۲۰×۱۰۸۰، که باعث میشود رمزینهها از فاصله دورتری از دوربین قابلاسکن باشند.
بااینحال، در برنامههایی که تأخیر در آنها حیاتی است، میتوانید با گرفتن تصویر در وضوح پایینتر، عملکرد را بهبود دهید، اما باید بارکد بخش عمدهای از تصویر ورودی را تشکیل دهد. همچنین نکاتی برای بهبود عملکرد همزمان را ببینید.
۱. پیکربندی اسکنر بارکد
اگر میدانید که انتظار دارید کدام قالبهای بارکد خوانده شود، میتوانید با پیکربندی اسکنر بارکد برای اسکن کردن فقط آن قالبها، سرعت آن را بهبود دهید.برای مثال، برای اسکن کردن فقط کد Aztec و رمزینههای پاسخسریع،
شیء BarcodeScannerOptions را مانند
مثال زیر بسازید:
Swift
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
قالبهای زیر پشتیبانی میشوند:
- code128
- code39
- code93
- codaBar
- dataMatrix
- EAN13
- EAN8
- ITF
- qrCode
- UPCA
- UPCE
- PDF417
- آزتک
آبجکتیو-سی
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
قالبهای زیر پشتیبانی میشوند:
- کد-۱۲۸ (
MLKBarcodeFormatCode128) - Code-39 (
MLKBarcodeFormatCode39) - Code-93 (
MLKBarcodeFormatCode93) - Codabar (
MLKBarcodeFormatCodaBar) - ماتریکس دادهها (
MLKBarcodeFormatDataMatrix) - EAN-13 (
MLKBarcodeFormatEAN13) - EAN-8 (
MLKBarcodeFormatEAN8) - ITF (
MLKBarcodeFormatITF) - رمزینه پاسخسریع (
MLKBarcodeFormatQRCode) - UPC-A (
MLKBarcodeFormatUPCA) - UPC-E (
MLKBarcodeFormatUPCE) - PDF-417 (
MLKBarcodeFormatPDF417) - کد آزتک (
MLKBarcodeFormatAztec)
۲. آماده کردن تصویر ورودی
برای اسکن کردن رمزینهها در تصویر، تصویر را بهعنوانUIImage یا
CMSampleBufferRef به روش process() یا results(in:)
BarcodeScanner ارسال کنید:
بااستفاده از UIImage یا CMSampleBuffer، یک شیء VisionImage ایجاد کنید.
اگر از UIImage استفاده میکنید، این مراحل را دنبال کنید:
- با
UIImage، شیءVisionImageایجاد کنید. حتماً.orientationصحیح را مشخص کنید.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
آبجکتیو-سی
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 } }
آبجکتیو-سی
- (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; } }
- بااستفاده از
شیء
CMSampleBufferو جهتگیری، شیءVisionImageایجاد کنید:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
آبجکتیو-سی
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
۳. دریافت نمونهای از BarcodeScanner
نمونهای ازBarcodeScanner را دریافت کنید:
Swift
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
آبجکتیو-سی
MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner]; // Or, to change the default settings: // MLKBarcodeScanner *barcodeScanner = // [MLKBarcodeScanner barcodeScannerWithOptions:options];
۴. پردازش تصویر
سپس تصویر را به روشprocess() ارسال کنید:
Swift
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
آبجکتیو-سی
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
۵. دریافت اطلاعات از رمزینهها
اگر عملیات اسکن بارکد موفقیتآمیز باشد، اسکنر آرایهای از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 } }
آبجکتیو-سی
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; } }
نکتههایی برای بهبود عملکرد همزمان
اگر میخواهید بارکدها را در یک برنامه درلحظه اسکن کنید، این دستورالعملها را دنبال کنید تا به بهترین نرخهای فریم دست یابید:
-
ورودی را با وضوح اصلی دوربین ضبط نکنید. در برخیاز دستگاهها، ضبط ورودی با وضوح بومی منجر به تولید تصاویر بسیار بزرگ (بیشاز ۱۰ مگاپیکسل) میشود که درنتیجه تأخیر بسیار بدی بدون هیچگونه سودی برای دقت ایجاد میکند. درعوض، فقط اندازه موردنیاز برای اسکن کردن بارکد را از دوربین درخواست کنید که معمولاً بیشتر از ۲ مگاپیکسل نیست.
بااینحال، پیشتنظیمهای جلسه ضبط نامگذاریشده (
AVCaptureSessionPresetDefault،AVCaptureSessionPresetLow،AVCaptureSessionPresetMedium، و غیره) توصیه نمیشوند، زیرا ممکن است در برخی دستگاهها به وضوحهای نامناسب نگاشت شوند. بهجای آن، از پیشتنظیمهای خاص مثلAVCaptureSessionPreset1280x720استفاده کنید.اگر سرعت اسکن کردن برایتان مهم است، میتوانید وضوح تصویربرداری را بیشتر کاهش دهید. بااینحال، الزامات حداقل اندازه بارکد را که در بالا ذکر شده است بهخاطر داشته باشید.
اگر میخواهید بارکدها را از توالی قابهای ویدیو جاریسازی تشخیص دهید، ممکن است تشخیصدهنده نتایج متفاوتی از قاب به قاب تولید کند. باید صبر کنید تا مجموعهای پیوسته از مقدار یکسان دریافت کنید تا مطمئن شوید نتیجه خوبی برمیگردانید.
رقم «جمعآزما» برای ITF و CODE-39 پشتیبانی نمیشود.
- برای پردازش قابهای ویدیو، از
results(in:)میانای برنامهسازی کاربردی همزمان آشکارساز استفاده کنید. این روش را از تابعcaptureOutput(_, didOutput:from:)مربوط بهAVCaptureVideoDataOutputSampleBufferDelegateفراخوانی کنید تا نتایج را بهصورت همگام از فریم ویدیو دادهشده دریافت کنید.AVCaptureVideoDataOutputalwaysDiscardsLateVideoFramesرا بهعنوانtrueنگه دارید تا تماسهای برقرارشده با آشکارساز را محدود کنید. اگر قاب ویدیو جدیدی درحین اجرای آشکارساز دردسترس قرار گیرد، حذف خواهد شد. - اگر از برونداد آشکارساز برای رونهادن گرافیک روی تصویر ورودی استفاده میکنید، ابتدا نتیجه را از ML Kit دریافت کنید، سپس تصویر را پرداز و در یک مرحله رونهاد کنید. با انجام این کار، برای هر قاب ورودی پردازششده، فقط یکبار به سطح نمایشگر رندر میکنید. برای نمونه، updatePreviewOverlayViewWithLastFrame را در نمونه راهاندازی سریع ML Kit ببینید.