Вы можете использовать ML Kit для распознавания текста на изображениях. ML Kit имеет как API общего назначения, подходящий для распознавания текста на изображениях, например текста уличного знака, так и API, оптимизированный для распознавания текста документов. API общего назначения имеет модели как на устройстве, так и в облаке. Распознавание текста документа доступно только в виде облачной модели. См. обзор для сравнения облачной модели и модели на устройстве.
Прежде чем вы начнете
- Если вы еще не добавили Firebase в свое приложение, сделайте это, следуя инструкциям в руководстве по началу работы.
- Включите библиотеки ML Kit в свой подфайл:
pod 'Firebase/MLVision', '6.25.0' # If using an on-device API: pod 'Firebase/MLVisionTextModel', '6.25.0'
После установки или обновления подов вашего проекта обязательно откройте проект Xcode, используя его.xcworkspace
. - В вашем приложении импортируйте Firebase:
Быстрый
import Firebase
Цель-C
@import Firebase;
Если вы хотите использовать облачную модель и еще не включили облачные API для своего проекта, сделайте это сейчас:
- Откройте страницу API ML Kit в консоли Firebase.
Если вы еще не обновили свой проект до тарифного плана Blaze, нажмите « Обновить », чтобы сделать это. (Вам будет предложено обновиться, только если ваш проект не входит в план Blaze.)
Только проекты уровня Blaze могут использовать облачные API.
- Если облачные API еще не включены, щелкните Включить облачные API .
Если вы хотите использовать только модель на устройстве, вы можете пропустить этот шаг.
Теперь вы готовы начать распознавать текст на изображениях.
Инструкции по входному изображению
Чтобы ML Kit точно распознавал текст, входные изображения должны содержать текст, представленный достаточным количеством данных пикселей. В идеале для латинского текста размер каждого символа должен быть не менее 16x16 пикселей. Для текста на китайском, японском и корейском языках (поддерживается только облачными API) размер каждого символа должен составлять 24x24 пикселя. Для всех языков, как правило, нет преимущества в точности для символов, размер которых превышает 24x24 пикселя.
Так, например, изображение размером 640x480 может хорошо подойти для сканирования визитной карточки, занимающей всю ширину изображения. Для сканирования документа, напечатанного на бумаге формата Letter, может потребоваться изображение размером 720x1280 пикселей.
Плохая фокусировка изображения может снизить точность распознавания текста. Если вы не получаете приемлемых результатов, попробуйте попросить пользователя повторно захватить изображение.
Если вы распознаете текст в приложении реального времени, вы также можете учитывать общие размеры входных изображений. Меньшие изображения могут обрабатываться быстрее, поэтому, чтобы уменьшить задержку, захватывайте изображения с более низким разрешением (с учетом приведенных выше требований к точности) и следите за тем, чтобы текст занимал как можно большую часть изображения. Также см. Советы по повышению производительности в реальном времени .
Распознавать текст на изображениях
Чтобы распознать текст на изображении с помощью встроенной в устройство или облачной модели, запустите распознаватель текста, как описано ниже.
1. Запустите распознаватель текста
Передайте изображение как `UIImage` или `CMSampleBufferRef` в метод `process(_:completion:)` `VisionTextRecognizer`:- Получите экземпляр
VisionTextRecognizer
, вызвавonDeviceTextRecognizer
илиcloudTextRecognizer
:Быстрый
Чтобы использовать модель на устройстве:
let vision = Vision.vision() let textRecognizer = vision.onDeviceTextRecognizer()
Чтобы использовать облачную модель:
let vision = Vision.vision() let textRecognizer = vision.cloudTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudTextRecognizer(options: options)
Цель-C
Чтобы использовать модель на устройстве:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision onDeviceTextRecognizer];
Чтобы использовать облачную модель:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudTextRecognizerOptions *options = [[FIRVisionCloudTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizerWithOptions: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;
- При необходимости поверните изображение так, чтобы его свойство
- Затем передайте изображение методу
process(_:completion:)
:Быстрый
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Цель-C
[textRecognizer processImage:image completion:^(FIRVisionText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Извлечь текст из блоков распознанного текста
Если операция распознавания текста завершится успешно, она вернет объект [`VisionText`][VisionText]. Объект `VisionText` содержит полный текст, распознанный на изображении, и ноль или более объектов [`VisionTextBlock`][VisionTextBlock]. Каждый `VisionTextBlock` представляет собой прямоугольный блок текста, который содержит ноль или более объектов [`VisionTextLine`][VisionTextLine]. Каждый объект `VisionTextLine` содержит ноль или более объектов [`VisionTextElement`][VisionTextElement], которые представляют слова и подобные им объекты (даты, числа и т. д.). Для каждого объекта `VisionTextBlock`, `VisionTextLine` и `VisionTextElement` вы можете получить текст, распознанный в регионе, и ограничивающие координаты региона. Например:Быстрый
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockLanguages = block.recognizedLanguages let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for line in block.lines { let lineText = line.text let lineConfidence = line.confidence let lineLanguages = line.recognizedLanguages let lineCornerPoints = line.cornerPoints let lineFrame = line.frame for element in line.elements { let elementText = element.text let elementConfidence = element.confidence let elementLanguages = element.recognizedLanguages let elementCornerPoints = element.cornerPoints let elementFrame = element.frame } } }
Цель-C
NSString *resultText = result.text; for (FIRVisionTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages; NSArray<NSValue *> *blockCornerPoints = block.cornerPoints; CGRect blockFrame = block.frame; for (FIRVisionTextLine *line in block.lines) { NSString *lineText = line.text; NSNumber *lineConfidence = line.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages; NSArray<NSValue *> *lineCornerPoints = line.cornerPoints; CGRect lineFrame = line.frame; for (FIRVisionTextElement *element in line.elements) { NSString *elementText = element.text; NSNumber *elementConfidence = element.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *elementLanguages = element.recognizedLanguages; NSArray<NSValue *> *elementCornerPoints = element.cornerPoints; CGRect elementFrame = element.frame; } } }
Советы по улучшению производительности в реальном времени
Если вы хотите использовать модель на устройстве для распознавания текста в приложении реального времени, следуйте этим рекомендациям для достижения наилучшей частоты кадров:
- Дроссель вызовов распознавателя текста. Если во время работы распознавателя текста становится доступным новый видеокадр, удалите его.
- Если вы используете выходные данные распознавателя текста для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем выполните визуализацию изображения и наложение за один шаг. Поступая таким образом, вы визуализируете на поверхность дисплея только один раз для каждого входного кадра. В качестве примера см. классы previewOverlayView и FIRDetectionOverlayView в демонстрационном образце приложения.
- Рассмотрите возможность захвата изображений с более низким разрешением. Однако также имейте в виду требования этого API к размеру изображения.
Следующие шаги
- Перед развертыванием в рабочей среде приложения, использующего Cloud API, необходимо предпринять дополнительные шаги, чтобы предотвратить и смягчить последствия несанкционированного доступа к API .
Распознавать текст на изображениях документов
Чтобы распознать текст документа, настройте и запустите облачный распознаватель текста документа, как описано ниже.
API распознавания текста документов, описанный ниже, предоставляет интерфейс, предназначенный для более удобной работы с изображениями документов. Однако, если вы предпочитаете интерфейс, предоставляемый API разреженного текста, вы можете использовать его вместо этого для сканирования документов, настроив облачный распознаватель текста на использование модели плотного текста .
Чтобы использовать API распознавания текста документа:
1. Запустите распознаватель текста
Передайте изображение какUIImage
или CMSampleBufferRef
в метод VisionDocumentTextRecognizer
process(_:completion:)
:- Получите экземпляр
VisionDocumentTextRecognizer
, вызвавcloudDocumentTextRecognizer
:Быстрый
let vision = Vision.vision() let textRecognizer = vision.cloudDocumentTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudDocumentTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudDocumentTextRecognizer(options: options)
Цель-C
FIRVision *vision = [FIRVision vision]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudDocumentTextRecognizerOptions *options = [[FIRVisionCloudDocumentTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizerWithOptions: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;
- При необходимости поверните изображение так, чтобы его свойство
- Затем передайте изображение методу
process(_:completion:)
:Быстрый
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Цель-C
[textRecognizer processImage:image completion:^(FIRVisionDocumentText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Извлечь текст из блоков распознанного текста
Если операция распознавания текста завершится успешно, она вернет объектVisionDocumentText
. Объект VisionDocumentText
содержит полный текст, распознанный на изображении, и иерархию объектов, отражающих структуру распознанного документа: Для каждого VisionDocumentTextBlock
, VisionDocumentTextParagraph
, VisionDocumentTextWord
и VisionDocumentTextSymbol
можно получить текст, распознаваемый в регионе, и ограничивающие координаты региона.
Например:
Быстрый
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockRecognizedLanguages = block.recognizedLanguages let blockBreak = block.recognizedBreak let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for paragraph in block.paragraphs { let paragraphText = paragraph.text let paragraphConfidence = paragraph.confidence let paragraphRecognizedLanguages = paragraph.recognizedLanguages let paragraphBreak = paragraph.recognizedBreak let paragraphCornerPoints = paragraph.cornerPoints let paragraphFrame = paragraph.frame for word in paragraph.words { let wordText = word.text let wordConfidence = word.confidence let wordRecognizedLanguages = word.recognizedLanguages let wordBreak = word.recognizedBreak let wordCornerPoints = word.cornerPoints let wordFrame = word.frame for symbol in word.symbols { let symbolText = symbol.text let symbolConfidence = symbol.confidence let symbolRecognizedLanguages = symbol.recognizedLanguages let symbolBreak = symbol.recognizedBreak let symbolCornerPoints = symbol.cornerPoints let symbolFrame = symbol.frame } } } }
Цель-C
NSString *resultText = result.text; for (FIRVisionDocumentTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockRecognizedLanguages = block.recognizedLanguages; FIRVisionTextRecognizedBreak *blockBreak = block.recognizedBreak; CGRect blockFrame = block.frame; for (FIRVisionDocumentTextParagraph *paragraph in block.paragraphs) { NSString *paragraphText = paragraph.text; NSNumber *paragraphConfidence = paragraph.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *paragraphRecognizedLanguages = paragraph.recognizedLanguages; FIRVisionTextRecognizedBreak *paragraphBreak = paragraph.recognizedBreak; CGRect paragraphFrame = paragraph.frame; for (FIRVisionDocumentTextWord *word in paragraph.words) { NSString *wordText = word.text; NSNumber *wordConfidence = word.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *wordRecognizedLanguages = word.recognizedLanguages; FIRVisionTextRecognizedBreak *wordBreak = word.recognizedBreak; CGRect wordFrame = word.frame; for (FIRVisionDocumentTextSymbol *symbol in word.symbols) { NSString *symbolText = symbol.text; NSNumber *symbolConfidence = symbol.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *symbolRecognizedLanguages = symbol.recognizedLanguages; FIRVisionTextRecognizedBreak *symbolBreak = symbol.recognizedBreak; CGRect symbolFrame = symbol.frame; } } } }
Следующие шаги
- Перед развертыванием в рабочей среде приложения, использующего Cloud API, необходимо предпринять дополнительные шаги, чтобы предотвратить и смягчить последствия несанкционированного доступа к API .