Rozpoznawaj pismo odręczne użytkowników

Interfejs ręcznie rozpoznawanego pisma odręcznego umożliwia rozpoznawanie tekstu generowanego odręcznie.

Czym jest interfejs Handwriter Recognition API?

Interfejs API rozpoznawania pisma odręcznego umożliwia konwertowanie pisma odręcznego (atramentem) użytkowników na tekst. Niektóre systemy operacyjne od dawna obsługują takie interfejsy API, a dzięki tej nowej funkcji aplikacje internetowe mogą aby użytkownicy mogli wreszcie korzystać z tej funkcji. Konwersja odbywa się bezpośrednio na urządzeniu użytkownika, działa nawet w trybie offline – bez dodawania żadnych bibliotek ani usług innych firm.

Ten interfejs API implementuje tak zwane „online” czy też rozpoznawania w czasie zbliżonym do rzeczywistego. Oznacza to, że odręczne znaki wpisywane przez użytkownika są rozpoznawane podczas rysowania kilka ruchów. W przeciwieństwie do trybu offline takich jak optyczne rozpoznawanie znaków (OCR), gdzie że znany jest tylko produkt końcowy, algorytmy online mogą zwiększyć dokładność dzięki dodatkowych sygnałów, takich jak sekwencja czasowa i ciśnienie poszczególnych pociągnięć atramentu.

Sugerowane przypadki użycia interfejsu Handwrite Recognition API

Przykładowe zastosowania:

  • Aplikacje do robienia notatek, w których użytkownicy chcą tworzyć odręczne notatki i je tłumaczyć w formie tekstu.
  • Formularze, w których ze względu na ograniczenia czasowe użytkownicy mogą korzystać z pisania palcem lub piórem.
  • Gry wymagające wpisania liter lub cyfr, np. krzyżówki, hangman czy sudoku.

Obecny stan,

Interfejs ręcznie rozpoznawanego pisma odręcznego jest dostępny w Chromium 99.

Jak korzystać z interfejsu Handwriter Recognition API

Wykrywanie cech

Wykryj obsługę przeglądarki, sprawdzając, czy istnieje metoda createHandwritingRecognizer(). na obiekcie nawigatorskim:

if ('createHandwritingRecognizer' in navigator) {
  // 🎉 The Handwriting Recognition API is supported!
}

Podstawowe pojęcia

Interfejs API rozpoznawania pisma odręcznego konwertuje odręczne dane wejściowe na tekst niezależnie od metody wprowadzania (mysz, dotyk, długopis). Interfejs API składa się z 4 głównych elementów:

  1. Punkt wskazuje miejsce, w którym w danym momencie znajdował się wskaźnik.
  2. Styl składa się z jednego lub większej liczby punktów. Rejestracja pociągnięcia rozpoczyna się, gdy użytkownik skieruje kursor w dół (np. kliknie główny przycisk myszy, dotknie ekranu rysikiem lub palec), a kończy, gdy uniesie wskaźnik z powrotem.
  3. Rysunek składa się z jednego lub kilku pociągnięć. Na tym poziomie odbywa się rzeczywiste rozpoznawanie.
  4. Rozpoznawanie jest skonfigurowane z oczekiwanym językiem wprowadzania. Służy do tworzenia instancji rysunku z zastosowaną konfiguracją rozpoznawania.

Pojęcia te są implementowane jako specjalne interfejsy i słowniki, które omówimy za chwilę.

Podstawowe elementy interfejsu HandWrite Recognition API: co najmniej 1 punkt tworzy kreskę – jeden lub więcej pociągnięć to rysunek, który jest tworzony przez moduł rozpoznawania. Rzeczywiste rozpoznawanie odbywa się na poziomie rysunku.

Tworzę moduł rozpoznawania

Aby rozpoznać odręczny tekst, musisz uzyskać HandwritingRecognizer po wywołaniu navigator.createHandwritingRecognizer() i przekazaniu ograniczeń . Ograniczenia określają model rozpoznawania pisma odręcznego, którego należy używać. Obecnie może określić listę języków zgodnie z preferencjami:

const recognizer = await navigator.createHandwritingRecognizer({
  languages: ['en'],
});

Metoda zwraca obietnicę rozwiązaną za pomocą instancji HandwritingRecognizer, gdy przeglądarka może zrealizować to żądanie. W przeciwnym razie odrzuci obietnicę z błędem. funkcja rozpoznawania pisma odręcznego nie będzie dostępna. Dlatego warto wysyłać zapytania do .

Obsługa modułu rozpoznawania zapytań

Wywołując navigator.queryHandwritingRecognizerSupport(), możesz sprawdzić, czy platforma docelowa obsługuje te funkcje rozpoznawania pisma odręcznego, których chcesz używać. W poniższym przykładzie para klucz-wartość deweloper:

  • Chce wykrywać teksty po angielsku
  • otrzymuj alternatywne, mniej prawdopodobne prognozy, gdy są dostępne
  • uzyskać dostęp do wyniku podziału na segmenty, tj. do rozpoznanych znaków, w tym punktów pociągnięcia z niej
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

Metoda zwraca obietnicę rozwiązaną za pomocą obiektu wynikowego. Jeśli przeglądarka obsługuje tę funkcję określony przez programistę, jego wartość zostanie ustawiona na true. W przeciwnym razie ma ona wartość false. Możesz użyć tych informacji, by włączyć lub wyłączyć określone funkcje w swojej aplikacji, a także dostosować zapytanie i wysłać nowe.

Rozpocznij rysunek

W aplikacji musisz udostępnić obszar do wprowadzania danych, w którym użytkownik może wpisać odręcznie wpisów. Ze względu na wydajność zalecamy wdrożenie tego rozwiązania za pomocą canvas obiekt. Dokładny implementacji tej części nie leży w zakresach tego artykułu, ale możesz zajrzeć do wersji demonstracyjnej jak to zrobić.

Aby rozpocząć nowy rysunek, wywołaj metodę startDrawing() w module rozpoznawania. Ta metoda wymaga z różnymi wskazówkami, aby dostroić algorytm rozpoznawania. Wszystkie wskazówki są opcjonalne:

  • Rodzaj wprowadzanego tekstu: tekst, adresy e-mail, cyfry lub pojedynczy znak (recognitionType)
  • Typ urządzenia wejściowego: myszka, dotyk lub pióro (inputType)
  • Poprzedni tekst (textContext)
  • Liczba mniej prawdopodobnych prognoz alternatywnych, które powinny zostać zwrócone (alternatives)
  • Lista znaków umożliwiających identyfikację użytkownika („grafemów”), które użytkownik najprawdopodobniej wpisze (graphemeSet)

Interfejs HandWrite Recognition API dobrze działa Zdarzenia wskaźnika, które dają wartość abstrakcyjny interfejs do przetwarzania danych wejściowych z dowolnego urządzenia wskazującego. Argumenty zdarzenia wskaźnika zawierają typ używanego wskaźnika. Oznacza to, że możesz używać zdarzeń wskaźnika do określenia typu danych wejściowych automatycznie. W poniższym przykładzie rysunek dotyczący rozpoznawania pisma odręcznego jest automatycznie utworzona przy pierwszym wystąpieniu zdarzenia pointerdown na obszarze pisma odręcznego. Jako Pole pointerType może być puste lub mieć wartość zastrzeżoną. Wprowadziłem(-am) kontrolę spójności, aby sprawdź, czy w typie danych wejściowych rysunku są ustawione tylko obsługiwane wartości.

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);
});

Dodaj kreskę

Zdarzenie pointerdown to też dobry moment, by zacząć nowy styl. Aby to zrobić, utwórz nowy wystąpienia HandwritingStroke. Zapisz też bieżącą godzinę jako punkt odniesienia kolejne dodane do niego punkty:

function startStroke(event) {
  activeStroke = {
    stroke: new HandwritingStroke(),
    startTime: Date.now(),
  };
  addPoint(event);
}

Dodaj punkt

Po utworzeniu kreski musisz bezpośrednio dodać do niej pierwszy punkt. W miarę dodawania kolejnych wspomnianych później, warto wdrożyć logikę tworzenia punktów w osobnej metodzie. W w poniższym przykładzie metoda addPoint() oblicza czas, który upłynął na podstawie sygnatury czasowej odwołania. Informacje o czasie są opcjonalne, ale mogą poprawić jakość rozpoznawania. Następnie odczytuje znaki X i Współrzędne Y ze zdarzenia wskaźnika i dodają punkt do bieżącej linii.

function addPoint(event) {
  const timeElapsed = Date.now() - activeStroke.startTime;
  activeStroke.stroke.addPoint({
    x: event.offsetX,
    y: event.offsetY,
    t: timeElapsed,
  });
}

Moduł obsługi zdarzeń pointermove jest wywoływany, gdy wskaźnik przesuwa się po ekranie. Te punkty które trzeba dodać do kreski. Zdarzenie można też zgłosić, jeśli wskaźnik nie znajduje się w „w dół” np. podczas przesuwania kursora po ekranie bez naciskania myszy. Przycisk Moduł obsługi zdarzeń z poniższego przykładu sprawdza, czy istnieje aktywny styl, i dodaje do nowego punktu.

canvas.addEventListener('pointermove', (event) => {
  if (activeStroke) {
    addPoint(event);
  }
});

Rozpoznaj tekst

Gdy użytkownik ponownie podniesie wskaźnik, możesz dodać do rysunku kreskę, wywołując jego Metoda addStroke(). Poniższy przykład resetuje również zasadę activeStroke, więc pointermove moduł obsługi nie dodaje punktów do zakończonej kreski.

Następnie trzeba rozpoznać dane wejściowe użytkownika przez wywołanie metody getPrediction() w rysunek. Rozpoznawanie trwa zwykle mniej niż kilkaset milisekund, więc możesz pracować wielokrotnie i generowanie prognoz. W poniższym przykładzie uruchamiana jest nowa prognoza po każdym zakończeniu pociągnięcia.

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));
});

Ta metoda zwraca obietnicę, która jest rozwiązywana z tablicą prognoz uporządkowanych według prawdopodobieństwa. Liczba elementów zależy od wartości przekazanej do podpowiedzi alternatives. Ty może użyć tej tablicy, aby przedstawić użytkownikowi jedną z możliwych dopasowań i poprosić go o wybranie . Możesz również wybrać najbardziej prawdopodobną prognozę. przykład.

Obiekt prognozy zawiera rozpoznany tekst i opcjonalny wynik segmentacji, który w następnej sekcji.

Szczegółowe statystyki z wynikami segmentacji

Jeśli platforma docelowa go obsługuje, obiekt prognozy może też zawierać wynik podziału na segmenty. Jest to tablica zawierająca cały rozpoznany segment pisma odręcznego, kombinację rozpoznanych znak rozpoznawalny użytkownika (grapheme) wraz z jego pozycją w rozpoznanym tekście (beginIndex, endIndex) oraz pociągnięcia i punkty, które go tworzą.

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);
      });
    },
  );
}

Możesz użyć tych informacji, aby ponownie odnaleźć rozpoznane grafemy na płótnie.

Każdy rozpoznawany grafem jest rysowany w ramkach

Pełne uznanie

Po zakończeniu rozpoznawania możesz zwolnić zasoby, wywołując metodę clear() w HandwritingDrawing i metoda finish() w HandwritingRecognizer:

drawing.clear();
recognizer.finish();

Prezentacja

Komponent internetowy <handwriting-textarea> implementuje komponent stopniowo udoskonalone, funkcje edycji umożliwiające pisanie odręczne i rozpoznawanie obiektów. Klikając przycisk w prawym dolnym rogu elementu sterującego edycji, aktywujesz do trybu rysowania. Gdy skończysz rysowanie, komponent internetowy automatycznie uruchomi rozpoznawania tekstu i dodać go z powrotem do elementu sterującego. Rozpoznawanie pisma odręcznego Interfejs API nie jest w ogóle obsługiwany lub platforma nie obsługuje żądanych funkcji, przycisk edycji zostaną ukryte. Podstawowe elementy sterujące edycji można nadal używać jako elementu <textarea>.

Komponent internetowy zawiera właściwości i atrybuty definiujące zachowanie rozpoznawania na zewnątrz, w tym languages i recognitiontype. Zawartość elementu sterującego możesz ustawić w Atrybut value:

<handwriting-textarea languages="en" recognitiontype="text" value="Hello"></handwriting-textarea>

Aby otrzymywać informacje o zmianach wartości, możesz nasłuchiwać zdarzenia input.

Możesz wypróbować komponent, korzystając z tej wersji demonstracyjnej w Glitch. Koniecznie zapoznaj się też kodu źródłowego. Aby użyć elementu sterującego w aplikacji, uzyskaj ją z npm.

Bezpieczeństwo i uprawnienia

Zespół Chromium zaprojektował i wdrożył interfejs Handwriter Recognition API, kierując się kluczowymi zasadami w artykule Kontrola nad dostępem do zaawansowanych funkcji platform internetowych, w tym kontrolę, przejrzystość i ergonomię.

Kontrola użytkowników

Użytkownik nie może wyłączyć interfejsu Handwriter Recognition API. Jest dostępny tylko w przypadku witryn jest dostarczana przez HTTPS i może być wywoływana tylko z kontekstu przeglądania najwyższego poziomu.

Przejrzystość

Nie wiadomo, czy rozpoznawanie pisma odręcznego jest aktywne. Aby zapobiec pobieraniu odcisków cyfrowych, stosuje środki zaradcze, takie jak wyświetlanie użytkownikowi prośby o zgodę, gdy wykryje możliwe nadużycie.

Trwałość uprawnień

Interfejs HandWrite Recognition API nie wyświetla obecnie żadnych promptów o uprawnieniach. W związku z tym uprawnienie nie musi być w żaden sposób utrwalana.

Prześlij opinię

Zespół Chromium chce dowiedzieć się więcej o Twoich doświadczeniach z interfejsem ręcznie pisma odręcznego Recognition API.

Opowiedz nam o konstrukcji interfejsu API

Czy jest coś, co nie działa w interfejsie API zgodnie z oczekiwaniami? Czy może brakuje tu metod lub właściwości potrzebne do realizacji pomysłu? Masz pytanie lub komentarz na temat zabezpieczeń model? Zgłoś problem ze specyfikacją w odpowiednim repozytorium GitHub lub dodaj swoje uwagi do do istniejącego problemu.

Zgłoś problem z implementacją

Czy wystąpił błąd związany z implementacją Chromium? Czy implementacja różni się od specyfikacji? Zgłoś błąd na new.crbug.com. Podaj jak najwięcej szczegółów. instrukcje dotyczące ponownego odtwarzania i wpisz Blink>Handwriting w polu Komponenty. Usługa Glitch świetnie nadaje się do szybkiego i łatwego udostępniania poprawek.

Pokaż wsparcie dla interfejsu API

Czy planujesz korzystać z interfejsu Handwriter Recognition API? Twoje publiczne wsparcie pomaga zespołowi Chromium nadaje priorytet funkcjom i pokazuje innym dostawcom przeglądarek, jak ważne jest ich wsparcie.

Poinformuj nas, jak zamierzasz korzystać z tego narzędzia w wątku poświęconym dysku WICG. Wyślij tweeta do @ChromiumDev za pomocą hashtagu #HandwritingRecognition. i daj nam znać, gdzie i jak go używasz.

Podziękowania

Ten artykuł napisali Joe Medley, Honglin Yu i Jiewei Qian. Baner powitalny: Samir Bouaked na kanale Odchylenie.