Mit der Handschrifterkennungs-API können Sie handschriftlichen Text sofort erkennen.
Was ist die Handschrifterkennungs-API?
Mit der Handschrifterkennungs-API können Sie Handschrift (Tinte) Ihrer Nutzer in Text umwandeln. Einige Betriebssysteme enthalten seit Langem solche APIs. Mit dieser neuen Funktion können Ihre Webanwendungen diese Funktion endlich nutzen. Die Konvertierung erfolgt direkt auf dem Gerät des Nutzers, funktioniert sogar im Offlinemodus, ohne dass Bibliotheken oder Dienste von Drittanbietern hinzugefügt werden müssen.
Diese API implementiert eine sogenannte Online- oder echtzeitnahe Erkennung. Das bedeutet, dass die handschriftlichen Eingabe erkannt wird, während der Nutzer sie zeichnet, indem die einzelnen Striche erfasst und analysiert werden. Im Gegensatz zu Offline-Verfahren wie der optischen Zeichenerkennung (Optical Character Recognition, OCR), bei denen nur das Endprodukt bekannt ist, können Online-Algorithmen aufgrund zusätzlicher Signale wie der zeitlichen Abfolge und des Drucks einzelner Tintenstriche ein höheres Genauigkeitsniveau bieten.
Empfohlene Anwendungsfälle für die Handschrifterkennungs-API
Anwendungsbeispiele:
- Notizenanwendungen, in denen Nutzer handschriftliche Notizen erfassen und in Text übersetzen lassen möchten.
- Formularanwendungen, bei denen Nutzer bei zeitlicher Beschränkung die Eingabe per Stift oder Finger verwenden können
- Spiele, für die Buchstaben oder Zahlen eingegeben werden müssen, z. B. Kreuzworträtsel, Galgenmännchen oder Sudoku.
Aktueller Status
Die Handschrifterkennungs-API ist bei Chromium 99 erhältlich.
Handschrifterkennungs-API verwenden
Funktionserkennung
Prüfen Sie, ob die Methode createHandwritingRecognizer()
im Navigatorobjekt vorhanden ist, um die Browserunterstützung zu ermitteln:
if ('createHandwritingRecognizer' in navigator) {
// 🎉 The Handwriting Recognition API is supported!
}
Wichtige Konzepte
Die Handschrifterkennungs-API wandelt handschriftliche Eingaben unabhängig von der Eingabemethode (Maus, Berührung, Stift) in Text um. Die API hat vier Hauptentitäten:
- Ein Punkt gibt an, wo sich der Mauszeiger zu einem bestimmten Zeitpunkt befand.
- Ein Strich besteht aus einem oder mehreren Punkten. Die Aufzeichnung eines Strichs beginnt, wenn der Nutzer den Zeiger nach unten setzt (d.h. auf die primäre Maustaste klickt oder den Bildschirm mit einem Stift oder Finger berührt) und endet, wenn er ihn wieder nach oben hebt.
- Eine Zeichnung besteht aus einer oder mehreren Strichen. Die eigentliche Erkennung findet auf dieser Ebene statt.
- Die Erkennung ist mit der erwarteten Eingabesprache konfiguriert. Damit wird eine Instanz einer Zeichnung mit der Konfiguration der Erkennung erstellt.
Diese Konzepte werden als spezifische Schnittstellen und Wörterbücher implementiert, die ich in Kürze behandeln werde.
Erkennung erstellen
Um Text aus handschriftlichen Eingaben zu erkennen, müssen Sie eine Instanz eines HandwritingRecognizer
abrufen. Rufen Sie dazu navigator.createHandwritingRecognizer()
auf und übergeben Sie Einschränkungen. Einschränkungen bestimmen, welches Modell zur Handschrifterkennung verwendet werden sollte. Derzeit können Sie eine Liste von Sprachen in der gewünschten Reihenfolge angeben:
const recognizer = await navigator.createHandwritingRecognizer({
languages: ['en'],
});
Die Methode gibt ein Versprechen zurück, das mit einer Instanz von HandwritingRecognizer
aufgelöst wird, wenn der Browser Ihre Anfrage ausführen kann. Andernfalls wird das Versprechen mit einem Fehler abgelehnt und die Handschrifterkennung ist nicht verfügbar. Aus diesem Grund sollten Sie die Unterstützung der Erkennung für bestimmte Erkennungsfunktionen zuerst abfragen.
Unterstützung der Erkennung abfragen
Durch Aufrufen von navigator.queryHandwritingRecognizerSupport()
können Sie prüfen, ob die Zielplattform die Features zur Handschrifterkennung unterstützt, die Sie verwenden möchten. Im folgenden Beispiel geht der Entwickler so vor:
- möchte Texte auf Englisch erkennen
- alternative, weniger wahrscheinliche Vorhersagen erhalten, falls verfügbar
- Zugriff auf das Segmentierungsergebnis erhalten, d.h. die erkannten Zeichen, einschließlich der Punkte und Striche, aus denen sie bestehen
const { languages, alternatives, segmentationResults } =
await navigator.queryHandwritingRecognizerSupport({
languages: ['en'],
alternatives: true,
segmentationResult: true,
});
console.log(languages); // true or false
console.log(alternatives); // true or false
console.log(segmentationResult); // true or false
Die Methode gibt ein Versprechen zurück, das mit einem Ergebnisobjekt aufgelöst wird. Wenn der Browser die vom Entwickler angegebene Funktion unterstützt, wird der Wert auf true
festgelegt. Andernfalls wird er auf false
festgelegt.
Sie können diese Informationen verwenden, um bestimmte Features in Ihrer Anwendung zu aktivieren oder zu deaktivieren oder um Ihre Abfrage anzupassen und eine neue zu senden.
Zeichnung beginnen
Innerhalb Ihrer Anwendung sollten Sie einen Eingabebereich anbieten, in dem Nutzer handschriftliche Einträge eingeben können. Aus Leistungsgründen wird empfohlen, dies mithilfe eines Canvas-Objekts zu implementieren. Auf die genaue Implementierung dieses Teils wird in diesem Artikel nicht eingegangen. Wie das geht, erfahren Sie in der Demo.
Um eine neue Zeichnung zu starten, rufen Sie die Methode startDrawing()
für die Erkennung auf. Bei dieser Methode wird ein Objekt mit verschiedenen Hinweisen verwendet, um den Erkennungsalgorithmus zu optimieren. Alle Hinweise sind optional:
- Die Art des eingegebenen Texts: Text, E-Mail-Adressen, Zahlen oder ein einzelnes Zeichen (
recognitionType
) - Der Typ des Eingabegeräts: Maus-, Touch- oder Stifteingabe (
inputType
) - Der vorherige Text (
textContext
) - Die Anzahl der weniger wahrscheinlichen alternativen Vorhersagen, die zurückgegeben werden sollen (
alternatives
) - Eine Liste mit vom Nutzer identifizierbaren Zeichen („Graphemes“), die der Nutzer höchstwahrscheinlich eingibt (
graphemeSet
).
Die Handschrifterkennungs-API funktioniert gut mit Zeigerereignissen, die eine abstrakte Schnittstelle zur Verarbeitung von Eingaben von jedem Zeigegerät bieten. Die Argumente des Zeigerereignisses enthalten den verwendeten Zeigertyp. Das bedeutet, dass Sie Zeigerereignisse verwenden können, um den Eingabetyp automatisch zu bestimmen. Im folgenden Beispiel wird die Zeichnung zur Handschrifterkennung automatisch beim ersten Auftreten eines pointerdown
-Ereignisses im Handschriftbereich erstellt. Da pointerType
leer oder auf einen proprietären Wert festgelegt sein kann, habe ich eine Konsistenzprüfung eingeführt, um sicherzustellen, dass nur unterstützte Werte für den Eingabetyp der Zeichnung festgelegt sind.
let drawing;
let activeStroke;
canvas.addEventListener('pointerdown', (event) => {
if (!drawing) {
drawing = recognizer.startDrawing({
recognitionType: 'text', // email, number, per-character
inputType: ['mouse', 'touch', 'pen'].find((type) => type === event.pointerType),
textContext: 'Hello, ',
alternatives: 2,
graphemeSet: ['f', 'i', 'z', 'b', 'u'], // for a fizz buzz entry form
});
}
startStroke(event);
});
Schwimmstil hinzufügen
Das pointerdown
-Ereignis ist auch der richtige Ort, um einen neuen Strich zu beginnen. Erstellen Sie dazu eine neue Instanz von HandwritingStroke
. Außerdem sollten Sie die aktuelle Zeit als Bezugspunkt für die nachfolgenden Punkte speichern, die ihr hinzugefügt werden:
function startStroke(event) {
activeStroke = {
stroke: new HandwritingStroke(),
startTime: Date.now(),
};
addPoint(event);
}
Punkt hinzufügen
Nachdem Sie die Kontur erstellt haben, sollten Sie den ersten Punkt direkt hinzufügen. Da Sie später weitere Punkte hinzufügen, ist es sinnvoll, die Logik zur Punkterstellung in einer separaten Methode zu implementieren. Im folgenden Beispiel berechnet die Methode addPoint()
die verstrichene Zeit ab dem Referenzzeitstempel.
Die zeitlichen Informationen sind optional, können aber die Erkennungsqualität verbessern. Anschließend werden die X- und Y-Koordinaten aus dem Zeigerereignis ausgelesen und der Punkt dem aktuellen Strich hinzugefügt.
function addPoint(event) {
const timeElapsed = Date.now() - activeStroke.startTime;
activeStroke.stroke.addPoint({
x: event.offsetX,
y: event.offsetY,
t: timeElapsed,
});
}
Der pointermove
-Event-Handler wird aufgerufen, wenn der Mauszeiger über den Bildschirm bewegt wird. Diese Punkte müssen ebenfalls dem Strich hinzugefügt werden. Das Ereignis kann auch ausgelöst werden, wenn sich der Zeiger nicht in einem "Abwärts"-Zustand befindet, z. B. wenn der Cursor über den Bildschirm bewegt wird, ohne die Maustaste zu drücken. Der Event-Handler aus dem folgenden Beispiel prüft, ob ein aktiver Strich vorhanden ist, und fügt ihm den neuen Punkt hinzu.
canvas.addEventListener('pointermove', (event) => {
if (activeStroke) {
addPoint(event);
}
});
Text erkennen
Wenn der Nutzer den Mauszeiger wieder anhebt, können Sie die Kontur durch Aufrufen der addStroke()
-Methode Ihrer Zeichnung hinzufügen. Im folgenden Beispiel wird auch activeStroke
zurückgesetzt, sodass der pointermove
-Handler dem abgeschlossenen Strich keine Punkte hinzufügt.
Als Nächstes wird die Eingabe des Nutzers durch Aufrufen der Methode getPrediction()
für die Zeichnung erkannt. Die Erkennung dauert in der Regel weniger als ein paar Hundert Millisekunden, sodass Sie bei Bedarf wiederholt Vorhersagen ausführen können. Im folgenden Beispiel wird nach jedem abgeschlossenen Strich eine neue Vorhersage ausgeführt.
canvas.addEventListener('pointerup', async (event) => {
drawing.addStroke(activeStroke.stroke);
activeStroke = null;
const [mostLikelyPrediction, ...lessLikelyAlternatives] = await drawing.getPrediction();
if (mostLikelyPrediction) {
console.log(mostLikelyPrediction.text);
}
lessLikelyAlternatives?.forEach((alternative) => console.log(alternative.text));
});
Diese Methode gibt ein Versprechen zurück, das mit einem Array von Vorhersagen, sortiert nach ihrer Wahrscheinlichkeit, aufgelöst wird. Die Anzahl der Elemente hängt von dem Wert ab, den Sie an den alternatives
-Hinweis übergeben haben. Mit diesem Array können Sie dem Nutzer eine Auswahl möglicher Übereinstimmungen anzeigen und ihn eine Option auswählen lassen. Alternativ können Sie einfach die wahrscheinlichste Vorhersage verwenden, wie ich es im Beispiel mache.
Das Vorhersageobjekt enthält den erkannten Text und ein optionales Segmentierungsergebnis, auf das ich im folgenden Abschnitt näher eingehen werde.
Detaillierte Statistiken mit Segmentierungsergebnissen
Sofern dies von der Zielplattform unterstützt wird, kann das Vorhersageobjekt auch ein Segmentierungsergebnis enthalten.
Dies ist ein Array, das alle Segmente mit erkannten Handschriften, eine Kombination aus dem erkannten, vom Nutzer identifizierbaren Zeichen (grapheme
), seiner Position im erkannten Text (beginIndex
, endIndex
) und den Strichen und Punkten enthält, die es erstellt haben.
if (mostLikelyPrediction.segmentationResult) {
mostLikelyPrediction.segmentationResult.forEach(
({ grapheme, beginIndex, endIndex, drawingSegments }) => {
console.log(grapheme, beginIndex, endIndex);
drawingSegments.forEach(({ strokeIndex, beginPointIndex, endPointIndex }) => {
console.log(strokeIndex, beginPointIndex, endPointIndex);
});
},
);
}
Anhand dieser Informationen können Sie die erkannten Grapheme auf dem Canvas noch einmal aufspüren.
Vollständige Erkennung
Wenn die Erkennung abgeschlossen ist, können Sie Ressourcen freigeben, indem Sie die Methode clear()
für HandwritingDrawing
und die Methode finish()
für HandwritingRecognizer
aufrufen:
drawing.clear();
recognizer.finish();
Demo
Die Webkomponente <handwriting-textarea>
implementiert eine schrittweise verbesserte Bearbeitungssteuerung, die Handschrifterkennung unterstützt. Wenn Sie auf die Schaltfläche rechts unten im Bearbeitungssteuerelement klicken, wird der Zeichenmodus aktiviert. Wenn Sie die Zeichnung fertiggestellt haben, startet die Webkomponente die Erkennung automatisch und fügt den erkannten Text wieder dem Bearbeitungssteuerelement hinzu. Wenn die Handschrifterkennungs-API überhaupt nicht unterstützt wird oder die Plattform die angeforderten Funktionen nicht unterstützt, wird die Schaltfläche „Bearbeiten“ ausgeblendet. Das grundlegende Bearbeitungssteuerelement kann jedoch als <textarea>
verwendet werden.
Die Webkomponente bietet Eigenschaften und Attribute, mit denen das Erkennungsverhalten von außen definiert werden kann, einschließlich languages
und recognitiontype
. Sie können den Inhalt des Steuerelements über das Attribut value
festlegen:
<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>
Wenn Sie über Änderungen am Wert informiert werden möchten, können Sie auf das Ereignis input
warten.
Du kannst die Komponente mit dieser Demo auf Glitch ausprobieren. Wir empfehlen Ihnen außerdem, einen Blick auf den Quellcode zu werfen. Wenn Sie das Steuerelement in Ihrer Anwendung verwenden möchten, rufen Sie es von npm ab.
Sicherheit und Berechtigungen
Das Chromium-Team hat die Handschrifterkennungs-API gemäß den Grundprinzipien entwickelt und implementiert, die unter Zugriff auf leistungsstarke Webplattformfunktionen steuern definiert wurden, darunter Nutzersteuerung, Transparenz und Ergonomie.
Nutzersteuerung
Die Handschrifterkennungs-API kann vom Nutzer nicht deaktiviert werden. Sie ist nur für Websites verfügbar, die über HTTPS bereitgestellt werden, und kann nur aus dem Browser-Kontext der obersten Ebene aufgerufen werden.
Transparenz
Es wird nicht angezeigt, ob die Handschrifterkennung aktiv ist. Um Fingerprinting zu verhindern, implementiert der Browser Gegenmaßnahmen, z. B. wird dem Nutzer eine Berechtigungsaufforderung angezeigt, wenn er einen möglichen Missbrauch erkennt.
Berechtigungspersistenz
Die Handwriting Recognition API zeigt derzeit keine Aufforderungen zu Berechtigungen an. Daher muss die Berechtigung in keiner Weise beibehalten werden.
Feedback
Das Chromium-Team möchte mehr über Ihre Erfahrungen mit der Handschrifterkennungs-API erfahren.
Informationen zum API-Design
Gibt es etwas an der API, das nicht wie erwartet funktioniert? Oder fehlen Methoden oder Eigenschaften, um Ihre Idee umzusetzen? Haben Sie eine Frage oder einen Kommentar zum Sicherheitsmodell? Sie können ein Spezifikationsproblem im entsprechenden GitHub-Repository melden oder Ihre Gedanken zu einem vorhandenen Problem hinzufügen.
Problem mit der Implementierung melden
Haben Sie bei der Implementierung von Chromium einen Fehler gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation?
Reichen Sie einen Fehler unter new.crbug.com ein. Geben Sie dabei so viele Details wie möglich und eine einfache Anleitung zum Reproduzieren an. Geben Sie Blink>Handwriting
in das Feld Komponenten ein.
Mit Glitch lassen sich schnell und einfach Reproduktionen durchführen.
Unterstützung für die API zeigen
Möchten Sie die Handschrifterkennungs-API verwenden? Deine öffentliche Unterstützung hilft dem Chromium-Team, Funktionen zu priorisieren und anderen Browseranbietern zu zeigen, wie wichtig es ist, sie zu unterstützen.
Teile über die geplante Verwendung im WICG-Discourse-Thread mit. Sende einen Tweet an @ChromiumDev mit dem Hashtag #HandwritingRecognition
und teile uns mit, wo und wie du es verwendest.
Hilfreiche Links
- Erklärung
- Entwurf der Spezifikationen
- GitHub-Repository
- ChromeStatus
- Chromium-Programmfehler
- TAG-Überprüfung
- Intention eines Prototyps
- WebKit-Dev-Thread
- Mozilla-Standardposition
Danksagungen
Dieser Artikel wurde von Joe Medley, Honglin Yu und Jiewei Qian geprüft. Hero-Image von Samir Bouaked auf Unsplash