С помощью ML Kit можно распознавать текст на изображениях или видео, например текст на дорожном знаке. Основные характеристики этой функции:
| Text Recognition v2 API | |
|---|---|
| Описание | Распознавать текст на изображениях и видео. Поддерживаются латиница, китайский, деванагари, японский и корейский алфавиты, а также широкий спектр языков. |
| Названия SDK | GoogleMLKit/TextRecognition |
| Реализация | Объекты статически связываются с приложением во время сборки. |
| Влияние на размер приложения | Около 38 МБ на каждый скрипт SDK |
| Эффективность | В реальном времени на большинстве устройств для SDK с латинским шрифтом, медленнее для других. |
Попробовать
- Попробуйте пример приложения, чтобы увидеть, как используется этот API.
- Попробуйте код самостоятельно, используя практическую работу.
Подготовка
- Добавьте в Podfile следующие поды ML Kit:
# To recognize Latin script pod 'GoogleMLKit/TextRecognition', '8.0.0' # To recognize Chinese script pod 'GoogleMLKit/TextRecognitionChinese', '8.0.0' # To recognize Devanagari script pod 'GoogleMLKit/TextRecognitionDevanagari', '8.0.0' # To recognize Japanese script pod 'GoogleMLKit/TextRecognitionJapanese', '8.0.0' # To recognize Korean script pod 'GoogleMLKit/TextRecognitionKorean', '8.0.0'
- После установки или обновления Pods откройте проект Xcode, используя файл
.xcworkspace. ML Kit поддерживается в Xcode версии 12.4 и выше.
1. Создайте экземпляр TextRecognizer.
Создайте экземпляр TextRecognizer, вызвав +textRecognizer(options:) и передав параметры, связанные с SDK, который вы объявили как зависимость выше:
Swift
// When using Latin script recognition SDK let latinOptions = TextRecognizerOptions() let latinTextRecognizer = TextRecognizer.textRecognizer(options:options) // When using Chinese script recognition SDK let chineseOptions = ChineseTextRecognizerOptions() let chineseTextRecognizer = TextRecognizer.textRecognizer(options:options) // When using Devanagari script recognition SDK let devanagariOptions = DevanagariTextRecognizerOptions() let devanagariTextRecognizer = TextRecognizer.textRecognizer(options:options) // When using Japanese script recognition SDK let japaneseOptions = JapaneseTextRecognizerOptions() let japaneseTextRecognizer = TextRecognizer.textRecognizer(options:options) // When using Korean script recognition SDK let koreanOptions = KoreanTextRecognizerOptions() let koreanTextRecognizer = TextRecognizer.textRecognizer(options:options)
Objective-C
// When using Latin script recognition SDK MLKTextRecognizerOptions *latinOptions = [[MLKTextRecognizerOptions alloc] init]; MLKTextRecognizer *latinTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options]; // When using Chinese script recognition SDK MLKChineseTextRecognizerOptions *chineseOptions = [[MLKChineseTextRecognizerOptions alloc] init]; MLKTextRecognizer *chineseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options]; // When using Devanagari script recognition SDK MLKDevanagariTextRecognizerOptions *devanagariOptions = [[MLKDevanagariTextRecognizerOptions alloc] init]; MLKTextRecognizer *devanagariTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options]; // When using Japanese script recognition SDK MLKJapaneseTextRecognizerOptions *japaneseOptions = [[MLKJapaneseTextRecognizerOptions alloc] init]; MLKTextRecognizer *japaneseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options]; // When using Korean script recognition SDK MLKKoreanTextRecognizerOptions *koreanOptions = [[MLKKoreanTextRecognizerOptions alloc] init]; MLKTextRecognizer *koreanTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];
2. Подготовьте исходное изображение
Передайте изображение в видеUIImage или CMSampleBufferRef методу process(_:completion:) объекта TextRecognizer:
Создайте объект VisionImage, используя UIImage или CMSampleBuffer.
Если вы используете UIImage, выполните следующие действия:
- Создайте объект
VisionImageсUIImage. Убедитесь, что вы указали правильное значение параметра.orientation.Swift
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Objective-C
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 } }
Objective-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и ориентацию:Swift
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Objective-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Обработка изображения
Затем передайте изображение методу process(_:completion:):
Swift
textRecognizer.process(visionImage) { result, error in
guard error == nil, let result = result else {
// Error handling
return
}
// Recognized text
}Objective-C
[textRecognizer processImage:image completion:^(MLKText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // Error handling return; } // Recognized text }];
4. Извлечение текста из блоков распознанного текста
Если операция распознавания текста выполнена успешно, возвращается объект Text. Объект Text содержит полный текст, распознанный на изображении, и ноль или более объектов TextBlock.
Каждый объект TextBlock представляет собой прямоугольный текстовый блок, который может содержать ноль или более объектов TextLine. Каждый объект TextLine содержит ноль или более объектов TextElement, представляющих слова и подобные им сущности, например даты и числа.
Для каждого объекта TextBlock, TextLine и TextElement можно получить текст, распознанный в регионе, и координаты границ региона.
Пример:
Swift
let resultText = result.text
for block in result.blocks {
let blockText = block.text
let blockLanguages = block.recognizedLanguages
let blockCornerPoints = block.cornerPoints
let blockFrame = block.frame
for line in block.lines {
let lineText = line.text
let lineLanguages = line.recognizedLanguages
let lineCornerPoints = line.cornerPoints
let lineFrame = line.frame
for element in line.elements {
let elementText = element.text
let elementCornerPoints = element.cornerPoints
let elementFrame = element.frame
}
}
}Objective-C
NSString *resultText = result.text;
for (MLKTextBlock *block in result.blocks) {
NSString *blockText = block.text;
NSArray<MLKTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages;
NSArray<NSValue *> *blockCornerPoints = block.cornerPoints;
CGRect blockFrame = block.frame;
for (MLKTextLine *line in block.lines) {
NSString *lineText = line.text;
NSArray<MLKTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages;
NSArray<NSValue *> *lineCornerPoints = line.cornerPoints;
CGRect lineFrame = line.frame;
for (MLKTextElement *element in line.elements) {
NSString *elementText = element.text;
NSArray<NSValue *> *elementCornerPoints = element.cornerPoints;
CGRect elementFrame = element.frame;
}
}
}Требования к исходным изображениям
-
Чтобы ML Kit мог точно распознать текст, на входных изображениях должно быть достаточно пикселей, представляющих текст. Желательно, чтобы каждый символ был не менее 16 x 16 пикселей. Как правило, увеличение размера символов свыше 24 x 24 пикселей не повышает точность распознавания.
Например, изображение размером 640 x 480 хорошо подойдет для сканирования визитной карточки, занимающей всю ширину изображения. Чтобы отсканировать документ, напечатанный на бумаге формата Letter, может потребоваться изображение размером 720 x 1280 пикселей.
-
Нечеткое изображение может повлиять на точность распознавания текста. Если вы не получаете приемлемых результатов, попросите пользователя сделать снимок заново.
-
Если вы распознаете текст в приложении, работающем в реальном времени, учитывайте общие размеры входных изображений. Небольшие изображения обрабатываются быстрее. Чтобы уменьшить задержку, убедитесь, что текст занимает как можно большую часть изображения, и снимайте изображения с более низким разрешением (учитывая требования к точности, упомянутые выше). Подробнее о том, как повысить эффективность…
Советы по повышению эффективности
- Для обработки кадров видео используйте синхронный API детектора
results(in:). Вызовите этот метод из функцииcaptureOutput(_, didOutput:from:)объектаAVCaptureVideoDataOutputSampleBufferDelegate, чтобы синхронно получить результаты из заданного кадра видео. Установите для параметраAVCaptureVideoDataOutputзначениеalwaysDiscardsLateVideoFrames, чтобы ограничить количество вызовов детектора.trueЕсли во время работы детектора станет доступен новый кадр видео, он будет отброшен. - Если вы используете результаты работы детектора для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем отрисуйте изображение и наложите графику за один шаг. Это позволит вам выполнять рендеринг на поверхности экрана только один раз для каждого обработанного входного кадра. Пример можно найти в функции updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.
- Попробуйте снимать с более низким разрешением. Однако также учитывайте требования к размеру изображений в этом API.
- Чтобы избежать снижения производительности, не запускайте одновременно несколько экземпляров
TextRecognizerс разными параметрами скрипта.