Erstellen einer Android-Anwendung zur Texterkennung in 10 Minuten. Mobile Vision CodeLab

Videoversion des Tutorials



Die optische Zeichenerkennung ( OCR ) bietet dem Computer die Möglichkeit, Text in einem Bild zu lesen, sodass Anwendungen Zeichen, Artikel, Flyer, Textseiten, Menüs oder alles in Form von Text verstehen können. Mobile Vision Text API bietet Android Entwicklern eine leistungsstarke und zuverlässige OCR Funktion, die die meisten Android Geräte unterstützt und die Größe Ihrer Anwendung nicht erhöht.


In diesem Tutorial erstellen Sie eine Anwendung, in der der gesamte in den Frame fallende Text während des Videoaufzeichnungsprozesses erkannt und abgespielt wird.


Wir haben auch Artikel zu anderen Mobile Vision-Funktionen veröffentlicht:



Der Quellcode kann hier heruntergeladen werden .


Oder klonen Sie das GitHub Repository über die Befehlszeile:


 $ git clone https://github.com/googlesamples/android-vision.git 

Das visionSamples Repository enthält viele Beispielprojekte im Zusammenhang mit Mobile Vision . In dieser Lektion werden nur zwei verwendet:


  • ocr-codelab / ocr-reader-start ist der ursprüngliche Code, den Sie in dieser Lektion verwenden werden.
  • ocr-codelab / ocr-reader-complete - der vollständige Code für die fertige Anwendung. Sie können damit Fehler beheben oder direkt zur Arbeitsanwendung wechseln.

Google Play Services-Update


Möglicherweise müssen Sie Ihre installierte Version von Google Repository aktualisieren, um die Mobile Vision Text API .


Öffnen Sie Android Studio und öffnen Sie den SDK Manager :




Stellen Sie sicher, dass das Google Repository neuesten Stand ist. Es muss mindestens Version 26 .




Fügen Sie eine Google Play Services-Abhängigkeit hinzu und erstellen Sie eine Launcher-App


Jetzt können Sie das Starterprojekt öffnen:


  1. Wählen Sie ein Startverzeichnis ocr-reader aus dem heruntergeladenen Code ( Datei > Öffnen > ocr-codelab/ocr-reader-start ).


  2. Fügen Sie der Anwendung die Abhängigkeit von Google Play Services . Ohne diese Abhängigkeit ist die Text API nicht verfügbar.



Das Projekt zeigt möglicherweise das Fehlen der Datei integer / google_play_services_version an und gibt einen Fehler aus. Dies ist normal, wir werden es im nächsten Schritt beheben.


Öffnen Sie die Datei build.gradle im app Modul und ändern Sie den Abhängigkeitsblock so, dass dort die Abhängigkeit von play-services-vision ist. Wenn alles fertig ist, sollte die Datei folgendermaßen aussehen:


 dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:support-v4:26.1.0' implementation 'com.android.support:design:26.1.0' implementation 'com.google.android.gms:play-services-vision:15.0.0' } 

  1. Klicken Sie auf Gradle Synchronisierungstaste.


  2. Klicken Sie auf Startknopf.



Nach einigen Sekunden wird der Bildschirm "Text lesen" angezeigt, dies ist jedoch nur ein schwarzer Bildschirm.




Im CameraSource passiert nichts, da CameraSource nicht konfiguriert ist. Lass es uns tun.


Wenn Sie keinen Erfolg haben, können Sie ein Projekt öffnen ocr-reader-complete und stellen Sie sicher, dass es richtig funktioniert. Dieses Projekt ist eine vorgefertigte Version der Lektion. Wenn diese Version nicht funktioniert, sollten Sie überprüfen, ob mit Ihren Geräte- und Android Studio Einstellungen alles in Ordnung ist.


Konfigurieren Sie TextRecognizer und CameraSource


TextRecognizer erstellen wir unseren TextRecognizer . Dieses Detektorobjekt verarbeitet die Bilder und bestimmt, welcher Text in ihnen erscheint. Nach der Initialisierung kann TextRecognizer verwendet werden, um Text in allen Bildtypen zu erkennen. Suchen Sie die Methode createCameraSource und erstellen Sie einen TextRecognizer :


OcrCaptureActivity.java


 private void createCameraSource(boolean autoFocus, boolean useFlash) { Context context = getApplicationContext(); // TODO: Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. // TODO: Check if the TextRecognizer is operational. // TODO: Create the mCameraSource using the TextRecognizer. } 

Jetzt ist TextRecognizer einsatzbereit. Möglicherweise funktioniert es jedoch noch nicht. Wenn das Gerät nicht über genügend Speicher verfügt oder Google Play Services keine OCR Abhängigkeiten laden kann, funktioniert das TextRecognizer Objekt nicht. Bevor wir es für die Texterkennung verwenden, müssen wir überprüfen, ob es bereit ist. Wir werden diese Prüfung zu createCameraSource hinzufügen, nachdem wir den createCameraSource initialisiert haben:


OcrCaptureActivity.java


 // TODO: Check if the TextRecognizer is operational. if (!textRecognizer.isOperational()) { Log.w(TAG, "Detector dependencies are not yet available."); // Check for low storage. If there is low storage, the native library will not be // downloaded, so detection will not become operational. IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null; if (hasLowStorage) { Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show(); Log.w(TAG, getString(R.string.low_storage_error)); } } 

Nachdem wir überprüft haben, dass TextRecognizer einsatzbereit ist, können wir damit einzelne Frames erkennen. Aber wir wollen etwas Interessanteres tun: Lesen Sie den Text im Videomodus. Zu diesem CameraSource erstellen wir eine CameraSource , die für die Steuerung der Kamera CameraSource ist. Wir müssen eine hohe Auflösung für die Aufnahme einstellen und den Autofokus aktivieren, um die Aufgabe der Erkennung von kleinem Text zu bewältigen. Wenn Sie sicher sind, dass Ihre Benutzer große Textblöcke, z. B. Zeichen, betrachten, können Sie eine niedrigere Auflösung verwenden, und die Bildverarbeitung wird schneller:


OcrCaptureActivity.java


 // TODO: Create the cameraSource using the TextRecognizer. cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer) .setFacing(CameraSource.CAMERA_FACING_BACK) .setRequestedPreviewSize(1280, 1024) .setRequestedFps(15.0f) .setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null) .setFocusMode(autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO : null) .build(); 

So sollte die createCameraSource Methode aussehen, wenn Sie fertig sind:


OcrCaptureActivity.java


 private void createCameraSource(boolean autoFocus, boolean useFlash) { Context context = getApplicationContext(); // Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. // Check if the TextRecognizer is operational. if (!textRecognizer.isOperational()) { Log.w(TAG, "Detector dependencies are not yet available."); // Check for low storage. If there is low storage, the native library will not be // downloaded, so detection will not become operational. IntentFilter lowstorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW); boolean hasLowStorage = registerReceiver(null, lowstorageFilter) != null; if (hasLowStorage) { Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show(); Log.w(TAG, getString(R.string.low_storage_error)); } } // Create the cameraSource using the TextRecognizer. cameraSource = new CameraSource.Builder(getApplicationContext(), textRecognizer) .setFacing(CameraSource.CAMERA_FACING_BACK) .setRequestedPreviewSize(1280, 1024) .setRequestedFps(15.0f) .setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null) .setFocusMode(autoFocus ? Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO : null) .build(); } 

Wenn Sie die Anwendung ausführen, werden Sie sehen, dass das Video gestartet wurde! createCameraSource Bilder von der Kamera zu verarbeiten, müssen wir dieses letzte TODO zu createCameraSource : Erstellen Sie einen Processor , um den createCameraSource Text zu verarbeiten.


OcrDetectorProcessor erstellen


Ihre Anwendung kann jetzt Text in einzelnen Frames mithilfe der Erkennungsmethode in TextRecognizer . So finden Sie beispielsweise Text auf einem Foto. Um den Text jedoch direkt während der Videoaufnahme lesen zu können, müssen Sie einen Processor implementieren, der den Text verarbeitet, sobald er auf dem Bildschirm angezeigt wird.


OcrDetectorProcessor Sie zur OcrDetectorProcessor Klasse OcrDetectorProcessor implementieren Sie die Detector.Processor Schnittstelle:


OcrDetectorProcessor.java


 public class OcrDetectorProcessor implements Detector.Processor<TextBlock> { private GraphicOverlay<OcrGraphic> graphicOverlay; OcrDetectorProcessor(GraphicOverlay<OcrGraphic> ocrGraphicOverlay) { graphicOverlay = ocrGraphicOverlay; } } 

Um diese Schnittstelle zu implementieren, müssen Sie zwei Methoden überschreiben. Der erste, receiveDetections , empfängt TextBlocks von receiveDetections , TextBlocks sie erkannt werden. Die zweite release wird verwendet, um Ressourcen freizugeben, wenn ein TextRecognizer zerstört wird. In diesem Fall müssen wir nur die grafische OcrGraphic löschen, wodurch alle OcrGraphic Objekte OcrGraphic werden.


Wir werden TextBlocks und OcrGraphic Objekte für jeden vom Prozessor erkannten TextBlocks erstellen. Wir implementieren die Logik ihrer Zeichnung im nächsten Schritt.


OcrDetectorProcessor.java


 @Override public void receiveDetections(Detector.Detections<TextBlock> detections) { graphicOverlay.clear(); SparseArray<TextBlock> items = detections.getDetectedItems(); for (int i = 0; i < items.size(); ++i) { TextBlock item = items.valueAt(i); if (item != null && item.getValue() != null) { Log.d("Processor", "Text detected! " + item.getValue()); OcrGraphic graphic = new OcrGraphic(graphicOverlay, item); graphicOverlay.add(graphic); } } } @Override public void release() { graphicOverlay.clear(); } 

textRecognizer der Prozessor bereit ist, müssen wir textRecognizer für die Verwendung konfigurieren. createCameraSource Sie zum letzten verbleibenden TODO in der Methode OcrCaptureActivity in OcrCaptureActivity :


OcrCaptureActivity.java


 // Create the TextRecognizer TextRecognizer textRecognizer = new TextRecognizer.Builder(context).build(); // TODO: Set the TextRecognizer's Processor. textRecognizer.setProcessor(new OcrDetectorProcessor(graphicOverlay)); 

Führen Sie nun die Anwendung aus. Wenn Sie zu diesem Zeitpunkt die Kamera über Text bewegen, werden Debug-Meldungen "Text erkannt!" Angezeigt. in Android Monitor Logcat ! Dies ist jedoch keine sehr visuelle Methode, um zu visualisieren, was TextRecognizer sieht, oder?


Im nächsten Schritt werden wir diesen Text auf dem Bildschirm zeichnen.


Zeichnen von Text auf dem Bildschirm


Lassen Sie uns die OcrGraphic in OcrGraphic . Wir müssen verstehen, ob das Bild Text enthält, die Koordinaten seiner Ränder in Leinwandrahmen konvertieren und dann sowohl die Ränder als auch den Text zeichnen.


OcrGraphic.java


 @Override public void draw(Canvas canvas) { // TODO: Draw the text onto the canvas. if (text == null) { return; } // Draws the bounding box around the TextBlock. RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); canvas.drawRect(rect, rectPaint); // Render the text at the bottom of the box. canvas.drawText(text.getValue(), rect.left, rect.bottom, textPaint); } 

Starten Sie die Anwendung und testen Sie sie an diesem Beispieltext:



Sie sollten sehen, dass auf dem Bildschirm ein Rahmen mit Text angezeigt wird! Mit TEXT_COLOR können Sie mit der Farbe des Textes TEXT_COLOR .


Wie wäre es damit?



Der Rahmen um den Text sieht korrekt aus, aber der Text befindet sich am unteren Rand.




Dies liegt daran, dass die Engine den gesamten Text, den sie im TextBlock als einen einzigen Satz TextBlock , selbst wenn ein Satz in mehrere Zeilen unterteilt ist. Wenn Sie das gesamte Angebot erhalten möchten, ist dies sehr praktisch. Aber was ist, wenn Sie wissen möchten, wo sich jede einzelne Textzeile befindet?


Sie können Lines aus einem TextBlock getComponents , indem getComponents TextBlock aufrufen. getComponents dann jede Zeile sortieren, können Sie leicht die Position und den Text darin getComponents . Auf diese Weise können Sie Text an der Stelle zeichnen, an der er wirklich angezeigt wird.


OcrGraphic.java


 @Override public void draw(Canvas canvas) { // TODO: Draw the text onto the canvas. if (text == null) { return; } // Draws the bounding box around the TextBlock. RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); canvas.drawRect(rect, rectPaint); // Break the text into multiple lines and draw each one according to its own bounding box. List<? extends Text> textComponents = text.getComponents(); for(Text currentText : textComponents) { float left = translateX(currentText.getBoundingBox().left); float bottom = translateY(currentText.getBoundingBox().bottom); canvas.drawText(currentText.getValue(), left, bottom, textPaint); } } 

Versuchen Sie diesen Text noch einmal:



Großartig! Sie können den gefundenen Text je nach Bedarf sogar in noch kleinere Komponenten aufteilen. Sie können getComponents in jeder Zeile aufrufen und Elements (lateinische Wörter) getComponents . Es ist möglich, textSize so zu konfigurieren, dass der Text so viel Platz einnimmt wie der tatsächliche Text auf dem Bildschirm.




Spielen Sie Text ab, wenn Sie darauf klicken


Jetzt wird der Text von der Kamera in strukturierte Linien umgewandelt und diese Linien werden auf dem Bildschirm angezeigt. Lass uns etwas anderes mit ihnen machen.


Mithilfe der in Android TextToSpeech API und der OcrGraphic Methode in OcrGraphic können wir der Anwendung beibringen, laut zu sprechen, wenn Sie auf den Text klicken.


Lassen Sie uns zunächst die Methode OcrGraphic in OcrGraphic . Wir müssen nur überprüfen, ob die x und y Koordinaten innerhalb der Grenzen des angezeigten Textes liegen.
OcrGraphic.java


 public boolean contains(float x, float y) { // TODO: Check if this graphic's text contains this point. if (text == null) { return false; } RectF rect = new RectF(text.getBoundingBox()); rect = translateRect(rect); return rect.contans(x, y); } 

Möglicherweise stellen Sie fest, dass die Draw Methode viel gemeinsam hat! In diesem Projekt sollten Sie in der Lage sein, den Code wiederzuverwenden, aber hier lassen wir alles so, wie es nur als Beispiel dient.


onTap wir nun mit der onTap Methode in OcrCaptureActivity und verarbeiten den Klick auf den Text, falls sich an dieser Stelle einer befindet.


OcrCaptureActivity.java


 private boolean onTap(float rawX, float rawY) { // TODO: Speak the text when the user taps on screen. OcrGraphic graphic = graphicOverlay.getGraphicAtLocation(rawX, rawY); TextBlock text = null; if (graphic != null) { text = graphic.getTextBlock(); if (text != null && text.getValue() != null) { Log.d(TAG, "text data is being spoken! " + text.getValue()); // TODO: Speak the string. } else { Log.d(TAG, "text data is null"); } } else { Log.d(TAG,"no text detected"); } return text != null; } 

Sie können die Anwendung ausführen und sicherstellen, dass das Klicken auf den Text tatsächlich über Android Monitor Logcat .


Lassen Sie uns unsere App zum Reden bringen! Gehen Sie zum Anfang der Activity und suchen Sie die onCreate Methode. Beim Starten der Anwendung müssen wir die TextToSpeech Engine für die zukünftige Verwendung initialisieren.


OcrCaptureActivity.java


 @Override public void onCreate(Bundle bundle) { // (Portions of this method omitted) // TODO: Set up the Text To Speech engine. TextToSpeech.OnInitListener listener = new TextToSpeech.OnInitListener() { @Override public void onInit(final int status) { if (status == TextToSpeech.SUCCESS) { Log.d("TTS", "Text to speech engine started successfully."); tts.setLanguage(Locale.US); } else { Log.d("TTS", "Error starting the text to speech engine."); } } }; tts = new TextToSpeech(this.getApplicationContext(), listener); } 

Trotz der Tatsache, dass wir TextToSpeech korrekt initialisiert TextToSpeech , müssen Sie in der Regel immer noch allgemeine Fehler behandeln, z. B. wenn die Engine beim ersten Klicken auf den Text noch nicht bereit ist.


TextToSpeech auch sprachabhängig. Sie können die Sprache basierend auf der Sprache des erkannten Textes ändern. Die Spracherkennung ist nicht in die Mobile Vision Text API , sie ist jedoch über die Google Translate API verfügbar. Als Sprache zum Erkennen von Text können Sie die Sprache des Benutzergeräts verwenden.


Alles, was übrig bleibt, ist das Hinzufügen des onTap in der onTap Methode.


OcrCaptureActivity.java


 private boolean onTap(float rawX, float rawY) { // TODO: Speak the text when the user taps on screen. OcrGraphic graphic = graphicOverlay.getGraphicAtLocation(rawX, rawY); TextBlock text = null; if (graphic != null) { text = graphic.getTextBlock(); if (text != null && text.getValue() != null) { Log.d(TAG, "text data is being spoken! " + text.getValue()); // Speak the string. tts.speak(text.getValue(), TextToSpeech.QUEUE_ADD, null, "DEFAULT"); } else { Log.d(TAG, "text data is null"); } } else { Log.d(TAG,"no text detected"); } return text != null; } 

Wenn Sie nun die Anwendung starten und auf den erkannten Text klicken, wird er von Ihrem Gerät abgespielt. Probieren Sie es aus!


Fertigstellung


Jetzt haben Sie eine Anwendung, die Text von der Kamera erkennen und laut aussprechen kann!


Sie können das erworbene Wissen der Texterkennung in Ihren anderen Anwendungen anwenden. Lesen Sie beispielsweise Adressen und Telefonnummern von Visitenkarten und durchsuchen Sie den Text anhand von Fotos verschiedener Dokumente. Kurz gesagt, verwenden Sie OCR überall dort, wo Sie Text in einem Bild erkennen müssen.


Quelle

Source: https://habr.com/ru/post/de412679/


All Articles