זיהוי המשתמשים שלך' כתב יד

ממשק ה-API לזיהוי כתבי יד מאפשר לכם לזהות טקסט מקלט בכתב יד בזמן ההתרחשות שלו.

מהו ממשק ה-API לזיהוי כתבי יד?

ה-API לזיהוי כתבי יד מאפשר להמיר כתב יד (דיו) מהמשתמשים שלכם לטקסט. חלק ממערכות ההפעלה כוללות כבר זמן רב ממשקי API כאלה, ובזכות היכולת החדשה הזו, אפליקציות האינטרנט שלכם להשתמש בפונקציונליות הזאת. ההמרה מתבצעת ישירות במכשיר של המשתמש, אפילו במצב אופליין, והכל בלי להוסיף ספריות או שירותים של צד שלישי.

ה-API הזה מטמיע את מה שנקרא "on-line" או זיהוי כמעט בזמן אמת. המשמעות היא קלט בכתב יד מזוהה בזמן שהמשתמש מצייר אותו על ידי תיעוד וניתוח של תנועות. לעומת 'אופליין' הליכים כמו זיהוי תווים אופטי (OCR), כאשר רק המוצר הסופי ידוע, אלגוריתמים אונליין יכולים לספק רמת דיוק גבוהה יותר אותות נוספים, כמו רצף הזמן והלחץ של משיכות דיו בודדות.

תרחישים לדוגמה של הצעות לשימוש בממשק ה-API לזיהוי כתבי יד

דוגמאות לשימושים:

  • אפליקציות לרישום הערות שבהן המשתמשים רוצים לתעד פתקים בכתב יד ולתרגם אותם לטקסט.
  • אפליקציות ב-Forms, שבהן המשתמשים יכולים להשתמש בקלט עט או באצבע בגלל מגבלות זמן.
  • משחקים שמחייבים מילוי של אותיות או מספרים, כמו תשבצים, תליינים או סודוקו.

הסטטוס הנוכחי

ממשק ה-API לזיהוי כתבי יד זמין מ-(Chromium 99).

איך משתמשים בממשק ה-API לזיהוי כתבי יד

זיהוי תכונות

גילוי תמיכה בדפדפן על ידי בדיקת קיומו של ה-method createHandwritingRecognizer() באובייקט הניווט:

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

מושגי ליבה

ה-API לזיהוי כתב יד ממיר קלט בכתב יד לטקסט, ללא קשר לשיטת הקלט (עכבר, מגע, עט). ה-API כולל ארבע ישויות עיקריות:

  1. נקודה מייצגת את המיקום של הסמן בזמן מסוים.
  2. קו חוצה כולל נקודה אחת או יותר. ההקלטה של הקו מתחילה כשהמשתמש מוסיף את הסמן למטה (כלומר, לוחץ על לחצן העכבר הראשי, או נוגע במסך באמצעות העט או אצבע) ומסתיימת כשהוא מרים את הסמן בחזרה למעלה.
  3. שרטוט כולל קו חוצה אחד או יותר. הזיהוי בפועל מתבצע ברמה הזו.
  4. המזהה מוגדר עם שפת הקלט הצפויה. הוא משמש ליצירת מכונה של שרטוט עם תצורת המזהה.

העקרונות האלה מיושמים כממשקים ומילונים ספציפיים, ואסביר אותם בקרוב.

ישויות הליבה של ממשק ה-API לזיהוי כתבי יד: נקודה אחת או יותר מורכבות מקו חוצה, קו חוצה אחד או יותר יוצר שרטוט שהמזהה יוצר. הזיהוי בפועל מתבצע ברמת הציור.

יצירת מזהה

כדי לזהות טקסט מקלט בכתב יד, צריך להשיג מופע של HandwritingRecognizer על ידי קריאה ל-navigator.createHandwritingRecognizer() והעברת מגבלות אליה. המגבלות קובעות את המודל לזיהוי כתב יד שבו צריך להשתמש. נכון לעכשיו, יכולים לציין רשימה של שפות לפי סדר העדפה:

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

ה-method מחזירה הבטחה לפתרון עם מופע של HandwritingRecognizer כאשר יוכל למלא את הבקשה שלך. אחרת, הוא ידחה את ההבטחה עם שגיאה, זיהוי כתב יד לא יהיה זמין. לכן כדאי להריץ שאילתה בתמיכה של המזהה בתכונות זיהוי מסוימות.

תמיכה של הכלי לזיהוי שאילתות

באמצעות קריאה אל navigator.queryHandwritingRecognizerSupport(), אפשר לבדוק אם פלטפורמת היעד תומכת בתכונות זיהוי כתב יד שבהן מתכוונים להשתמש. במשפט הבא, מפתח:

  • רוצה לזהות טקסטים באנגלית
  • קבלת תחזיות חלופיות ופחות סבירות, כשהן זמינות
  • לקבל גישה לתוצאת הפילוח, כלומר התווים המזוהים, כולל הנקודות התנועות שמהן הן מורכבות
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

השיטה מחזירה הבטחה לפתרון עם אובייקט תוצאה. אם הדפדפן תומך בתכונה הזו שצוין על ידי המפתח, הערך שלו יוגדר כ-true. אחרת, הוא יוגדר כ-false. ניתן להשתמש במידע זה כדי להפעיל או להשבית תכונות מסוימות בתוך האפליקציה, או להתאים את השאילתה ולשלוח שאילתה חדשה.

התחלת שרטוט

בתוך האפליקציה, עליכם להציע אזור להזנת קלט שבו המשתמש יוצר את כתב היד רשומות. כדי להשיג ביצועים טובים, מומלץ ליישם את זה בעזרת canvas object. המדויק של חלק זה לא נכלל במאמר הזה, אבל אפשר לעיין בהדגמה (דמו). כדי לראות איך אפשר לעשות את זה.

כדי להתחיל שרטוט חדש, צריך להפעיל את השיטה startDrawing() במזהה. השיטה הזו שמכיל רמזים שונים כדי לשפר את האלגוריתם לזיהוי. כל הרמזים הם אופציונליים:

  • סוג הטקסט שהוזן: טקסט, כתובות אימייל, מספרים או תו ספציפי (recognitionType)
  • סוג המכשיר לקליטת נתונים: קלט עכבר, מגע או עט (inputType)
  • הטקסט הקודם (textContext)
  • מספר החיזויים החלופיים שצריכים להיות פחות צפויים (alternatives)
  • רשימה של תווים שניתנים לזיהוי על ידי משתמש ('גרפים') שסביר להניח שהמשתמש יזין (graphemeSet)

ה-API לזיהוי כתב יד פועל היטב עם אירועי מצביע שמספקים ממשק מופשט לקבלת קלט מכל התקן הצבעה. הארגומנטים של אירועי המצביע מכילים סוג הסמן שבו נעשה שימוש. כלומר, אפשר להשתמש באירועי מצביע כדי לקבוע את סוג הקלט באופן אוטומטי. בדוגמה הבאה, השרטוט לזיהוי כתב יד מופעל באופן אוטומטי נוצר באירוע הראשון של אירוע pointerdown באזור של כתב היד. כי יכול להיות שהשדה pointerType ריק או מוגדר לערך קנייני. הוספתי בדיקת עקביות כדי לבצע מוודאים שרק ערכים נתמכים מוגדרים לסוג הקלט של השרטוט.

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

הוספת קו

האירוע pointerdown הוא גם המקום הנכון להתחיל בו שבץ חדש. כדי לעשות את זה, צריך ליצור מופע של HandwritingStroke. כמו כן, עליכם לאחסן את השעה הנוכחית כנקודת התייחסות את הנקודות הבאות שנוספו אליה:

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

הוסף נקודה

לאחר יצירת הקו, צריך להוסיף אליו את הנקודה הראשונה באופן ישיר. ככל שיתווספו עוד בהמשך, הגיוני ליישם את הלוגיקה של יצירת הנקודות בשיטה נפרדת. ב בדוגמה הבאה, השיטה addPoint() מחשבת את הזמן שחלף מחותמת הזמן של ההפניה. המידע על הזמן הוא אופציונלי, אבל הוא יכול לשפר את איכות הזיהוי. לאחר מכן, הוא קורא את ה-X הקואורדינטות Y מאירוע הסמן ומוסיפות את הנקודה לקו הנוכחי.

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

מתבצעת קריאה למטפל באירועים של pointermove כשהסמן מועבר במסך. הנקודות האלה צריך להוסיף גם קו חוצה. אפשר להגביר את האירוע גם אם הסמן לא נמצא "down" במצב הזה, לדוגמה כשמזיזים את הסמן על המסך בלי ללחוץ על העכבר לחצן. הגורם המטפל באירועים מהדוגמה הבאה בודק אם קיים קו פעיל, ומוסיף את הרכיב נקודה חדשה.

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

זיהוי טקסט

כשהמשתמש מרים שוב את הסמן, אפשר להוסיף את הקו לשרטוט על ידי קריאה לפעולה אמצעי תשלום אחד (addStroke()). הדוגמה הבאה גם מאפסת את activeStroke, כך שהמאפיין pointermove ה-handler לא יוסיף נקודות למסגרת שהושלם.

בשלב הבא, הגיע הזמן לזהות את הקלט של המשתמש, על ידי קריאה ל-method getPrediction() שרטוט. בדרך כלל הזיהוי נמשך פחות מכמה מאות אלפיות השנייה, כך שאפשר להריץ אותו שוב ושוב ויצירת חיזויים במקרה הצורך. הדוגמה הבאה מפעילה חיזוי חדש אחרי כל השלמה של תנועת גולשים.

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

השיטה הזו מחזירה הבטחה שמסתיימת במערך של חיזויים, לפי הסדר שלהם היא הכי גבוהה. מספר הרכיבים תלוי בערך שהעברת לרמז alternatives. שלך אפשר להשתמש במערך הזה כדי להציג למשתמש אפשרויות של התאמות אפשריות, ולבקש ממנו לבחור כאפשרות. לחלופין, תוכלו פשוט להשתמש בחיזוי עם ההסתברות הגבוהה ביותר, וזה מה שאעשה לדוגמה.

אובייקט החיזוי מכיל את הטקסט המזוהה ותוצאת פילוח אופציונלית, בקטע הבא.

תובנות מפורטות עם תוצאות פילוח

אם פלטפורמת היעד נתמכת, גם אובייקט החיזוי יכול להכיל תוצאת פילוח. זהו מערך שמכיל את כל קטעי כתב היד שזוהו, שילוב של תו שמאפשר זיהוי של המשתמש (grapheme) יחד עם המיקום שלו בטקסט שזוהה (beginIndex, endIndex) ואת הקווים והנקודות שיצרו אותו.

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

אפשר להשתמש במידע הזה כדי לאתר שוב את הגרפים שזוהו באזור העריכה.

תיבות משורטטות סביב כל גרפים מזוהה

השלמת הזיהוי

לאחר השלמת הזיהוי, ניתן לפנות משאבים על ידי קריאה ל-method clear() HandwritingDrawing, וה-method finish() ב-HandwritingRecognizer:

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

הדגמה (דמו)

רכיב האינטרנט <handwriting-textarea> מיישם שיפור הדרגתי, עם אפשרות עריכה של כתב יד וזיהוי אובייקטים. כדי להפעיל את העריכה, לוחצים על הלחצן בפינה השמאלית התחתונה של פקד העריכה את מצב השרטוט. בסיום השרטוט, רכיב האינטרנט יפעיל אוטומטית בזיהוי הטקסט שזוהה, והוספת הטקסט שזוהה לפקד העריכה. אם תכונת זיהוי כתב היד אין תמיכה ב-API בכלל, או שהפלטפורמה לא תומכת בתכונות הנדרשות, אפשר ללחוץ על לחצן העריכה יוסתר. אבל אפשר להמשיך להשתמש בפקד העריכה הבסיסי כ-<textarea>.

רכיב האינטרנט מציע מאפיינים ומאפיינים להגדרת התנהגות הזיהוי מחוץ לבית, כולל languages ו-recognitiontype. ניתן להגדיר את התוכן של אמצעי הבקרה דרך מאפיין value:

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

כדי לקבל מידע על שינויים בערך, אפשר להאזין לאירוע input.

אפשר לנסות את הרכיב באמצעות ההדגמה הזו ב-Glitch. חשוב גם לעיין קוד מקור. כדי להשתמש בפקד קבל אותו מ-npm.

אבטחה והרשאות

צוות Chromium עיצב והטמיע את ממשק ה-API לזיהוי כתבי יד באמצעות עקרונות הליבה מוגדרת בקטע שליטה בגישה לתכונות מתקדמות של פלטפורמת אינטרנט, כולל משתמשים שליטה, שקיפות וארגונומיה.

שליטת משתמשים

המשתמשים לא יכולים להשבית את ממשק ה-API לזיהוי כתבי יד. האפשרות הזו זמינה רק באתרים נמסרות דרך HTTPS, וניתן לקרוא אותו רק מהקשר הגלישה ברמה העליונה.

שקיפות

אין אינדיקציה אם זיהוי כתב יד פעיל. כדי למנוע יצירה של טביעת אצבע דיגיטלית (fingerprinting), הדפדפן שמבצעת אמצעים נגדיים, כמו הצגת בקשת הרשאה למשתמש כשהוא מזהה התנהלות פוגעת אפשרית.

שמירת ההרשאות

בשלב הזה לא מוצגות בקשות להרשאות מה-API של זיהוי כתב יד. כלומר, ההרשאה לא צריכה להישמר בכל דרך שהיא.

משוב

צוות Chromium רוצה לשמוע על החוויה שלך עם ממשק ה-API של זיהוי כתב יד.

מתארים את עיצוב ה-API

האם יש משהו ב-API שלא פועל כצפוי? או שחסרות שיטות או מאפיינים שאתם צריכים ליישום הרעיון שלכם? יש לכם שאלה או הערה בנושא האבטחה מודל טרנספורמר? שולחים בעיית מפרט במאגר GitHub המתאים, או מוסיפים את דעתכם קיימת.

דיווח על בעיה בהטמעה

מצאת באג בהטמעה של Chromium? או שההטמעה שונה מהמפרט? דווחו על באג בכתובת new.crbug.com. כדאי לכלול כמה שיותר פרטים, הוראות פשוטות לשחזור, ומזינים Blink>Handwriting בתיבה רכיבים. Glitch היא אפשרות טובה לשיתוף תגובות מהירות וקלות.

הצגת תמיכה ב-API

האם את/ה מתכנן/ת להשתמש בממשק ה-API לזיהוי כתבי יד? התמיכה הציבורית שלך עוזרת לצוות Chromium היא גם מראה לספקי דפדפנים אחרים עד כמה זה חשוב לתמוך בהם.

תוכלו לשתף את האופן שבו אתם מתכננים להשתמש בו בשרשור השיחה של WICG. שליחת ציוץ אל @ChromiumDev משתמשים ב-hashtag #HandwritingRecognition וספר לנו איפה אתה משתמש בו ובאיזה אופן.

אישורים

המאמר הזה נבדקה על ידי ג'ו מדלי, Honglin Yu וג'ייווי קיאן. תמונה ראשית (Hero) מאת Samir Bouaked מופעל ביטול הפתיחה.