Вы можете использовать ML Kit для распознавания текста на изображениях. ML Kit предлагает как универсальный API, подходящий для распознавания текста на изображениях, например, текста уличных вывесок, так и API, оптимизированный для распознавания текста документов. Универсальный API поддерживает как локальную, так и облачную модели. Распознавание текста документов доступно только в облачной модели. Сравнение облачной и локальной моделей см. в обзоре .
Прежде чем начать
- Если вы еще не добавили Firebase в свое приложение, сделайте это, следуя инструкциям в руководстве по началу работы .
-  Включите библиотеки ML Kit в ваш Podfile:pod 'Firebase/MLVision', '6.25.0' # If using an on-device API: pod 'Firebase/MLVisionTextModel', '6.25.0' .xcworkspace.
-  В вашем приложении импортируйте Firebase: Быстрыйimport Firebase Objective-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) Objective-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) Objective-CFIRVisionImage *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 } } - Objective-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 ) - Objective-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 Objective-CFIRVisionImage *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 } Objective-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 } } }
Objective-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 к размерам изображений.
Следующие шаги
- Перед тем как развернуть в рабочей среде приложение, использующее облачный API, следует предпринять некоторые дополнительные шаги для предотвращения и минимизации последствий несанкционированного доступа к API .
Распознавать текст на изображениях документов
Чтобы распознать текст документа, настройте и запустите облачный распознаватель текста документа, как описано ниже.
API распознавания текста документов, описанный ниже, предоставляет интерфейс, предназначенный для более удобной работы с изображениями документов. Однако, если вы предпочитаете интерфейс API разреженного текста, вы можете использовать его для сканирования документов, настроив облачный распознаватель текста на использование модели плотного текста .
Чтобы использовать API распознавания текста документа:
1. Запустите распознаватель текста.
Передайте изображение какUIImage или CMSampleBufferRef в process(_:completion:) VisionDocumentTextRecognizer :-  Получите экземпляр 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) Objective-CFIRVision *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) Objective-CFIRVisionImage *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 } } - Objective-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 ) - Objective-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 Objective-CFIRVisionImage *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 } Objective-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 } } } }
Objective-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; } } } }
Следующие шаги
- Перед тем как развернуть в рабочей среде приложение, использующее облачный API, следует предпринять некоторые дополнительные шаги для предотвращения и минимизации последствий несанкционированного доступа к API .