التعرف على الكتابة اليدوية للمستخدمين

تتيح لك واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد التعرُّف على النص من الإدخال المكتوب بخط اليد أثناء حدوثه.

ما هي واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد؟

تتيح لك واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد تحويل الكتابة اليدوية (الحبر) من المستخدمين إلى نص. تشتمل بعض أنظمة التشغيل على واجهات برمجة التطبيقات هذه منذ فترة طويلة، وباستخدام هذه الإمكانية الجديدة، يمكن لتطبيقات الويب هذه الوظيفة أخيرًا. وتتم عملية التحويل مباشرةً على جهاز المستخدم، وتعمل حتى في وضع عدم الاتصال بالإنترنت، وكل ذلك بدون إضافة أي مكتبات أو خدمات تابعة لجهات خارجية.

تنفِّذ واجهة برمجة التطبيقات هذه ما يُعرف باسم "على الإنترنت" أو التعرّف على المحتوى في الوقت الفعلي تقريبًا وهذا يعني أن يتم التعرّف على الإدخال المكتوب بخط اليد أثناء رسمه من خلال التقاط الإدخال الفردي وتحليله حركة سباحة. على عكس "غير متصل" إجراءات مثل التعرّف البصري على الأحرف (OCR)، حيث لا يعرف سوى المنتج النهائي، ويمكن أن توفر الخوارزميات عبر الإنترنت مستوى أعلى من الدقة بسبب إشارات إضافية مثل التسلسل الزمني وضغط ضغطات الحبر الفردية.

حالات الاستخدام المقترَحة لواجهة برمجة تطبيقات التعرُّف على الكتابة بخط اليد

تشمل أمثلة الاستخدامات ما يلي:

  • تطبيقات لتدوين الملاحظات حيث يريد المستخدمون تسجيل ملاحظات مكتوبة بخط اليد وترجمتها إلى نص.
  • نماذج تطبيقات يمكن للمستخدمين من خلالها استخدام القلم أو الإدخال بالإصبع لضيق الوقت.
  • الألعاب التي تتطلب ملء أحرف أو أرقام، مثل الكلمات المتقاطعة أو الهانغل أو السودوكو.

الوضع الحالي

تتوفّر واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد من (Chromium 99).

طريقة استخدام واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد

رصد الميزات

رصد توافق المتصفّح من خلال التحقق من توفُّر طريقة createHandwritingRecognizer() على كائن المستكشف:

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

المفاهيم الأساسية

تتيح واجهة برمجة التطبيقات "التعرُّف على الكتابة بخط اليد" تحويل الإدخال المكتوب بخط اليد إلى نص، بغض النظر عن أسلوب الإدخال. (الماوس، اللمس، القلم). وتضم واجهة برمجة التطبيقات أربعة كيانات رئيسية، وهي:

  1. تشير النقطة إلى مكان وجود المؤشر في وقت معيّن.
  2. يتكون السكتة الدماغية من نقطة واحدة أو أكثر. يبدأ تسجيل السكتة الدماغية عندما يضع المستخدم المؤشر لأسفل (أي النقر على زر الماوس الأساسي أو لمس الشاشة بالقلم أو وينتهي عند رفع المؤشر للأعلى مرة أخرى.
  3. يتكون الرسم من ضغطة أو أكثر. يحدث التقدير الفعلي على هذا المستوى.
  4. تم ضبط أداة التعرّف على لغة الإدخال المتوقّعة. يتم استخدامه لإنشاء مثيل رسم مع تطبيق إعداد أداة التعرّف.

يتم تنفيذ هذه المفاهيم كواجهات وقواميس محددة، وسوف أتناولها قريبًا.

الكيانات الأساسية لواجهة برمجة تطبيقات التعرف على الكتابة بخط اليد: تؤدي نقطة واحدة أو أكثر إلى إنشاء سُمك خط ، وضغطة واحدة أو أكثر تؤلف رسمًا، تنشئها أداة التعرف. يحدث التعرف الفعلي على مستوى الرسم.

إنشاء أداة التعرّف

للتعرف على النص من الإدخال المكتوب بخط اليد، تحتاج إلى الحصول على مثيل HandwritingRecognizer من خلال استدعاء navigator.createHandwritingRecognizer() وتمرير القيود إليه. تحدِّد القيود نموذج التعرّف على الكتابة بخط اليد الذي يجب استخدامه. في الوقت الحالي، تحديد قائمة اللغات بترتيب التفضيلات:

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

تعرض الطريقة وعدًا بحلّ المشكلة من خلال مثيل 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. يمكنك استخدام هذه المعلومات لتفعيل ميزات معيّنة أو إيقافها في تطبيقك، أو لتعديل طلبك وإرسال طلب جديد.

بدء رسم

داخل التطبيق، يجب توفير منطقة إدخال حيث يكتب المستخدم الإدخالات. لأسباب تتعلق بالأداء، ننصح بتنفيذ ذلك بمساعدة كائن لوحة الرسم. المطابقة التامة من هذا الجزء ليس موضوع هذه المقالة، ولكن يمكنك الرجوع إلى العرض التوضيحي لمعرفة كيف يمكن القيام بذلك.

لبدء رسم جديد، عليك استدعاء طريقة startDrawing() في أداة التعرّف. تستغرق هذه الطريقة يحتوي على تلميحات مختلفة لتحسين خوارزمية التعرف. جميع التلميحات اختيارية:

  • نوع النص الذي يتم إدخاله: نص أو عناوين بريد إلكتروني أو أرقام أو حرف فردي (recognitionType)
  • نوع جهاز الإدخال: الماوس أو اللمس أو القلم (inputType)
  • النص السابق (textContext)
  • عدد عبارات البحث المقترحة البديلة التي يقل احتمال عرضها (alternatives)
  • قائمة بالأحرف التي يمكن للمستخدم التعرّف عليها ("المخططات") التي من المرجّح أن يُدخلها المستخدم (graphemeSet)

تعمل واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد بشكل جيد مع أحداث المؤشر التي توفّر واجهة مجردة لاستهلاك المدخلات من أي جهاز تأشير. تحتوي وسيطات حدث المؤشر على ونوع المؤشر المستخدم. وهذا يعني أنّه يمكنك استخدام أحداث المؤشر لتحديد نوع الإدخال. تلقائيًا. في المثال التالي، يتم رسم التعرف على الكتابة بخط اليد تلقائيًا تم إنشاؤه عند ورود الحدث 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 عند تحريك المؤشر على الشاشة. نقطتان يجب إضافته إلى الحد الخارجي أيضًا. كما يمكن رفع الحدث إذا لم يكن المؤشر في "أسفل" الحالة، مثلاً عند تحريك المؤشر على الشاشة بدون الضغط على الماوس . يتحقق معالج الحدث من المثال التالي من وجود سُمك خط نشط، ويضيف نقطة جديدة عليه.

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

التعرّف على النص

عندما يرفع المستخدم المؤشر مرة أخرى، يمكنك إضافة سُمك الخط إلى الرسم عن طريق استدعاء طريقة addStroke(). يعيد المثال التالي ضبط activeStroke أيضًا، وبالتالي فإن pointermove لن يضيف المعالج نقاطًا إلى الحد المكتمل.

بعد ذلك، حان الوقت للتعرف على مدخلات المستخدم من خلال استدعاء طريقة 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);
      });
    },
  );
}

يمكنك استخدام هذه المعلومات لتعقب الرسومات البيانية المعروفة على اللوحة مرة أخرى.

يتم رسم المربعات حول كل رسم بياني معروف

تقدير كامل

بعد اكتمال التقدير، يمكنك تحرير موارد من خلال استدعاء طريقة clear() في HandwritingDrawing، وطريقة finish() على HandwritingRecognizer:

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

عرض توضيحي

ينفذ مكون الويب <handwriting-textarea> محسَّنة تدريجيًا، مع إمكانية التحكّم في التعديل مع إمكانية الكتابة بخط اليد والتقدير. بالنقر على الزر في أسفل يسار عنصر التحكّم في التعديل، يتم تفعيل وضع الرسم. عند إكمال الرسم، سيبدأ مكون الويب تلقائيًا التعرف على النص الذي تم التعرف عليه مرة أخرى إلى عنصر تحكم التعديل. إذا كان تطبيق "التعرّف على الكتابة بخط اليد" واجهة برمجة التطبيقات غير متوافقة على الإطلاق، أو لا تدعم المنصة الميزات المطلوبة، زر التعديل سيتم إخفاء. ويظل عنصر التحكّم الأساسي في التعديل قابلاً للاستخدام باعتباره <textarea>.

يقدم مكوِّن الويب خصائص وسمات لتحديد سلوك التعرف من في الخارج، بما في ذلك languages وrecognitiontype. يمكنك ضبط محتوى عنصر التحكّم من خلال سمة value:

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

للاطّلاع على أي تغييرات تطرأ على القيمة، يمكنك الاستماع إلى حدث input.

يمكنك تجربة المكوِّن باستخدام هذا العرض التوضيحي على Glitch. تأكد أيضًا من إلقاء نظرة على رمز المصدر. لاستخدام عنصر التحكّم في التطبيق، الحصول عليه من npm.

الأمان والأذونات

صمَّم فريق Chromium ونفّذ واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد باستخدام المبادئ الأساسية. المحدد في التحكم في الوصول إلى ميزات النظام الأساسي للويب الفعالة، بما في ذلك حسابات والتحكم والشفافية وهندسة العمل.

تحكم المستخدم

لا يمكن للمستخدم إيقاف واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد. لا تتوفّر هذه الميزة إلا للمواقع الإلكترونية عبر HTTPS، وقد يتم استدعاؤها فقط من خلال سياق التصفح ذي المستوى الأعلى.

الشفافية

وما من إشارة إلى ما إذا كانت ميزة التعرُّف على الكتابة بخط اليد مفعّلة. لمنع البصمات الرقمية، يستخدم المتصفح تنفيذ إجراءات مضادة، مثل عرض طلب الإذن للمستخدم عند رصده احتمال إساءة الاستخدام.

استمرار الإذن

لا تعرض واجهة برمجة تطبيقات التعرف على الكتابة بخط اليد حاليًا أي طلبات للحصول على أذونات. وبالتالي، لا يمكن منح الإذن لا يلزم استمراره بأي شكل من الأشكال.

ملاحظات

يرغب فريق Chromium في التعرُّف على تجاربك في استخدام واجهة برمجة تطبيقات التعرُّف على الكتابة بخط اليد.

أخبِرنا عن تصميم واجهة برمجة التطبيقات

هل هناك أي مشكلة في واجهة برمجة التطبيقات لا تعمل كما توقعت؟ أم أن هناك طرق مفقودة أو الخصائص التي تحتاج إليها لتنفيذ فكرتك؟ طرح سؤال أو تعليق بشأن الأمان النموذج؟ يُرجى الإبلاغ عن مشكلة في المواصفات حول مستودع GitHub ذي الصلة، أو إضافة أفكارك إلى مشكلة حالية.

الإبلاغ عن مشكلة في التنفيذ

هل واجهت مشكلة في التنفيذ في Chromium؟ أم أن التنفيذ يختلف عن المواصفات؟ يُرجى الإبلاغ عن الخطأ على new.crbug.com. تأكد من تضمين أكبر قدر ممكن من التفاصيل، تعليمات بسيطة لإعادة الإنتاج، وأدخل Blink>Handwriting في مربع المكونات. تعمل ميزة الخطأ بشكلٍ رائع لمشاركة النسخ المُعاد إنتاجها بسرعة وسهولة.

إظهار الدعم لواجهة برمجة التطبيقات

هل تخطط لاستخدام واجهة برمجة تطبيقات التعرُّف على الكتابة بخط اليد؟ يساعد دعمك العلني فريق Chromium تحديد أولويات الميزات وإظهار لموردي المتصفحات الآخرين مدى أهمية دعمها.

شارِك الطريقة التي تنوي استخدامها بها في سلسلة محادثات WICG Discourse. إرسال تغريدة إلى @ChromiumDev باستخدام علامة التصنيف #HandwritingRecognition عليك إعلامنا بمكان تطبيقك وطريقة استخدامه

شكر وتقدير

تمت مراجعة هذه المقالة بواسطة جو ميدلي وهونغلين يو وجيوي تشيان. صورة رئيسية بواسطة سمير بواكد على إزالة البداية