Automatische Sprachausgabe von YouTube-Untertiteln mithilfe von Computer Vision

Hey Habr! Vor ungefähr sechs Monaten stieß ich auf einen Artikel mit fast demselben Name . Die Idee selbst schien mir interessant und ich wollte etwas Ähnliches nur mit Computer Vision machen, und das ist, was ich bekam:

Allgemeine Projektarchitektur

Das Projekt basiert auf drei Diensten, von denen der erste für die Erkennung von Untertiteln und die Konvertierung des Textbildes in ein maschinenlesbares Textformat, der zweite Dienst für die Übersetzung von Text (derzeit nur vom Englischen ins Russische) und der letzte zuständig ist service ist für die Visualisierung und Sprachausgabe des Textes verantwortlich. Die Kommunikation zwischen Diensten wird unter Verwendung der Bibliothek implementiert ZeroMQ.

Datensammlung

Die Lösung fast jeder ML-Aufgabe beginnt mit dem Sammeln von Daten – diese Aufgabe ist keine Ausnahme, daher war es notwendig, einen Datensatz zu sammeln, der Screenshots von YouTube-Videos mit Untertiteln enthält und die Begrenzungsrahmen der Untertitel selbst hervorhebt. Hier sind die grundlegenden Anforderungen an Datensätze:

1) Untertitel müssen in verschiedenen Sprachen sein.

2) Das Bild mit dem Video selbst muss unterschiedliche Größen haben, dh das Video kann Vollbild oder Teil des Bildschirms sein.

3) Untertitel befinden sich in verschiedenen Bereichen des Bildschirms.

4) Anforderungen an die Untertitel selbst:

  • kann unterschiedlich groß sein;

  • Schriftfamilie: normale und proportionale serifenlose Schrift;

  • Schriftfarbe: weiß;

  • Hintergrundfarbe: schwarz;

  • Hintergrundtransparenz: 75 %;

  • Fenstertransparenz: 0%.

Der Datensatz wurde von LabelMe-Mitarbeitern erfolgreich zusammengestellt, wofür ihnen vielen Dank gebührt! Den Originaldatensatz finden Sie unter Kaggle .

Untertitelerkennung

Nachdem der Datensatz zusammengestellt wurde, muss das Modell trainiert werden, um Untertitel zu finden und sogar in Echtzeit zu erkennen. Die Wahl fiel auf yolov5 . Und nach 50 Trainingsepochen an einem vortrainierten Modell haben wir ziemlich beeindruckende Messwerte erhalten:

Und so funktioniert die Erkennung in Echtzeit:

Vorbereiten eines Bildes für OCR

Die meisten OCR-Bibliotheken, über die wir weiter unten sprechen werden, sind besser dran, ein Graustufenbild zu übergeben, also mache ich das zuerst:

Kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1)) grey = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, thresh_img = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY) transformation_image = cv2. morphologyEx(thresh_img, cv2.MORPH_OPEN, Kernel, Iterationen=1)

Die Ausgabe ist in etwa so:

Jetzt ist das Bild fertig, es scheint, nehmen Sie es und übertragen Sie das Bild in eine Bibliothek zur Texterkennung, aber es war nicht da. Tatsache ist, dass yolo mir ungefähr 10 Bilder pro Sekunde gibt und dementsprechend viele Bilder mit demselben Text erhalten werden, und warum müssen wir denselben Text viele Male übersetzen und sprechen?

OpenCV hat eine so großartige Funktion wie matchTemplate(). Diese Funktion kann als eine sehr einfache Form der Objekterkennung angesehen werden. Mithilfe des Musterabgleichs können wir Objekte im Eingabebild erkennen, indem wir eine “Vorlage” verwenden, die das Objekt enthält, das wir erkennen möchten:

Um das Muster im Quellbild zu finden, verschieben wir das Muster von links nach rechts und von oben nach unten über das Quellbild:

Diese Funktion gibt als einer der Parameter bedingt die Wahrscheinlichkeit von 0 bis 1 zurück, wie ähnlich zwei Bilder einander sind. Wenn diese Zahl größer als 0,75 ist, können wir davon ausgehen, dass sich auf diesen beiden Bildern derselbe Text befindet. Sie können mehr über diese Funktion lesen hier .

Das zweite Problem ist, dass der Text im nächsten Frame um 1-2 Wörter zum vorherigen ergänzt wird, das heißt:

Wie Sie sehen, unterscheidet sich der Text des ersten Bildes vom Text des zweiten Bildes nur durch “ist”. Ich denke, dies ist keine Option, um jeweils ein Wort zu isolieren und dieses eine Wort an den nächsten Schritt weiterzugeben. Daher schlage ich vor, irgendwie festzustellen, dass die Zeile beendet ist, und nur das Bild, auf dem die Zeile endet, wird an das nächste weitergegeben Bühne. Wir werden später darüber sprechen, wie wir dies bestimmen.

Die Funktion wird uns bei dieser Schwierigkeit helfen. bitweise_und() . Diese bitweise Operation fügt zwei Bilder so zusammen, dass nur die gleichen Teile beider Bilder im Ausgabebild verbleiben. Wenn wir diese Funktion auf die beiden obigen Bilder anwenden, sollten wir im Idealfall so etwas erhalten:

Aber was tatsächlich passiert, ist Folgendes:

Die Erkennung funktioniert jedoch nicht immer auf die gleiche Weise, dh es kommt häufig vor, dass ein Bild mit demselben Text, aber auf einem anderen Rahmen, um 2-3 Pixel in Breite und / oder Höhe abweicht. In diesem Fall können wir die Begrenzungsrahmen jedes Buchstabens finden und das Bild an diesen Koordinaten zuschneiden, sodass wir den schwarzen Hintergrund um den Text herum entfernen können. Ich habe in einem meiner vorherigen Artikel über Algorithmen zum Finden von Konturen und Begrenzungsrahmen geschrieben. Und als Ergebnis sollten wir ein dem Idealfall ähnliches Bild erhalten. Und dann ist alles ganz einfach: Wir übergeben das resultierende Bild zusammen mit dem ersten Bild (das nicht das Wort ist am Ende hat) an die Funktion matchTemplate() und verfahren genauso wie ein paar Absätze weiter oben beschrieben. Hier ist das Bild bereit für OCR 🙂

OCR

Nach einer meiner Meinung nach erfolgreichen Erkennung möchte ich auch Textbilder erfolgreich in ein maschinenlesbares Textformat konvertieren, aber das war nicht der Fall. Ich habe mir die folgenden Bibliotheken für die Texterkennung angesehen: Tesseract, EasyOCR und PaddleOCR. Jetzt müssen Sie einen der vorgeschlagenen auswählen. Nun, es wurde beschlossen, eine kleine Studie durchzuführen und zu überprüfen, wie gut jede der Bibliotheken mit meinen Daten nach drei Kriterien arbeitet: CER, WER und Algorithmuslaufzeit, wo Sie über die ersten beiden Metriken lesen können hier . Dafür wurden 50 Bilder aus dem Datensatz genommen und ich habe die Untertitel dieser Bilder in einem separaten umgeschrieben JSON-Datei . Ich habe die Daten durch die Inferenz jeder Entscheidung laufen lassen und die folgenden Ergebnisse erhalten:

Um ehrlich zu sein, dachte ich, dass die Ergebnisse besser wären, weil ich ein ziemlich gut vorbereitetes Graustufenbild hatte: ein Minimum an Hintergrundrauschen, der Text ist gleichmäßig, ohne Verdrehungen und Verzerrungen.

Nun müssen Sie sich für die zu verwendende Bibliothek entscheiden. Es scheint fast naheliegend, PaddleOCR zu verwenden, aber das Problem ist, dass ich nur 2 GB Videospeicher zur Verfügung habe, von denen ~ 1,5 GB vom Erkennungsmodell verbraucht werden, und auf der CPU dauert diese Lösung sehr lange, was nicht sehr ist für Echtzeit geeignet, die Situation ist die gleiche wie bei EasyOCR, außer dass ich es überhaupt nicht geschafft habe, diese Lösung auf der CPU auszuführen, aber für die Zukunft, wenn ich ein anständiges vidyuha habe, werde ich es im Hinterkopf behalten 🙂 Nur Tesseract bleibt – ich werde es verwenden.

Textverarbeitung und Übersetzung

Es kommt oft vor, dass Tesseract in einem Wort 1-2 Buchstaben falsch erkennen kann, wodurch das Wort in Zukunft falsch übersetzt werden kann. Also beschloss ich, die Bibliothek zu benutzen pyenchantdie die Rechtschreibung eines Wortes überprüft und wenn das Wort falsch geschrieben ist, schlägt die Bibliothek ein Wort vor, das dem aktuellen Wort ähnlich ist, und der resultierende Text wird an die nächste Stufe weitergeleitet – die Übersetzung.

Mit der Übersetzung ist alles einfach – Google Übersetzer-API. Es übersetzt an manchen Stellen nicht ganz richtig, aber ich habe keine schnellen und keine Beschränkungen bei der Anzahl der Anfragen bemerkt.

Sprachausgabe und Textvisualisierung

Für die Sprachausgabe habe ich ein nicht schickes Lib verwendet pyttsx3. Für die russische Sprache klingt das so lala, aber mit der Zeit gewöhnt man sich daran. Und die Visualisierung des Textes wurde mit Hilfe der Bibliothek umgesetzt PySimpleGUI

Fazit

Dieses Projekt wird wohl kaum von Menschen zur Lösung der Aufgabe genutzt werden, zumindest in der jetzigen Umsetzung, da es hier noch genug Probleme z. B. mit der Geschwindigkeit (5 Sekunden hinter der Realität) gibt, aber ich habe auch Ideen zur Verbesserung des Projekts , verbessern Sie beispielsweise die Textübersetzung wie hier beschrieben und trainieren Sie ein Texterkennungsmodell mit Ihren eigenen Daten. Das ist alles für mich 🙂 Der Quellcode ist verfügbar unter github . Allen einen schönen Tag!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *