Met de API voor handschriftherkenning kunt u tekst herkennen aan handgeschreven invoer terwijl deze wordt ingevoerd.
Wat is de API voor handschriftherkenning?
Met de Handschriftherkenning API kunt u handschrift (inkt) van uw gebruikers omzetten in tekst. Sommige besturingssystemen beschikken al lang over dergelijke API's, en met deze nieuwe mogelijkheid kunnen uw webapps eindelijk van deze functionaliteit gebruikmaken. De conversie vindt rechtstreeks plaats op het apparaat van de gebruiker, werkt zelfs offline, en dat alles zonder dat er bibliotheken of services van derden nodig zijn.
Deze API implementeert zogenaamde "on-line" of bijna realtime herkenning. Dit betekent dat de handgeschreven invoer wordt herkend terwijl de gebruiker tekent, door de afzonderlijke streken vast te leggen en te analyseren. In tegenstelling tot "off-line" procedures zoals Optical Character Recognition (OCR), waarbij alleen het eindproduct bekend is, kunnen on-line algoritmen een hogere nauwkeurigheid bieden dankzij extra signalen zoals de tijdsvolgorde en druk van individuele inktstreken.
Voorgestelde gebruiksscenario's voor de API voor handschriftherkenning
Voorbeelden van toepassingen zijn:
- Notitie-applicaties waarbij gebruikers handgeschreven aantekeningen willen maken en deze naar tekst willen laten vertalen.
- Formulierentoepassingen waarbij gebruikers vanwege tijdsbeperkingen de stylus of vingerinvoer kunnen gebruiken.
- Spellen waarbij je letters of cijfers moet invullen, zoals kruiswoordpuzzels, galgje of sudoku.
Huidige status
De Handwriting Recognition API is beschikbaar vanaf (Chromium 99).
Hoe de handschriftherkennings-API te gebruiken
Functiedetectie
Detecteer browserondersteuning door te controleren op het bestaan van de createHandwritingRecognizer()
methode op het navigatorobject:
if ('createHandwritingRecognizer' in navigator) {
// 🎉 The Handwriting Recognition API is supported!
}
Kernconcepten
De Handschriftherkenning API zet handgeschreven invoer om in tekst, ongeacht de invoermethode (muis, aanraking, stylus). De API bestaat uit vier hoofdonderdelen:
- Een punt geeft aan waar de aanwijzer zich op een bepaald moment bevond.
- Een streek bestaat uit een of meer punten. De registratie van een streek start wanneer de gebruiker de aanwijzer neerzet (d.w.z. door op de primaire muisknop te klikken of het scherm aan te raken met de stylus of vinger) en eindigt wanneer de aanwijzer weer omhoog wordt gehaald.
- Een tekening bestaat uit één of meerdere penseelstreken. De daadwerkelijke herkenning vindt op dit niveau plaats.
- De herkenner is geconfigureerd met de verwachte invoertaal. Deze wordt gebruikt om een exemplaar van een tekening te maken met de herkennerconfiguratie toegepast.
Deze concepten worden geïmplementeerd als specifieke interfaces en woordenboeken, die ik straks zal bespreken.
Een herkenner maken
Om tekst uit handgeschreven invoer te herkennen, moet u een instantie van een HandwritingRecognizer
verkrijgen door navigator.createHandwritingRecognizer()
aan te roepen en er beperkingen aan door te geven. Beperkingen bepalen welk model voor handschriftherkenning moet worden gebruikt. Momenteel kunt u een lijst met talen opgeven in volgorde van voorkeur:
const recognizer = await navigator.createHandwritingRecognizer({
languages: ['en'],
});
De methode retourneert een belofte die wordt opgelost met een instantie van een HandwritingRecognizer
wanneer de browser aan uw verzoek kan voldoen. Anders wordt de belofte afgewezen met een foutmelding en is handschriftherkenning niet beschikbaar. Daarom is het raadzaam om eerst de ondersteuning van de herkenner voor specifieke herkenningsfuncties te raadplegen.
Ondersteuning voor queryherkenning
Door navigator.queryHandwritingRecognizer()
aan te roepen, kunt u controleren of het doelplatform de handschriftherkenningsfuncties ondersteunt die u wilt gebruiken. Deze methode gebruikt hetzelfde constraintobject als de navigator.createHandwritingRecognizer()
methode, met daarin de lijst met gevraagde talen. De methode retourneert een promise die wordt omgezet met een resultobject als er een compatibele herkenner wordt gevonden. Anders wordt de promise omgezet naar null
. In het volgende voorbeeld:
- wil teksten in het Engels detecteren
- krijg alternatieve, minder waarschijnlijke voorspellingen als deze beschikbaar zijn
- toegang krijgen tot het segmentatieresultaat, dat wil zeggen de herkende tekens, inclusief de punten en strepen waaruit ze bestaan
const result =
await navigator.queryHandwritingRecognizerSupport({
languages: ['en']
});
console.log(result?.textAlternatives); // true if alternatives are supported
console.log(result?.textSegmentation); // true if segmentation is supported
Als de browser de door de ontwikkelaar benodigde functie ondersteunt, wordt de waarde in het resultaatobject op true
gezet. Anders wordt deze op false
gezet. U kunt deze informatie gebruiken om bepaalde functies binnen uw applicatie in of uit te schakelen of om een nieuwe query voor een andere set talen te versturen.
Begin met tekenen
Binnen uw applicatie moet u een invoergebied aanbieden waar de gebruiker handgeschreven invoer kan invoeren. Om prestatieredenen is het aan te raden dit te implementeren met behulp van een canvasobject . De exacte implementatie hiervan valt buiten het bestek van dit artikel, maar u kunt de demo raadplegen om te zien hoe het werkt.
Om een nieuwe tekening te starten, roept u de methode startDrawing()
aan op de herkenner. Deze methode gebruikt een object met verschillende hints om het herkenningsalgoritme te verfijnen. Alle hints zijn optioneel:
- Het soort tekst dat wordt ingevoerd: tekst, e-mailadressen, cijfers of een afzonderlijk teken (
recognitionType
) - Het type invoerapparaat: muis-, aanraak- of stylusinvoer (
inputType
) - De voorgaande tekst (
textContext
) - Het aantal minder waarschijnlijke alternatieve voorspellingen dat moet worden geretourneerd (
alternatives
) - Een lijst met door de gebruiker identificeerbare tekens ("grafemen") die de gebruiker waarschijnlijk zal invoeren (
graphemeSet
)
De Handschriftherkenning API werkt goed samen met Pointer Events , die een abstracte interface bieden om invoer van elk aanwijsapparaat te verwerken. De argumenten van de pointer events bevatten het type pointer dat wordt gebruikt. Dit betekent dat u pointer events kunt gebruiken om het invoertype automatisch te bepalen. In het volgende voorbeeld wordt de tekening voor handschriftherkenning automatisch aangemaakt bij de eerste keer dat een pointerdown
-gebeurtenis in het handschriftgebied plaatsvindt. Omdat het pointerType
leeg kan zijn of ingesteld kan zijn op een eigen waarde, heb ik een consistentiecontrole geïntroduceerd om ervoor te zorgen dat alleen ondersteunde waarden worden ingesteld voor het invoertype van de tekening.
let drawing;
let activeStroke;
canvas.addEventListener('pointerdown', (event) => {
if (!drawing) {
drawing = recognizer.startDrawing({
recognitionType: 'text', // email, number, per-character
inputType: ['mouse', 'touch', 'stylus'].find((type) => type === event.pointerType),
textContext: 'Hello, ',
alternatives: 2,
graphemeSet: ['f', 'i', 'z', 'b', 'u'], // for a fizz buzz entry form
});
}
startStroke(event);
});
Voeg een streek toe
De pointerdown
-gebeurtenis is ook de juiste plek om een nieuwe penseelstreek te beginnen. Maak hiervoor een nieuwe instantie van HandwritingStroke
. Sla ook de huidige tijd op als referentiepunt voor de volgende punten die eraan worden toegevoegd:
function startStroke(event) {
activeStroke = {
stroke: new HandwritingStroke(),
startTime: Date.now(),
};
addPoint(event);
}
Voeg een punt toe
Nadat u de lijn hebt gemaakt, moet u het eerste punt er direct aan toevoegen. Omdat u later meer punten toevoegt, is het zinvol om de logica voor het maken van punten in een aparte methode te implementeren. In het volgende voorbeeld berekent de addPoint()
-methode de verstreken tijd op basis van het referentietijdstempel. De temporele informatie is optioneel, maar kan de herkenningskwaliteit verbeteren. Vervolgens worden de X- en Y-coördinaten van de pointergebeurtenis gelezen en wordt het punt aan de huidige lijn toegevoegd.
function addPoint(event) {
const timeElapsed = Date.now() - activeStroke.startTime;
activeStroke.stroke.addPoint({
x: event.offsetX,
y: event.offsetY,
t: timeElapsed,
});
}
De gebeurtenishandler pointermove
wordt aangeroepen wanneer de aanwijzer over het scherm wordt bewogen. Deze punten moeten ook aan de lijn worden toegevoegd. De gebeurtenis kan ook worden geactiveerd als de aanwijzer niet in de "neerwaartse" stand staat, bijvoorbeeld wanneer de cursor over het scherm wordt bewogen zonder de muisknop in te drukken. De gebeurtenishandler uit het volgende voorbeeld controleert of er een actieve lijn is en voegt het nieuwe punt daaraan toe.
canvas.addEventListener('pointermove', (event) => {
if (activeStroke) {
addPoint(event);
}
});
Tekst herkennen
Wanneer de gebruiker de aanwijzer weer optilt, kunt u de lijn aan uw tekening toevoegen door de addStroke()
methode aan te roepen. In het volgende voorbeeld wordt ook de activeStroke
gereset, zodat de pointermove
handler geen punten toevoegt aan de voltooide lijn.
Vervolgens is het tijd om de invoer van de gebruiker te herkennen door de getPrediction()
methode op de tekening aan te roepen. Herkenning duurt meestal minder dan een paar honderd milliseconden, dus u kunt indien nodig herhaaldelijk voorspellingen uitvoeren. Het volgende voorbeeld voert na elke voltooide streek een nieuwe voorspelling uit.
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));
});
Deze methode retourneert een belofte die resulteert in een array van voorspellingen, gesorteerd op waarschijnlijkheid. Het aantal elementen is afhankelijk van de waarde die je aan de hint alternatives
hebt doorgegeven. Je kunt deze array gebruiken om de gebruiker een keuze te bieden uit mogelijke matches en hem of haar een optie te laten selecteren. Je kunt er ook voor kiezen om gewoon de meest waarschijnlijke voorspelling te doen, wat ik in het voorbeeld doe.
Het voorspellingsobject bevat de herkende tekst en een optioneel segmentatieresultaat, dat ik in de volgende sectie zal bespreken.
Gedetailleerde inzichten met segmentatieresultaten
Indien ondersteund door het doelplatform, kan het voorspellingsobject ook een segmentatieresultaat bevatten. Dit is een array met alle herkende handschriftsegmenten, een combinatie van het herkende, door de gebruiker identificeerbare teken ( grapheme
), de positie ervan in de herkende tekst ( beginIndex
, endIndex
) en de streken en punten waarmee het is gemaakt.
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);
});
},
);
}
Deze informatie kunt u gebruiken om de herkende grafemen op het canvas opnieuw op te sporen.
Volledige erkenning
Nadat de herkenning is voltooid, kunt u bronnen vrijmaken door de clear()
methode aan te roepen op HandwritingDrawing
en de finish()
methode op HandwritingRecognizer
:
drawing.clear();
recognizer.finish();
Demonstratie
De webcomponent <handwriting-textarea>
implementeert een steeds verbeterde bewerkingsfunctie die handschriftherkenning ondersteunt. Door op de knop in de rechteronderhoek van de bewerkingsfunctie te klikken, activeert u de tekenmodus. Wanneer u klaar bent met tekenen, start de webcomponent automatisch de herkenning en voegt de herkende tekst weer toe aan de bewerkingsfunctie. Als de API voor handschriftherkenning helemaal niet wordt ondersteund, of als het platform de gevraagde functies niet ondersteunt, is de bewerkingsknop verborgen. De basisbewerkingsfunctie blijft echter bruikbaar als <textarea>
.
De webcomponent biedt eigenschappen en attributen om het herkenningsgedrag van buitenaf te definiëren, inclusief languages
en recognitiontype
. U kunt de inhoud van het besturingselement instellen via het value
attribuut:
<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>
Om op de hoogte te blijven van eventuele wijzigingen in de waarde, kunt u naar de input
luisteren.
Je kunt het component uitproberen met deze demo op Glitch . Bekijk ook zeker de broncode . Om het besturingselement in je applicatie te gebruiken, kun je het downloaden van npm .
Beveiliging en machtigingen
Het Chromium-team heeft de API voor handschriftherkenning ontworpen en geïmplementeerd op basis van de kernprincipes die zijn gedefinieerd in Controlling Access to Powerful Web Platform Features , waaronder gebruikerscontrole, transparantie en ergonomie.
Gebruikerscontrole
De handschriftherkennings-API kan niet door de gebruiker worden uitgeschakeld. Deze is alleen beschikbaar voor websites die via HTTPS worden aangeboden en kan alleen worden aangeroepen vanuit de browseromgeving op het hoogste niveau.
Transparantie
Er is geen indicatie of handschriftherkenning actief is. Om vingerafdrukherkenning te voorkomen, implementeert de browser tegenmaatregelen, zoals het tonen van een toestemmingsvraag aan de gebruiker wanneer mogelijk misbruik wordt gedetecteerd.
Permissiepersistentie
De Handschriftherkenning API toont momenteel geen toestemmingsprompts. Toestemming hoeft dus op geen enkele manier te worden bewaard.
Feedback
Het Chromium-team wil graag uw ervaringen met de Handschriftherkenning API horen.
Vertel ons over het API-ontwerp
Werkt er iets aan de API dat niet werkt zoals je had verwacht? Of ontbreken er methoden of eigenschappen die je nodig hebt om je idee te implementeren? Heb je een vraag of opmerking over het beveiligingsmodel? Dien een spec-issue in op de betreffende GitHub-repository of voeg je mening toe aan een bestaand issue.
Meld een probleem met de implementatie
Heb je een bug gevonden in de implementatie van Chromium? Of wijkt de implementatie af van de specificatie? Meld een bug op new.crbug.com . Zorg ervoor dat je zoveel mogelijk details geeft, eenvoudige instructies voor het reproduceren en Blink>Handwriting
invoert in het vak 'Componenten' .
Toon ondersteuning voor de API
Bent u van plan de Handschriftherkenning API te gebruiken? Uw publieke steun helpt het Chromium-team bij het prioriteren van functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.
Deel hoe je het gaat gebruiken in de WICG Discourse-thread . Stuur een tweet naar @ChromiumDev met de hashtag #HandwritingRecognition
en laat ons weten waar en hoe je het gebruikt.
Nuttige links
- Uitlegger
- Spec-ontwerp
- GitHub-repository
- Chrome-status
- Chromium-bug
- TAG-beoordeling
- Intentie om prototype te maken
- WebKit-Dev-thread
- Mozilla-standaardpositie
Dankbetuigingen
Dit document is beoordeeld door Joe Medley , Honglin Yu en Jiewei Qian.