Вы можете использовать ML Kit для распознавания и декодирования штрих-кодов.
Прежде чем вы начнете
- Если вы еще не добавили Firebase в свое приложение, сделайте это, следуя инструкциям в руководстве по началу работы.
- Включите библиотеки ML Kit в свой подфайл:
pod 'Firebase/MLVision' pod 'Firebase/MLVisionBarcodeModel'
После установки или обновления подов вашего проекта обязательно откройте проект Xcode, используя его.xcworkspace
. - В вашем приложении импортируйте Firebase:
Быстрый
import Firebase
Цель-C
@import Firebase;
Инструкции по входному изображению
Чтобы 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 пикселей.
Плохая фокусировка изображения может снизить точность сканирования. Если вы не получаете приемлемых результатов, попробуйте попросить пользователя повторно захватить изображение.
Для типичных приложений рекомендуется предоставлять изображение с более высоким разрешением (например, 1280x720 или 1920x1080), что позволяет обнаруживать штрих-коды на большем расстоянии от камеры.
Однако в приложениях, где задержка имеет решающее значение, вы можете повысить производительность, захватывая изображения с более низким разрешением, но требуя, чтобы штрих-код составлял большую часть входного изображения. Также см. Советы по повышению производительности в реальном времени .
1. Настройте детектор штрих-кода
Если вы знаете, какие форматы штрих-кода вы ожидаете считывать, вы можете повысить скорость детектора штрих-кода, настроив его на обнаружение только этих форматов. Например, чтобы обнаруживать только код Aztec и QR-коды, создайте объект VisionBarcodeDetectorOptions
, как показано в следующем примере:
Быстрый
let format = VisionBarcodeFormat.all let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)
Поддерживаются следующие форматы:
- Код128
- Код39
- Код93
- КодаБар
- EAN13
- EAN8
- МФТ
- УПЦА
- UPCE
- QR код
- PDF417
- ацтек
- DataMatrix
Цель-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
в метод VisionBarcodeDetector
для detect(in:)
:- Получите экземпляр
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 Kit, а затем выполните визуализацию изображения и наложение за один шаг. Поступая таким образом, вы визуализируете на поверхность дисплея только один раз для каждого входного кадра. В качестве примера см. классы previewOverlayView и FIRDetectionOverlayView в демонстрационном образце приложения.