برای شناسایی و رمزگشایی بارکدها می توانید از کیت ML استفاده کنید.
قبل از شروع
- اگر قبلاً Firebase را به برنامه خود اضافه نکرده اید، این کار را با دنبال کردن مراحل راهنمای شروع کار انجام دهید.
- کتابخانه های ML Kit را در پادفایل خود قرار دهید:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
پس از نصب یا بهروزرسانی Pods پروژه، حتماً پروژه Xcode خود را با استفاده از.xcworkspace
آن باز کنید. - در برنامه خود، Firebase را وارد کنید:
سویفت
import Firebase
هدف-C
@import Firebase;
دستورالعمل های تصویر ورودی
برای اینکه کیت ML بتواند بارکدها را به طور دقیق بخواند، تصاویر ورودی باید حاوی بارکدهایی باشند که با داده های پیکسلی کافی نشان داده شوند.
نیازهای خاص داده پیکسلی هم به نوع بارکد و هم به مقدار داده ای که در آن کدگذاری می شود بستگی دارد (زیرا اکثر بارکدها از یک بار با طول متغیر پشتیبانی می کنند). به طور کلی، کوچکترین واحد معنی دار بارکد باید حداقل 2 پیکسل عرض داشته باشد (و برای کدهای 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
- کد QRC
- PDF417
- آزتک
- DataMatrix
هدف-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
فرمت های زیر پشتیبانی می شوند:
- کد 128 (
FIRVisionBarcodeFormatCode128
) - کد 39 (
FIRVisionBarcodeFormatCode39
) - کد 93 (
FIRVisionBarcodeFormatCode93
) - کدابار (
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)
هدف-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 دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. با انجام این کار، برای هر فریم ورودی فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال، کلاسهای previewOverlayView و FIRDetectionOverlayView را در برنامه نمونه ویترینی ببینید.
برای شناسایی و رمزگشایی بارکدها می توانید از کیت ML استفاده کنید.
قبل از شروع
- اگر قبلاً Firebase را به برنامه خود اضافه نکرده اید، این کار را با دنبال کردن مراحل راهنمای شروع کار انجام دهید.
- کتابخانه های ML Kit را در پادفایل خود قرار دهید:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
پس از نصب یا بهروزرسانی Pods پروژه، حتماً پروژه Xcode خود را با استفاده از.xcworkspace
آن باز کنید. - در برنامه خود، Firebase را وارد کنید:
سویفت
import Firebase
هدف-C
@import Firebase;
دستورالعمل های تصویر ورودی
برای اینکه کیت ML بتواند بارکدها را به طور دقیق بخواند، تصاویر ورودی باید حاوی بارکدهایی باشند که با داده های پیکسلی کافی نشان داده شوند.
نیازهای خاص داده پیکسلی هم به نوع بارکد و هم به مقدار داده ای که در آن کدگذاری می شود بستگی دارد (زیرا اکثر بارکدها از یک بار با طول متغیر پشتیبانی می کنند). به طور کلی، کوچکترین واحد معنی دار بارکد باید حداقل 2 پیکسل عرض داشته باشد (و برای کدهای 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
- کد QRC
- PDF417
- آزتک
- DataMatrix
هدف-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
فرمت های زیر پشتیبانی می شوند:
- کد 128 (
FIRVisionBarcodeFormatCode128
) - کد 39 (
FIRVisionBarcodeFormatCode39
) - کد 93 (
FIRVisionBarcodeFormatCode93
) - کدابار (
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)
هدف-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 دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. با انجام این کار، برای هر فریم ورودی فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال، کلاسهای previewOverlayView و FIRDetectionOverlayView را در برنامه نمونه ویترینی ببینید.
برای شناسایی و رمزگشایی بارکدها می توانید از کیت ML استفاده کنید.
قبل از شروع
- اگر قبلاً Firebase را به برنامه خود اضافه نکرده اید، این کار را با دنبال کردن مراحل راهنمای شروع کار انجام دهید.
- کتابخانه های ML Kit را در پادفایل خود قرار دهید:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
پس از نصب یا بهروزرسانی Pods پروژه، حتماً پروژه Xcode خود را با استفاده از.xcworkspace
آن باز کنید. - در برنامه خود، Firebase را وارد کنید:
سویفت
import Firebase
هدف-C
@import Firebase;
دستورالعمل های تصویر ورودی
برای اینکه کیت ML بتواند بارکدها را به طور دقیق بخواند، تصاویر ورودی باید حاوی بارکدهایی باشند که با داده های پیکسلی کافی نشان داده شوند.
نیازهای خاص داده پیکسلی هم به نوع بارکد و هم به مقدار داده ای که در آن کدگذاری می شود بستگی دارد (زیرا اکثر بارکدها از یک بار با طول متغیر پشتیبانی می کنند). به طور کلی، کوچکترین واحد معنی دار بارکد باید حداقل 2 پیکسل عرض داشته باشد (و برای کدهای 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
- کد QRC
- PDF417
- آزتک
- DataMatrix
هدف-C
FIRVisionBarcodeDetectorOptions *options = [[FIRVisionBarcodeDetectorOptions alloc] initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];
فرمت های زیر پشتیبانی می شوند:
- کد 128 (
FIRVisionBarcodeFormatCode128
) - کد 39 (
FIRVisionBarcodeFormatCode39
) - کد 93 (
FIRVisionBarcodeFormatCode93
) - کدابار (
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)
هدف-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 دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. با انجام این کار، برای هر فریم ورودی فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال، کلاسهای previewOverlayView و FIRDetectionOverlayView را در برنامه نمونه ویترینی ببینید.