Вы можете использовать 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 и 4 единиц. 8 пикселей в ширину. Поскольку штрих-код EAN-13 имеет общую ширину 95 единиц, ширина штрих-кода должна быть не менее 190 пикселей.
Более плотные форматы, такие как PDF417, требуют больших размеров в пикселях, чтобы ML Kit мог их надежно читать. Например, код PDF417 может содержать до 34 «слов» шириной 17 единиц в одной строке, что в идеале должно иметь ширину не менее 1156 пикселей.
Плохая фокусировка изображения может повлиять на точность сканирования. Если ваше приложение не дает приемлемых результатов, попросите пользователя повторно захватить изображение.
Для типичных приложений рекомендуется предоставлять изображение с более высоким разрешением, например 1280 x 720 или 1920 x 1080, что позволяет сканировать штрих-коды с большего расстояния от камеры.
Однако в приложениях, где задержка имеет решающее значение, вы можете повысить производительность, захватывая изображения с более низким разрешением, но требуя, чтобы штрих-код составлял большую часть входного изображения. Также см. Советы по повышению производительности в реальном времени .
1. Настройте сканер штрих-кода
Если вы знаете, какие форматы штрих-кодов вы ожидаете считывать, вы можете повысить скорость сканера штрих-кодов, настроив его на сканирование только этих форматов. Например, чтобы сканировать только код Aztec и QR-коды, создайте объект BarcodeScannerOptions
, как показано в следующем примере:
Быстрый
let format = .all let barcodeOptions = BarcodeScannerOptions(formats: format)
Поддерживаются следующие форматы:
- код128
- код 39
- код93
- codaBar
- матрица данных
- EAN13
- EAN8
- МФТ
- QR код
- УПЦА
- UPCE
- 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
) - СКП-А (
MLKBarcodeFormatUPCA
) - UPC-E (
MLKBarcodeFormatUPCE
) - PDF-417 (
MLKBarcodeFormatPDF417
) - Код ацтеков (
MLKBarcodeFormatAztec
)
2. Подготовьте входное изображение
Чтобы сканировать штрих-коды в изображении, передайте изображение какUIImage
или CMSampleBufferRef
process()
или results(in:)
BarcodeScanner
: Создайте объект 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:)
детектора. Вызовите этот метод изAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
чтобы синхронно получить результаты из данного видеокадра. СохраняйтеAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
какtrue
, чтобы ограничить вызовы детектора. Если новый видеокадр становится доступным во время работы детектора, он будет отброшен. - Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем выполните визуализацию изображения и наложение за один шаг. Поступая таким образом, вы визуализируете на поверхность дисплея только один раз для каждого обработанного входного кадра. В качестве примера см. updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.
Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2023-09-26 UTC.
[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Отсутствует нужная мне информация" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Слишком сложен/слишком много шагов" },{ "type": "thumb-down", "id": "outOfDate", "label":"Устарел" },{ "type": "thumb-down", "id": "translationIssue", "label":"Проблема с переводом текста" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Проблемы образцов/кода" },{ "type": "thumb-down", "id": "otherDown", "label":"Другое" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Прост для понимания" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Помог мне решить мою проблему" },{ "type": "thumb-up", "id": "otherUp", "label":"Другое" }]