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

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

API распознавания текста
Описание Распознавайте текст на латинице в изображениях или видео.
Название SDK GoogleMLKit/TextRecognition (version 2.2.0)
Реализация Активы статически связаны с вашим приложением во время сборки.
Влияние размера приложения Около 20 МБ
Спектакль В режиме реального времени на большинстве устройств.

Попробуйте

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

Прежде чем вы начнете

  1. Включите в свой подфайл следующие модули ML Kit:
    pod 'GoogleMLKit/TextRecognition','2.2.0'
    
    .
  2. После установки или обновления модулей вашего проекта откройте проект Xcode, используя его .xcworkspace . ML Kit поддерживается в Xcode версии 12.4 или выше.

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

Создайте экземпляр TextRecognizer , вызвав +textRecognizer :

Быстрый

let textRecognizer = TextRecognizer.textRecognizer()
      

Цель-C

MLKTextRecognizer *textRecognizer = [MLKTextRecognizer textRecognizer];
      

2. Подготовьте входное изображение

Передайте изображение как UIImage или CMSampleBufferRef в метод TextRecognizer process(_:completion:) :

Создайте объект VisionImage , используя UIImage или CMSampleBuffer .

Если вы используете UIImage , выполните следующие действия:

  • Создайте объект VisionImage с UIImage . Убедитесь, что вы правильно .orientation .

    Быстрый

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

    Цель-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
      }
    }
          

    Цель-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)

    Цель-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
}

Цель-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
        }
    }
}

Цель-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х16 пикселей. Как правило, символы размером более 24x24 пикселей не улучшают точность.

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

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

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

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

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