Распознавайте текст на изображениях с помощью ML Kit на iOS

Вы можете использовать ML Kit для распознавания текста на изображениях или видео, например, текста уличного знака. Основные характеристики этой функции:

API распознавания текста v2
Описание Распознавание текста на изображениях и видео, поддержка латинского, китайского, деванагари, японского и корейского алфавитов, а также широкого спектра языков .
Имена SDK GoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
Выполнение Активы статически привязываются к вашему приложению во время сборки.
Влияние размера приложения Около 38 МБ на скрипт SDK
Производительность В режиме реального времени на большинстве устройств для SDK с латинским алфавитом, на других — медленнее.

Попробуйте это

  • Поэкспериментируйте с образцом приложения , чтобы увидеть пример использования этого API.
  • Попробуйте выполнить код самостоятельно с помощью codelab .

Прежде чем начать

  1. Включите следующие модули ML Kit в свой Podfile:
    # 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'
    
  2. После установки или обновления Pods вашего проекта откройте проект Xcode, используя его .xcworkspace . ML Kit поддерживается в Xcode версии 12.4 или выше.

1. Создайте экземпляр TextRecognizer

Создайте экземпляр TextRecognizer , вызвав +textRecognizer(options:) , передав параметры, относящиеся к SDK, который вы объявили как зависимость выше:

Быстрый

// 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 .

    Быстрый

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-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
      }
    }
          

    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 и ориентацию:

    Быстрый

    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:) :

Быстрый

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 можно получить текст, распознанный в области, и ограничивающие координаты области.

Например:

Быстрый

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 входные изображения должны содержать текст, представленный достаточным количеством пиксельных данных. В идеале каждый символ должен быть размером не менее 16x16 пикселей. Обычно нет никакого преимущества в точности для символов размером более 24x24 пикселей.

    Так, например, изображение 640x480 может хорошо подойти для сканирования визитной карточки, которая занимает всю ширину изображения. Для сканирования документа, напечатанного на бумаге формата Letter, может потребоваться изображение размером 720x1280 пикселей.

  • Плохая фокусировка изображения может повлиять на точность распознавания текста. Если вы не получаете приемлемых результатов, попробуйте попросить пользователя повторно захватить изображение.

  • Если вы распознаете текст в приложении реального времени, вам следует учитывать общие размеры входных изображений. Более мелкие изображения могут обрабатываться быстрее. Чтобы сократить задержку, убедитесь, что текст занимает как можно большую часть изображения, и снимайте изображения с более низким разрешением (помня о требованиях к точности, упомянутых выше). Для получения дополнительной информации см. Советы по повышению производительности .

Советы по повышению производительности

  • Для обработки видеокадров используйте синхронный API results(in:) детектора. Вызовите этот метод из функции captureOutput(_, didOutput:from:) AVCaptureVideoDataOutputSampleBufferDelegate для синхронного получения результатов из заданного видеокадра. Оставьте alwaysDiscardsLateVideoFrames AVCaptureVideoDataOutput как true для ограничения вызовов детектора. Если новый видеокадр станет доступен во время работы детектора, он будет отброшен.
  • Если вы используете вывод детектора для наложения графики на входное изображение, сначала получите результат из ML Kit, затем визуализируйте изображение и наложение за один шаг. Таким образом, вы визуализируете на поверхности дисплея только один раз для каждого обработанного входного кадра. См. пример updatePreviewOverlayViewWithLastFrame в примере быстрого запуска ML Kit.
  • Рассмотрите возможность захвата изображений с более низким разрешением. Однако также помните о требованиях API к размерам изображений.
  • Чтобы избежать потенциального снижения производительности, не запускайте одновременно несколько экземпляров TextRecognizer с разными параметрами скрипта.