Вы можете использовать ML Kit для распознавания и декодирования штрих-кодов.
Попробуйте это
- Поэкспериментируйте с примером приложения , чтобы увидеть пример использования этого API.
Прежде чем начать
- Включите в свой подфайл следующие модули ML Kit:
pod 'GoogleMLKit/BarcodeScanning', '3.2.0'
- После установки или обновления модулей вашего проекта откройте проект Xcode, используя его
.xcworkspace
. ML Kit поддерживается в Xcode версии 12.4 или новее.
Рекомендации по входному изображению
Чтобы 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-коды, создайте объект BarcodeScannerOptions
, как показано в следующем примере:
Быстрый
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Поддерживаются следующие форматы:
- код128
- код39
- код93
- кодаБар
- dataMatrix
- EAN13
- EAN8
- МФТ
- qrCode
- УПКА
- УПЦЭ
- PDF417
- ацтекский
Цель-C
MLKBarcodeScannerOptions *options = [[MLKBarcodeScannerOptions alloc] initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];
Поддерживаются следующие форматы:
- Код-128 (
MLKBarcodeFormatCode128
) - Код-39 (
MLKBarcodeFormatCode39
) - Код-93 (
MLKBarcodeFormatCode93
) - Кодабар (
MLKBarcodeFormatCodaBar
) - Матрица данных (
MLKBarcodeFormatDataMatrix
) - EAN-13 (
MLKBarcodeFormatEAN13
) - EAN-8 (
MLKBarcodeFormatEAN8
) - ITF (
MLKBarcodeFormatITF
) - QR-код (
MLKBarcodeFormatQRCode
) - UPC-A (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Ацтекский код (
MLKBarcodeFormatAztec
)
2. Подготовьте входное изображение
Чтобы сканировать штрих-коды в изображении, передайте изображение какUIImage
или CMSampleBufferRef
в метод BarcodeScanner
process()
или results(in:)
: Создайте объект VisionImage
используя UIImage
или CMSampleBuffer
.
Если вы используете UIImage
, выполните следующие действия:
- Создайте объект
VisionImage
с помощьюUIImage
. Обязательно укажите правильную.orientation
.Быстрый
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Цель-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Если вы используете
CMSampleBuffer
, выполните следующие действия:Укажите ориентацию данных изображения, содержащихся в
CMSampleBuffer
.Чтобы получить ориентацию изображения:
Быстрый
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 } }
Цель-C
- (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; } }
- Создайте объект
VisionImage
используя объектCMSampleBuffer
и ориентацию:Быстрый
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Цель-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Получите экземпляр BarcodeScanner.
Получите экземплярBarcodeScanner
:Быстрый
let barcodeScanner = BarcodeScanner.barcodeScanner() // Or, to change the default settings: // let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)
Цель-C
MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner]; // Or, to change the default settings: // MLKBarcodeScanner *barcodeScanner = // [MLKBarcodeScanner barcodeScannerWithOptions:options];
4. Обработка изображения
Затем передайте изображение вprocess()
:Быстрый
barcodeScanner.process(visionImage) { features, error in guard error == nil, let features = features, !features.isEmpty else { // Error handling return } // Recognized barcodes }
Цель-C
[barcodeScanner processImage:image completion:^(NSArray<MLKBarcode *> *_Nullable barcodes, NSError *_Nullable error) { if (error != nil) { // Error handling return; } if (barcodes.count > 0) { // Recognized barcodes } }];
5. Получите информацию из штрих-кодов
Если операция сканирования штрих-кода прошла успешно, сканер возвращает массив объектовBarcode
. Каждый объектBarcode
представляет собой штрих-код, обнаруженный на изображении. Для каждого штрих-кода вы можете получить его ограничивающие координаты во входном изображении, а также необработанные данные, закодированные штрих-кодом. Также, если сканер штрих-кода смог определить тип данных, закодированных штрих-кодом, вы можете получить объект, содержащий разобранные данные.Например:
Быстрый
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 (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; } }
Советы по повышению производительности в реальном времени
Если вы хотите сканировать штрих-коды в приложении реального времени, следуйте этим рекомендациям для достижения наилучшей частоты кадров:
Не записывайте входные данные с собственным разрешением камеры. На некоторых устройствах при захвате входных данных с собственным разрешением создаются чрезвычайно большие (10+ мегапикселей) изображения, что приводит к очень низкой задержке без какого-либо улучшения точности. Вместо этого запрашивайте у камеры только тот размер, который необходим для сканирования штрих-кода, который обычно не превышает 2 мегапикселя.
Однако именованные предустановки сеанса захвата —
AVCaptureSessionPresetDefault
,AVCaptureSessionPresetLow
,AVCaptureSessionPresetMedium
и т. д.) — не рекомендуются, поскольку они могут соответствовать неподходящим разрешениям на некоторых устройствах. Вместо этого используйте определенные пресеты, такие какAVCaptureSessionPreset1280x720
.Если скорость сканирования важна, вы можете еще больше снизить разрешение захвата изображения. Однако помните о требованиях к минимальному размеру штрих-кода, изложенных выше.
Если вы пытаетесь распознать штрих-коды из последовательности кадров потокового видео, распознаватель может выдавать разные результаты от кадра к кадру. Вам следует подождать, пока вы не получите последовательные серии одного и того же значения, чтобы быть уверенным, что вы возвращаете хороший результат.
Цифра контрольной суммы не поддерживается для ITF и CODE-39.
- Для обработки видеокадров используйте синхронный API
results(in:)
детектора. Вызовите этот метод из функцииcaptureOutput(_, didOutput:from:)
AVCaptureVideoDataOutputSampleBufferDelegate
, чтобы синхронно получить результаты из данного видеокадра. Оставьте дляAVCaptureVideoDataOutput
значениеalwaysDiscardsLateVideoFrames
какtrue
, чтобы ограничить вызовы детектора. Если во время работы детектора появится новый видеокадр, он будет удален. - Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат из ML Kit, затем визуализируйте изображение и наложите его за один шаг. При этом вы выполняете рендеринг на поверхность дисплея только один раз для каждого обработанного входного кадра. Пример см. в updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.
Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2024-09-30 UTC.
[[["Прост для понимания","easyToUnderstand","thumb-up"],["Помог мне решить мою проблему","solvedMyProblem","thumb-up"],["Другое","otherUp","thumb-up"]],[["Отсутствует нужная мне информация","missingTheInformationINeed","thumb-down"],["Слишком сложен/слишком много шагов","tooComplicatedTooManySteps","thumb-down"],["Устарел","outOfDate","thumb-down"],["Проблема с переводом текста","translationIssue","thumb-down"],["Проблемы образцов/кода","samplesCodeIssue","thumb-down"],["Другое","otherDown","thumb-down"]],["Последнее обновление: 2024-09-30 UTC."],[],[]]