Wie wir Computer-Vision-Algorithmen verwenden: Videoverarbeitung in einem mobilen Browser mit OpenCV.js

Es gibt bereits alle Möglichkeiten, eine Person online zu identifizieren, aber bisher werden sie nur selten verwendet. Vielleicht haben wir als einer der Ersten das optimale Szenario für den Benutzer implementiert: Melden Sie sich von einem Smartphone aus auf der Website an, machen Sie ein Foto Ihres Führerscheins oder Reisepasses und senden Sie Daten an das System.

Betrachten wir, wie Computer-Vision-Algorithmen helfen, Dokumente in einem Videostream direkt in mobilen Browsern zu erkennen. In diesem Artikel teilen wir unsere Erfahrungen mit, wie wir OpenCV.js bei SimbirSoft dafür verwendet haben, welche Schwierigkeiten möglich sind, wie man Geschwindigkeit sicherstellt und eine „reibungslose“ Benutzeroberfläche erhält, ohne sich zu verlangsamen.




Was war die Aufgabe?


Das Geschäftsszenario für den zu entwickelnden Algorithmus ist wie folgt. Ein Benutzer, der von einem Mobiltelefon aus auf die Website zugreift, sollte in der Lage sein, seine Dokumente zu fotografieren und zur weiteren Verarbeitung an das System zu senden. Dies kann Teil des Identitätsprozesses sein, wenn Sie die Nutzung von Diensten beantragen.

Eine Webanwendung in diesem Szenario ist einer mobilen Anwendung aufgrund ihrer Verfügbarkeit und der kürzeren Zeit für den Abschluss des Vorgangs vorzuziehen. Die Webseite muss nicht installiert werden und ist sofort nach dem Laden betriebsbereit. Der Benutzer kann die erforderlichen Aktionen - Einreichen eines Antrags - unmittelbar nach Erhalt des Links ausführen, ohne durch zusätzliche Aktionen abgelenkt zu werden. Aus geschäftlicher Sicht erhöhen diese Faktoren die Umwandlung und die wirtschaftliche Effektivität des Prozesses.

Aus architektonischer Sicht ist der Algorithmus erforderlich, um die Grenzen des Dokuments direkt zu erkennen und den überschüssigen Hintergrund im Bild zuzuschneiden. Die Überprüfung der Identität, Authentifizierung und Betrugsprüfung wird von anderen Komponenten durchgeführt. Es ist jedoch ratsam, mindestens minimale Überprüfungen durchzuführen, um das Senden von Visitenkarten, leeren Papierrechtecken und anderen offensichtlich irrelevanten Bildern für die Verarbeitung von Bildern auszuschließen.

Bedarf


Im Rahmen unseres Projekts wurden folgende zusätzliche Anforderungen an den Algorithmus gestellt:

  • die Fähigkeit, in Echtzeit zu arbeiten: Der Videostream von der Kamera sollte während des Betriebs des Algorithmus nicht „langsamer“ werden.
  • die Fähigkeit, in einem breiten Spektrum von Kontrast- und Hintergrundtexturen zu arbeiten: kontrastarmer und kontrastarmer, homogener und heterogener Hintergrund;
  • Unterstützung für eine Vielzahl von Smartphone-Modellen, einschließlich Budgetmodellen, die vor einigen Jahren veröffentlicht wurden.

Schließlich gab es im Projekt keinen Datensatz zum Trainieren von Algorithmen für maschinelles Lernen, und es gab keine Möglichkeit, ihn zu sammeln und zu markieren. Wir hatten nur wenige Testmuster aus den Suchergebnissen von Google.

Angesichts dieser Problemstellung haben wir uns entschlossen, basierend auf den klassischen Computer-Vision-Algorithmen aus der opencv-Bibliothek zu entwickeln. Eine alternative Möglichkeit war die Verwendung von Algorithmen für maschinelles Lernen und neuronalen Netzen, die jedoch aufgrund von Leistungsanforderungen bereits in den frühen Arbeitsphasen verworfen wurden: Bei Anwendung wäre es nicht möglich, auf allen Zielgeräten eine Echtzeit-Rahmenverarbeitung bereitzustellen.

Allgemeiner Ansatz und Algorithmusstruktur


Die Hauptidee des Algorithmus ist ein Referenzrahmen, entlang dessen das Dokument ausgerichtet werden muss. Seine Verwendung verfolgt mehrere Ziele gleichzeitig. Erstens wird eine geeignete Bildgröße bereitgestellt, die für die weitere Verarbeitung von Dokumenten ausreicht. Zweitens kann es, wie wir später sehen werden, als einer der Kandidatenfilter bei der Suche nach Dokumentgrenzen verwendet werden. Drittens kann es zum Erfassen und Zuschneiden des Bildes verwendet werden, wenn die Ränder des Dokuments nicht gefunden wurden.



Feige. 1. Die allgemeine Struktur des Algorithmus

Die allgemeine Struktur des Algorithmus ist in Abb. 1 dargestellt. 1. Bilder aus dem Videostream werden in einem Zyklus verarbeitet, zwischen dessen Iterationen ein Zeitlimit festgelegt wird, das den gewünschten FPS entspricht. Wir haben bei 30 Bildern pro Sekunde angehalten. Auf diese Weise können Sie „Verlangsamungen“ vermeiden und die Belastung des Prozessors sowie den Stromverbrauch des Geräts verringern.

Jeder verarbeitete Rahmen wird einer Vorverarbeitung unterzogen, während der zwei grundlegende Operationen ausgeführt werden. Zunächst wird eine Kopie eines Frames mit einer festen Größe von 640 x 480 erstellt, mit der die weiteren Schritte des Algorithmus arbeiten. Das Originalbild bleibt ebenfalls erhalten, das erkannte Dokument wird daraus ausgeschnitten. Dadurch wird die Qualität des endgültigen Bildes gespeichert. Zweitens wird die erstellte Kopie in Graustufen übersetzt. Die Farbe des zu verarbeitenden Dokuments wird vom Algorithmus ignoriert, da sie von Land zu Land und sogar in verschiedenen Regionen des Landes variieren kann. Ein Beispiel ist ein Führerschein in den USA.

Der erste Schritt beim Erkennen eines Dokuments besteht darin, nach dem Gesicht im Bild zu suchen. Die Verwendung dieser Heuristik eliminiert die Erfassung von Visitenkarten und anderen offensichtlich irrelevanten Bildern. Die Suche wird mit dem Standard-CascadeClassifier.detectMultiScale () von opencv'shash und der vorab trainierten Kaskade haarcascade_frontalface_default durchgeführt . Die minimale und maximale Größe der erkannten Gesichter ist begrenzt, wodurch die Rechenkosten gesenkt werden können und der Maßstab des Dokuments im Bild weiter eingeschränkt wird. Ein Gesicht wird im Bild als erkannt betrachtet, wenn es sich links oder unten links für Pässe als Teil des Bereichs innerhalb des Referenzrahmens befindet (Abb. 2). Dies ist eine zusätzliche Maßnahme, um die korrekte Ausrichtung des Dokuments im Bild sicherzustellen.

Die Beispiele in diesem Artikel enthalten keine personenbezogenen Daten.



Feige. 2. Der Bereich der erwarteten Position des Gesichts im Bild. Der Stützrahmen wird rot angezeigt, die Ränder des Bereichs der erwarteten Position des Gesichts werden grün angezeigt.

Nach der Gesichtserkennung fahren wir mit der Rahmenerkennung fort. Oft wird hier findContours () verwendet . Dieser Ansatz funktioniert jedoch nur in kontrastierenden Fällen, z. B. bei einem Blatt Papier, das auf einem dunklen Schreibtisch liegt. Wenn der Kontrast geringer ist oder die Beleuchtung schlechter ist oder jemand ein Blatt in der Hand hält und einen Teil des Randes mit den Fingern bedeckt, zerfallen die erkannten Konturen in separate Komponenten, „verlieren“ wichtige Abschnitte oder werden überhaupt nicht erkannt.

Deshalb haben wir einen anderen Ansatz gewählt. Nach der Binarisierung führen wir das Bild zuerst mit Canny () durch den Rahmenfilter und betrachten dann das resultierende Bild für die Linie mit der Huff-Transformation HoughLines () . Der Schwellenwertparameter wird sofort groß genug auf 30 gesetzt, um erkannte kurze und andere irrelevante Segmente zu filtern.

Der resultierende Satz von Linien wird zusätzlich gefiltert, so dass nur Linien in der Nähe des Referenzrahmens verbleiben. Dazu übersetzen wir zuerst die Gleichungen der Rahmenlinien in Punkte im Polarkoordinatensystem (Rho, Theta) - Theta ist immer 0 oder pi / 2, und Rho ist für jede Linie eindeutig. Danach wählen wir aus den aus der Huff-Transformation erhaltenen Linien nur diejenigen aus, die in der Nähe der Kontrollpunkte liegen - gemäß der euklidischen Metrik unter Berücksichtigung des Unterschieds in der Skala der Werte.

Wir verteilen den Satz von Linien, der nach dem Filtern erhalten wurde, in vier Gruppen, die den vier Linien des Referenzrahmens entsprechen, finden die Schnittpunkte der Linien paarweise zwischen den Gruppen, mitteln und erhalten die Koordinaten der vier Punkte - die Ecken des erkannten Dokuments (Abb. 3).



Feige. 3. Linien filtern und Dokumentecken definieren. Grüne Linien - das Ergebnis der Filterung, gelbe Punkte - erkannten Ecken des Dokuments

Als Nächstes müssen Sie die Qualität des Rahmens sicherstellen. Dazu überprüfen wir, ob der Frame zum letzten Mal stationär geblieben ist. Subtrahieren Sie dazu den Frame zu Beginn des Zeitraums mit absdiff () vom aktuellen Frame und vergleichen Sie ihn mit dem Schwellenwert. Vor der Subtraktion glätten wir die Bilder zusätzlich mit einem Gaußschen Filter GaussianBlur () , um den Einfluss von Rauschen und anderen Zufallsfaktoren zu verringern. Wir bewerten auch den Fokus des Rahmens, indem wir seinen Laplace- Wert Laplace () berechnen , seine Varianz schätzen und den erhaltenen Wert mit einem Schwellenwert vergleichen.

Wenn alle Prüfungen erfolgreich sind, können Sie mit dem letzten Teil fortfahren. Wir berechnen die erkannten Koordinaten der Winkel neu in das Koordinatensystem des ursprünglichen, unterbelichteten Bildes und schneiden den resultierenden Bereich mit der roi () -Methode . Das Dokument wurde erfolgreich erkannt.

Implementierungsfunktionen


Während der Entwicklung des Algorithmus wurden seine Hauptkomponenten in einem Python-Skript zusammengestellt. Danach wurde der Algorithmus nach opencv.js und Javascript und dann nach wasm portiert. Dieser Ansatz wird durch Überlegungen zur Zweckmäßigkeit in allen Phasen bestimmt. Auf Python war es für unser Team bequemer, mit verschiedenen Varianten des Algorithmus zu experimentieren und grobe Parametereinstellungen vorzunehmen. Durch die Portierung auf Javascript konnte die Funktionsweise des Algorithmus auf der Zielplattform getestet werden, auch auf verschiedenen Geräten und Browsern. Basierend auf den Ergebnissen dieser Überprüfungen wurde eine Feinabstimmung der Algorithmusparameter durchgeführt. Durch das Umschreiben kritischer Codeabschnitte auf wasm konnten wir schließlich eine zusätzliche Leistungssteigerung erzielen.

Während der Migration wurden einige Unterschiede in der OpenCV-API festgestellt, die zu geringfügigen Änderungen in der Implementierung führten. Zum Beispiel wird die Varianz eines Laplace in Python einfach als Laplace () betrachtet. Var () . Mit OpenCV.js gibt es keine Möglichkeit, NumPy zu verwenden, es wurde jedoch keine alternative Implementierung der var () -Methode bereitgestellt. Lösung: Zählen Sie die Funktion meanStdDev () als Standardabweichung (Listing 1).

private isImageBlurry(image: cv.Mat): boolean {
		const laplacian = new cv.Mat();
		cv.Laplacian(image, laplacian, cv.CV_64F);
		const s_mat = new cv.Mat();
		cv.meanStdDev(laplacian, new cv.Mat(), s_mat);
		const s = s_mat.data64F[0];
		const v = Math.pow(s, 2);
		return (v < this.laplacianVarianceThreshold);
	}

Listing 1. Bewertung des Fokus auf das Bild anhand der Varianz des Laplace in opencv.js (TypeScript)

Ein weiteres Merkmal war die Notwendigkeit, die Größe der Bibliothek zu reduzieren. In seiner ursprünglichen Form hat OpenCV.js eine Kapazität von 7,9 MB. Der Download über das Internet verlangsamt die Initialisierung des Algorithmus. Die Lösung für dieses Problem besteht darin, die nicht verwendeten Module während des Zusammenbaus der Bibliothek zu „trimmen“, was die Größe der Ausgabedatei erheblich reduzieren kann: Wir haben es geschafft, eine Größe von 1,8 MB zu erreichen. Die Liste der in der Assembly enthaltenen Komponenten kann in der Konfigurationsdatei platform / js / opencv_js.config.py (Listing 2) konfiguriert werden .

white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, photo, aruco, calib3d])

Listing 2. Die ursprüngliche Whitelist der OpenCV-Module, die in der Assembly für Javascript enthalten sind

Schließlich wurde ein wichtiger Beitrag zur Sicherstellung der erforderlichen Leistung des Algorithmus geleistet, indem er in Web Worker verschoben wurde. Dieser Schritt, zusammen mit der Einschränkung von FPS, ermöglichte es uns, die "Verlangsamungen" des Videostreams während des Betriebs des Algorithmus zu beseitigen, was sich positiv auf UX auswirkte.

Ergebnisse


Beispiele für das Aufnehmen und Zuschneiden von Bildern sind in Abb. 1 dargestellt. 4. Es ist ersichtlich, dass das Zuschneiden mit der höchsten Qualität auf einem dunklen, gleichmäßigen Hintergrund erzielt wird und die niedrigste Qualität mit einem hellen inhomogenen Hintergrund erzielt wird. Dies ist der erwartete Effekt, der mit den Verläufen verbunden ist, die auf verschiedenen Hintergründen erhalten und zum Erkennen der Ränder eines Dokuments verwendet werden. Vor einem dunklen Hintergrund sind die Gradienten größer als auf einem hellen Hintergrund, ein gleichmäßiger Hintergrund führt zu einer geringeren Variabilität der Gradientenwerte. Dies führt zu einer zuverlässigen Erkennung von Grenzen und damit zu einem besseren Zuschneiden.




Feige. 4. Beispiele für das Zuschneiden von Dokumenten mithilfe eines Algorithmus

Fazit


Der Artikel enthält einen Algorithmus zum Erkennen von Dokumenten in Frames aus einem Videostream, der für die Verwendung in mobilen Browsern geeignet ist, und berücksichtigt auch die Funktionen seiner Implementierung mithilfe der Bibliothek opencv.js. Mit dem Algorithmus können Sie das Ausgabebild von Dokumenten in einer Qualität erhalten, die für die weitere Verwendung durch Algorithmen zur Authentifizierung, Identitätsprüfung usw. ausreicht. Die Geschwindigkeit der resultierenden Implementierung ermöglicht es Ihnen, eine "reibungslose" UX ohne "Verlangsamungen" und Frame-Verlust zu erhalten.

Vielen Dank für Ihre Aufmerksamkeit! Wir hoffen, dass Sie diesen Artikel nützlich finden.

All Articles