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

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

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

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

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

  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. После установки или обновления модулей вашего проекта откройте проект 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 для синхронного получения результатов из заданного видеокадра. Для ограничения вызовов детектора установите true alwaysDiscardsLateVideoFrames класса AVCaptureVideoDataOutput . Если новый видеокадр станет доступен во время работы детектора, он будет отброшен.
  • Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат из ML Kit, а затем визуализируйте изображение и наложение за один шаг. Таким образом, визуализация на поверхности дисплея выполняется только один раз для каждого обработанного входного кадра. См. пример updatePreviewOverlayViewWithLastFrame в кратком руководстве по ML Kit.
  • Рассмотрите возможность захвата изображений в более низком разрешении. Однако учитывайте требования API к размерам изображений.
  • Чтобы избежать потенциального снижения производительности, не запускайте несколько экземпляров TextRecognizer с различными параметрами скрипта одновременно.