Sie können ML Kit verwenden, um Text in Bildern zu erkennen. ML Kit verfügt sowohl über eine Allzweck-API, die zum Erkennen von Text in Bildern geeignet ist, wie z. B. den Text eines Straßenschilds, als auch über eine API, die zum Erkennen des Texts von Dokumenten optimiert ist. Die Allzweck-API hat sowohl geräteinterne als auch cloudbasierte Modelle. Die Dokumententexterkennung ist nur als Cloud-basiertes Modell verfügbar. In der Übersicht finden Sie einen Vergleich der Cloud- und On-Device-Modelle.
Bevor Sie beginnen
- Wenn Sie Ihrer App Firebase noch nicht hinzugefügt haben, befolgen Sie dazu die Schritte im Leitfaden „Erste Schritte“ .
- Schließen Sie die ML Kit-Bibliotheken in Ihre Poddatei ein:
pod 'Firebase/MLVision', '6.25.0' # If using an on-device API: pod 'Firebase/MLVisionTextModel', '6.25.0'
Nachdem Sie die Pods Ihres Projekts installiert oder aktualisiert haben, müssen Sie Ihr Xcode-Projekt mit seiner.xcworkspace
. - Importieren Sie in Ihrer App Firebase:
Schnell
import Firebase
Ziel c
@import Firebase;
Wenn Sie das Cloud-basierte Modell verwenden möchten und die Cloud-basierten APIs für Ihr Projekt noch nicht aktiviert haben, tun Sie dies jetzt:
- Öffnen Sie die Seite ML Kit APIs der Firebase-Konsole.
Wenn Sie Ihr Projekt noch nicht auf einen Blaze-Preisplan aktualisiert haben, klicken Sie dazu auf Upgrade . (Sie werden nur dann zum Upgrade aufgefordert, wenn Ihr Projekt nicht im Blaze-Plan enthalten ist.)
Nur Projekte auf Blaze-Ebene können Cloud-basierte APIs verwenden.
- Wenn Cloud-basierte APIs nicht bereits aktiviert sind, klicken Sie auf Cloud-basierte APIs aktivieren .
Wenn Sie nur das On-Device-Modell verwenden möchten, können Sie diesen Schritt überspringen.
Jetzt können Sie mit dem Erkennen von Text in Bildern beginnen.
Bildrichtlinien eingeben
Damit ML Kit Text genau erkennen kann, müssen Eingabebilder Text enthalten, der durch ausreichend Pixeldaten dargestellt wird. Idealerweise sollte bei lateinischem Text jedes Zeichen mindestens 16 x 16 Pixel groß sein. Bei chinesischem, japanischem und koreanischem Text (wird nur von den Cloud-basierten APIs unterstützt) sollte jedes Zeichen 24 x 24 Pixel groß sein. Für alle Sprachen gibt es im Allgemeinen keinen Genauigkeitsvorteil, wenn Zeichen größer als 24 x 24 Pixel sind.
Ein Bild im Format 640 x 480 eignet sich beispielsweise gut zum Scannen einer Visitenkarte, die die gesamte Breite des Bildes einnimmt. Zum Scannen eines auf Papier im Letter-Format gedruckten Dokuments ist möglicherweise ein Bild mit 720 x 1280 Pixel erforderlich.
Ein schlechter Bildfokus kann die Genauigkeit der Texterkennung beeinträchtigen. Wenn Sie keine akzeptablen Ergebnisse erzielen, bitten Sie den Benutzer, das Bild erneut aufzunehmen.
Wenn Sie Text in einer Echtzeitanwendung erkennen, sollten Sie möglicherweise auch die Gesamtabmessungen der Eingabebilder berücksichtigen. Kleinere Bilder können schneller verarbeitet werden. Um die Latenz zu reduzieren, erfassen Sie Bilder mit niedrigeren Auflösungen (unter Berücksichtigung der oben genannten Genauigkeitsanforderungen) und stellen Sie sicher, dass der Text so viel wie möglich vom Bild einnimmt. Siehe auch Tipps zur Verbesserung der Echtzeitleistung .
Text in Bildern erkennen
Führen Sie die Texterkennung wie unten beschrieben aus, um Text in einem Bild entweder mit einem geräteinternen oder einem Cloud-basierten Modell zu erkennen.
1. Führen Sie die Texterkennung aus
Übergeben Sie das Bild als `UIImage` oder `CMSampleBufferRef` an die `process(_:completion:)`-Methode von `VisionTextRecognizer`:- Rufen Sie eine Instanz von
VisionTextRecognizer
, indem Sie entwederonDeviceTextRecognizer
odercloudTextRecognizer
:Schnell
So verwenden Sie das On-Device-Modell:
let vision = Vision.vision() let textRecognizer = vision.onDeviceTextRecognizer()
So verwenden Sie das Cloud-Modell:
let vision = Vision.vision() let textRecognizer = vision.cloudTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudTextRecognizer(options: options)
Ziel c
So verwenden Sie das On-Device-Modell:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision onDeviceTextRecognizer];
So verwenden Sie das Cloud-Modell:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudTextRecognizerOptions *options = [[FIRVisionCloudTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizerWithOptions:options];
Erstellen Sie ein
VisionImage
Objekt mit einemUIImage
oder einemCMSampleBufferRef
.So verwenden Sie ein
UIImage
:- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
imageOrientation
.up
. - Erstellen Sie ein
VisionImage
-Objekt mit dem korrekt gedrehtenUIImage
. Geben Sie keine Rotationsmetadaten an – der Standardwert.topLeft
muss verwendet werden.Schnell
let image = VisionImage(image: uiImage)
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
So verwenden Sie eine
CMSampleBufferRef
:Erstellen Sie ein
VisionImageMetadata
Objekt, das die Ausrichtung der imCMSampleBufferRef
Puffer enthaltenen Bilddaten angibt.So erhalten Sie die Bildausrichtung:
Schnell
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Ziel c
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Erstellen Sie dann das Metadatenobjekt:
Schnell
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Ziel c
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Erstellen Sie ein
VisionImage
Objekt mit demCMSampleBufferRef
Objekt und den Rotationsmetadaten:Schnell
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
- Übergeben Sie das Bild dann an die Methode
process(_:completion:)
:Schnell
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Ziel c
[textRecognizer processImage:image completion:^(FIRVisionText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Text aus erkannten Textblöcken extrahieren
Wenn die Texterkennungsoperation erfolgreich ist, wird ein [`VisionText`][VisionText]-Objekt zurückgegeben. Ein `VisionText`-Objekt enthält den im Bild erkannten Volltext und null oder mehr [`VisionTextBlock`][VisionTextBlock]-Objekte. Jeder `VisionTextBlock` stellt einen rechteckigen Textblock dar, der null oder mehr [`VisionTextLine`][VisionTextLine]-Objekte enthält. Jedes `VisionTextLine`-Objekt enthält null oder mehr [`VisionTextElement`][VisionTextElement]-Objekte, die Wörter und wortähnliche Einheiten (Datum, Zahlen usw.) darstellen. Für jedes „VisionTextBlock“-, „VisionTextLine“- und „VisionTextElement“-Objekt können Sie den in der Region erkannten Text und die Begrenzungskoordinaten der Region abrufen. Zum Beispiel:Schnell
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockLanguages = block.recognizedLanguages let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for line in block.lines { let lineText = line.text let lineConfidence = line.confidence let lineLanguages = line.recognizedLanguages let lineCornerPoints = line.cornerPoints let lineFrame = line.frame for element in line.elements { let elementText = element.text let elementConfidence = element.confidence let elementLanguages = element.recognizedLanguages let elementCornerPoints = element.cornerPoints let elementFrame = element.frame } } }
Ziel c
NSString *resultText = result.text; for (FIRVisionTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages; NSArray<NSValue *> *blockCornerPoints = block.cornerPoints; CGRect blockFrame = block.frame; for (FIRVisionTextLine *line in block.lines) { NSString *lineText = line.text; NSNumber *lineConfidence = line.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages; NSArray<NSValue *> *lineCornerPoints = line.cornerPoints; CGRect lineFrame = line.frame; for (FIRVisionTextElement *element in line.elements) { NSString *elementText = element.text; NSNumber *elementConfidence = element.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *elementLanguages = element.recognizedLanguages; NSArray<NSValue *> *elementCornerPoints = element.cornerPoints; CGRect elementFrame = element.frame; } } }
Tipps zur Verbesserung der Echtzeitleistung
Wenn Sie das Modell auf dem Gerät verwenden möchten, um Text in einer Echtzeitanwendung zu erkennen, befolgen Sie diese Richtlinien, um die besten Frameraten zu erzielen:
- Aufrufe an die Texterkennung drosseln. Wenn ein neuer Videoframe verfügbar wird, während die Texterkennung ausgeführt wird, löschen Sie den Frame.
- Wenn Sie die Ausgabe der Texterkennung verwenden, um Grafiken über das Eingabebild zu legen, rufen Sie zuerst das Ergebnis von ML Kit ab, rendern Sie dann das Bild und überlagern Sie es in einem einzigen Schritt. Dadurch rendern Sie für jeden Eingabeframe nur einmal auf der Anzeigeoberfläche. Ein Beispiel finden Sie in den Klassen previewOverlayView und FIRDetectionOverlayView in der Showcase-Beispiel-App.
- Erwägen Sie, Bilder mit einer niedrigeren Auflösung aufzunehmen. Beachten Sie jedoch auch die Anforderungen an die Bildgröße dieser API.
Nächste Schritte
- Bevor Sie eine App, die eine Cloud-API verwendet, für die Produktion bereitstellen, sollten Sie einige zusätzliche Schritte unternehmen, um die Auswirkungen eines nicht autorisierten API-Zugriffs zu verhindern und abzumildern .
Erkennen Sie Text in Bildern von Dokumenten
Um den Text eines Dokuments zu erkennen, konfigurieren und führen Sie die cloudbasierte Texterkennung für Dokumente wie unten beschrieben aus.
Die unten beschriebene Dokumententexterkennungs-API stellt eine Schnittstelle bereit, die für das Arbeiten mit Bildern von Dokumenten bequemer sein soll. Wenn Sie jedoch die von der Sparse-Text-API bereitgestellte Schnittstelle bevorzugen, können Sie sie stattdessen zum Scannen von Dokumenten verwenden, indem Sie die Cloud-Texterkennung für die Verwendung des Dense-Text-Modells konfigurieren.
So verwenden Sie die Dokumenttexterkennungs-API:
1. Führen Sie die Texterkennung aus
Übergeben Sie das Bild alsUIImage
oder CMSampleBufferRef
an die VisionDocumentTextRecognizer
process(_:completion:)
von VisionDocumentTextRecognizer :- Rufen Sie eine Instanz von
VisionDocumentTextRecognizer
, indemcloudDocumentTextRecognizer
aufrufen:Schnell
let vision = Vision.vision() let textRecognizer = vision.cloudDocumentTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudDocumentTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudDocumentTextRecognizer(options: options)
Ziel c
FIRVision *vision = [FIRVision vision]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudDocumentTextRecognizerOptions *options = [[FIRVisionCloudDocumentTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizerWithOptions:options];
Erstellen Sie ein
VisionImage
Objekt mit einemUIImage
oder einemCMSampleBufferRef
.So verwenden Sie ein
UIImage
:- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
imageOrientation
.up
. - Erstellen Sie ein
VisionImage
-Objekt mit dem korrekt gedrehtenUIImage
. Geben Sie keine Rotationsmetadaten an – der Standardwert.topLeft
muss verwendet werden.Schnell
let image = VisionImage(image: uiImage)
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
So verwenden Sie eine
CMSampleBufferRef
:Erstellen Sie ein
VisionImageMetadata
Objekt, das die Ausrichtung der imCMSampleBufferRef
Puffer enthaltenen Bilddaten angibt.So erhalten Sie die Bildausrichtung:
Schnell
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Ziel c
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Erstellen Sie dann das Metadatenobjekt:
Schnell
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Ziel c
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Erstellen Sie ein
VisionImage
Objekt mit demCMSampleBufferRef
Objekt und den Rotationsmetadaten:Schnell
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Ziel c
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Drehen Sie das Bild bei Bedarf so, dass seine Eigenschaft
- Übergeben Sie das Bild dann an die Methode
process(_:completion:)
:Schnell
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Ziel c
[textRecognizer processImage:image completion:^(FIRVisionDocumentText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Text aus erkannten Textblöcken extrahieren
Wenn der Texterkennungsvorgang erfolgreich ist, wird einVisionDocumentText
Objekt zurückgegeben. Ein VisionDocumentText
Objekt enthält den im Bild erkannten vollständigen Text und eine Hierarchie von Objekten, die die Struktur des erkannten Dokuments widerspiegeln: Für jedes VisionDocumentTextBlock
-, VisionDocumentTextParagraph
-, VisionDocumentTextWord
- und VisionDocumentTextSymbol
-Objekt können Sie den in der Region erkannten Text und die Begrenzungskoordinaten der Region abrufen.
Zum Beispiel:
Schnell
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockRecognizedLanguages = block.recognizedLanguages let blockBreak = block.recognizedBreak let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for paragraph in block.paragraphs { let paragraphText = paragraph.text let paragraphConfidence = paragraph.confidence let paragraphRecognizedLanguages = paragraph.recognizedLanguages let paragraphBreak = paragraph.recognizedBreak let paragraphCornerPoints = paragraph.cornerPoints let paragraphFrame = paragraph.frame for word in paragraph.words { let wordText = word.text let wordConfidence = word.confidence let wordRecognizedLanguages = word.recognizedLanguages let wordBreak = word.recognizedBreak let wordCornerPoints = word.cornerPoints let wordFrame = word.frame for symbol in word.symbols { let symbolText = symbol.text let symbolConfidence = symbol.confidence let symbolRecognizedLanguages = symbol.recognizedLanguages let symbolBreak = symbol.recognizedBreak let symbolCornerPoints = symbol.cornerPoints let symbolFrame = symbol.frame } } } }
Ziel c
NSString *resultText = result.text; for (FIRVisionDocumentTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockRecognizedLanguages = block.recognizedLanguages; FIRVisionTextRecognizedBreak *blockBreak = block.recognizedBreak; CGRect blockFrame = block.frame; for (FIRVisionDocumentTextParagraph *paragraph in block.paragraphs) { NSString *paragraphText = paragraph.text; NSNumber *paragraphConfidence = paragraph.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *paragraphRecognizedLanguages = paragraph.recognizedLanguages; FIRVisionTextRecognizedBreak *paragraphBreak = paragraph.recognizedBreak; CGRect paragraphFrame = paragraph.frame; for (FIRVisionDocumentTextWord *word in paragraph.words) { NSString *wordText = word.text; NSNumber *wordConfidence = word.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *wordRecognizedLanguages = word.recognizedLanguages; FIRVisionTextRecognizedBreak *wordBreak = word.recognizedBreak; CGRect wordFrame = word.frame; for (FIRVisionDocumentTextSymbol *symbol in word.symbols) { NSString *symbolText = symbol.text; NSNumber *symbolConfidence = symbol.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *symbolRecognizedLanguages = symbol.recognizedLanguages; FIRVisionTextRecognizedBreak *symbolBreak = symbol.recognizedBreak; CGRect symbolFrame = symbol.frame; } } } }
Nächste Schritte
- Bevor Sie eine App, die eine Cloud-API verwendet, für die Produktion bereitstellen, sollten Sie einige zusätzliche Schritte unternehmen, um die Auswirkungen eines nicht autorisierten API-Zugriffs zu verhindern und abzumildern .