Text in Bildern mit ML Kit unter iOS erkennen

Mit ML Kit können Sie Text in Bildern oder Videos erkennen, z. B. den Text eines Straßenschilds. Die wichtigsten Merkmale dieser Funktion sind:

Text Recognition v2 API
BeschreibungErkennt Text in Bildern oder Videos, unterstützt lateinische, chinesische, Devanagari-, japanische und koreanische Schriftzeichen und eine Vielzahl von Sprachen.
SDK-NamenGoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
ImplementierungAssets werden beim Erstellen statisch mit Ihrer App verknüpft.
Auswirkungen auf die App-GrößeEtwa 38 MB pro Skript-SDK
LeistungEchtzeit auf den meisten Geräten für das SDK für lateinische Schrift, langsamer für andere.

Jetzt ausprobieren

  • In der Beispiel-App finden Sie ein Beispiel für die Verwendung dieser API.
  • Probieren Sie den Code im Codelab selbst aus.

Hinweis

  1. Fügen Sie die folgenden ML Kit-Pods in Ihre Podfile-Datei ein:
    # 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. Öffnen Sie nach der Installation oder Aktualisierung der Pods Ihres Projekts Ihr Xcode-Projekt mit der Datei .xcworkspace. ML Kit wird in Xcode-Version 12.4 oder höher unterstützt.

1. Instanz von TextRecognizer erstellen

Erstellen Sie eine Instanz von TextRecognizer, indem Sie +textRecognizer(options:) aufrufen und die Optionen für das SDK übergeben, das Sie oben als Abhängigkeit deklariert haben:

Swift

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

Übergeben Sie das Bild als UIImage oder CMSampleBufferRef an die Methode process(_:completion:) von TextRecognizer:

Erstellen Sie ein VisionImage-Objekt mit einem UIImage oder einem CMSampleBuffer.

Wenn Sie ein UIImage verwenden, gehen Sie so vor:

  • Erstellen Sie ein VisionImage-Objekt mit dem UIImage. Achten Sie darauf, die richtige .orientation anzugeben.

    Swift

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

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Wenn Sie ein CMSampleBuffer verwenden, gehen Sie so vor:

  • Geben Sie die Ausrichtung der Bilddaten im CMSampleBuffer an.

    So rufen Sie die Bildausrichtung ab:

    Swift

    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;
      }
    }
          
  • Erstellen Sie ein VisionImage-Objekt mit dem CMSampleBuffer-Objekt und der Ausrichtung:

    Swift

    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. Bild verarbeiten

Übergeben Sie das Bild dann an die Methode process(_:completion:):

Swift

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 aus Blöcken mit erkanntem Text extrahieren

Wenn der Texterkennungsvorgang erfolgreich ist, wird ein Text-Objekt zurückgegeben. Ein Text-Objekt enthält den vollständigen im Bild erkannten Text und null oder mehr TextBlock-Objekte.

Jeder TextBlock stellt einen rechteckigen Textblock dar, der null oder mehr TextLine-Objekte enthält. Jedes TextLine-Objekt enthält null oder mehr TextElement-Objekte, die Wörter und wortähnliche Entitäten wie Datumsangaben und Zahlen darstellen.

Für jedes TextBlock-, TextLine- und TextElement-Objekt können Sie den in der Region erkannten Text und die Begrenzungskoordinaten der Region abrufen.

Beispiel:

Swift

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

Richtlinien für Eingabebilder

  • Damit ML Kit Text genau erkennen kann, müssen Eingabebilder Text enthalten, der durch ausreichende Pixeldaten dargestellt wird. Idealerweise sollte jedes Zeichen mindestens 16 × 16 Pixel groß sein. In der Regel gibt es keinen Genauigkeitsvorteil, wenn Zeichen größer als 24 × 24 Pixel sind.

    So kann beispielsweise ein Bild mit 640 x 480 Pixeln gut funktionieren, um eine Visitenkarte zu scannen, die die gesamte Breite des Bildes einnimmt. Zum Scannen eines Dokuments, das auf Papier im Letter-Format gedruckt wurde, ist möglicherweise ein Bild mit 720 × 1.280 Pixeln erforderlich.

  • Ein schlechter Fokus kann die Genauigkeit der Texterkennung beeinträchtigen. Wenn Sie keine akzeptablen Ergebnisse erhalten, bitten Sie den Nutzer, das Bild noch einmal aufzunehmen.

  • Wenn Sie Text in einer Echtzeitanwendung erkennen, sollten Sie die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu verringern, sollte der Text so viel wie möglich vom Bild einnehmen. Nehmen Sie Bilder mit niedrigeren Auflösungen auf (beachten Sie dabei die oben genannten Genauigkeitsanforderungen). Weitere Informationen finden Sie unter Tipps zur Leistungsverbesserung.

Tipps zur Leistungsverbesserung

  • Verwenden Sie zum Verarbeiten von Videoframes die synchrone API results(in:) des Detektors. Rufen Sie diese Methode über die Funktion captureOutput(_, didOutput:from:) des AVCaptureVideoDataOutputSampleBufferDelegate auf, um synchron Ergebnisse aus dem angegebenen Videoframe abzurufen. Behalten Sie AVCaptureVideoDataOutput von alwaysDiscardsLateVideoFrames als true bei, um Aufrufe an den Detektor zu drosseln. Wenn ein neuer Videoframe verfügbar wird, während der Detektor ausgeführt wird, wird er verworfen.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken über das Eingabebild zu legen, rufen Sie zuerst das Ergebnis aus ML Kit ab und rendern Sie dann das Bild und das Overlay in einem einzigen Schritt. Dadurch wird für jeden verarbeiteten Eingabeframe nur einmal auf der Anzeigeoberfläche gerendert. Ein Beispiel finden Sie unter updatePreviewOverlayViewWithLastFrame im ML Kit-Kurzanleitungsbeispiel.
  • Versuchen Sie, Bilder mit einer niedrigeren Auflösung aufzunehmen. Beachten Sie jedoch auch die Anforderungen dieser API an die Bildabmessungen.
  • Führen Sie nicht mehrere TextRecognizer-Instanzen mit unterschiedlichen Skriptoptionen gleichzeitig aus, um potenzielle Leistungseinbußen zu vermeiden.