Text in Bildern mit ML Kit unter iOS erkennen

Sie können ML Kit verwenden, um Text in Bildern oder Videos zu erkennen, z. B. auf einem Straßenschild. Diese Funktion zeichnet sich durch folgende Eigenschaften aus:

Texterkennung API v2
BeschreibungErkennt Text in Bildern oder Videos, Unterstützung von lateinischen, chinesischen, Devanagari-, japanischen und koreanischen Skripts sowie verschiedenen Sprachen.
SDK-NamenGoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
ImplementierungAssets werden bei der Erstellung statisch mit Ihrer App verknüpft
Auswirkungen auf die App-GrößeEtwa 38 MB pro Skript-SDK
LeistungAuf den meisten Geräten läuft das SDK in Echtzeit für das Latin Script SDK, bei anderen langsamer.

Ausprobieren

  • Probieren Sie die Beispiel-App aus, um sich ein Beispiel für die Verwendung dieser API anzusehen.
  • Probieren Sie den Code selbst mit dem Codelab aus.

Hinweis

  1. Fügen Sie die folgenden ML Kit-Pods in Ihre Podfile-Datei ein:
    # To recognize Latin script
    pod 'GoogleMLKit/TextRecognition', '3.2.0'
    # To recognize Chinese script
    pod 'GoogleMLKit/TextRecognitionChinese', '3.2.0'
    # To recognize Devanagari script
    pod 'GoogleMLKit/TextRecognitionDevanagari', '3.2.0'
    # To recognize Japanese script
    pod 'GoogleMLKit/TextRecognitionJapanese', '3.2.0'
    # To recognize Korean script
    pod 'GoogleMLKit/TextRecognitionKorean', '3.2.0'
    
  2. Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, öffnen Sie das Xcode-Projekt mit seinem .xcworkspace. ML Kit wird ab Xcode Version 12.4 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, die 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 Image als UIImage oder CMSampleBufferRef an die Methode process(_:completion:) von TextRecognizer:

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

Wenn Sie UIImage verwenden, gehen Sie so vor:

  • Erstellen Sie mit dem UIImage ein VisionImage-Objekt. 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 CMSampleBuffer verwenden, gehen Sie so vor:

  • Gib die Ausrichtung der Bilddaten an, die in CMSampleBuffer enthalten sind.

    So erhalten Sie die Bildausrichtung:

    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 Objekt CMSampleBuffer 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 dann das Bild 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. Extrahiert Text aus Blöcken für erkannten Text

Wenn die Texterkennung erfolgreich war, wird ein Text-Objekt zurückgegeben. Ein Text-Objekt enthält den vollständigen Text, der im Bild erkannt wurde, und keine oder mehrere TextBlock-Objekte.

Jeder TextBlock steht für einen rechteckigen Textblock, der keine oder mehrere TextLine-Objekte enthält. Jedes TextLine-Objekt enthält keine oder mehrere 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 das ML Kit Text korrekt erkennt, müssen Eingabebilder Text enthalten, der durch genügend Pixeldaten dargestellt wird. Idealerweise sollte jedes Zeichen mindestens 16 x 16 Pixel groß sein. Im Allgemeinen besteht kein Vorteil, wenn die Zeichen größer als 24 x 24 Pixel sind.

    So kann beispielsweise ein Bild mit 640 × 480 Pixeln geeignet sein, eine Visitenkarte zu scannen, die die volle Breite des Bildes einnimmt. Zum Scannen eines Dokuments, das auf Papier im Briefformat gedruckt wird, ist möglicherweise ein Bild mit 720 × 1.280 Pixeln erforderlich.

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

  • Wenn Sie Text in einer Echtzeitanwendung erkennen, sollten Sie die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Damit die Latenz verringert wird, muss der Text einen möglichst großen Teil des Bilds aufnehmen und dabei Bilder mit einer geringeren Auflösung aufnehmen. (Unter Beachtung der oben genannten Anforderungen an die Genauigkeit) Weitere Informationen findest du unter Tipps zur Verbesserung der Leistung.

Tipps zum Verbessern der Leistung

  • Verwenden Sie zum Verarbeiten von Videoframes die results(in:) synchrone API des Detektors. Rufen Sie diese Methode aus der Funktion captureOutput(_, didOutput:from:) von AVCaptureVideoDataOutputSampleBufferDelegate auf, um Ergebnisse aus dem angegebenen Videoframe synchron zu erhalten. Behalten Sie die alwaysDiscardsLateVideoFrames von AVCaptureVideoDataOutput als true, um Aufrufe an den Detektor zu drosseln. Wenn während der Ausführung des Detektors ein neuer Videoframe verfügbar ist, wird er gelöscht.
  • Wenn Sie die Ausgabe des Detektors verwenden, um Grafiken auf dem Eingabebild einzublenden, erhalten Sie zuerst das Ergebnis aus ML Kit und rendern Sie dann das Bild und das Overlay in einem einzigen Schritt. Dadurch wird die Darstellung für jeden verarbeiteten Eingabeframe nur einmal auf der Anzeigeoberfläche gerendert. Ein Beispiel finden Sie im Beispiel der ML Kit-Kurzanleitung unter updatePreviewOverlayViewWithLastFrame.
  • Du kannst Bilder mit einer geringeren Auflösung aufnehmen. Beachten Sie jedoch auch die Anforderungen an die Bildabmessungen dieser API.
  • Damit die Leistung nicht beeinträchtigt wird, sollten Sie nicht mehrere TextRecognizer-Instanzen mit unterschiedlichen Skriptoptionen gleichzeitig ausführen.