अपने उपयोगकर्ताओं की हैंडराइटिंग को पहचानें

हैंडराइटिंग की पहचान करने वाले एपीआई की मदद से, हाथ से लिखे गए इनपुट में मौजूद टेक्स्ट की तुरंत पहचान की जा सकती है.

क्रिश्चियन लीबेल
क्रिश्चियन लीबेल
थॉमस स्टेनर
थॉमस स्टेनर

लिखावट की पहचान करने वाला एपीआई क्या है?

हैंडराइटिंग की पहचान करने वाले एपीआई की मदद से, उपयोगकर्ताओं की हैंडराइटिंग (इंक) को टेक्स्ट में बदला जा सकता है. कुछ ऑपरेटिंग सिस्टम में पहले से ही ऐसे एपीआई शामिल होते हैं. इस नई सुविधा के साथ, आपके वेब ऐप्लिकेशन आखिर में इस फ़ंक्शन का इस्तेमाल कर सकते हैं. कन्वर्ज़न सीधे उपयोगकर्ता के डिवाइस पर होता है और ऑफ़लाइन मोड में भी काम करता है. इसके लिए तीसरे पक्ष की लाइब्रेरी या सेवा को जोड़ना ज़रूरी नहीं है.

यह एपीआई तथाकथित "ऑन-लाइन" या करीब-करीब रीयल-टाइम पहचान लागू करता है. इसका मतलब है कि जब उपयोगकर्ता हाथ से लिखे इनपुट को कैप्चर कर रहा होता है, तब उस इनपुट को पहचाना जाता है. इसके लिए, एक स्ट्रोक को कैप्चर किया जाता है और उसका विश्लेषण किया जाता है. ऑप्टिकल कैरेक्टर रिकग्निशन (ओसीआर) जैसी "ऑफ़-लाइन" प्रोसेस के उलट, जहां सिर्फ़ एंड प्रॉडक्ट के बारे में जानकारी मिलती है, ऑन-लाइन एल्गोरिदम ज़्यादा सटीक जानकारी दे सकते हैं. ऐसा, समय के क्रम और अलग-अलग इंक स्ट्रोक के दबाव जैसे सिग्नल की वजह से होता है.

लिखावट की पहचान करने वाले एपीआई को इस्तेमाल करने के सुझाए गए उदाहरण

इस्तेमाल के उदाहरण:

  • नोट लेने वाले ऐसे ऐप्लिकेशन जिनमें उपयोगकर्ता हाथ से लिखे गए नोट कैप्चर करना चाहते हैं और उनका अनुवाद लेख में कराना चाहते हैं.
  • यह फ़ॉर्म ऐसे ऐप्लिकेशन बनाता है जिनमें समय की कमी की वजह से, उपयोगकर्ता पेन या फ़िंगर इनपुट का इस्तेमाल कर सकते हैं.
  • ऐसे गेम जिनमें अक्षर या संख्याएं भरने की ज़रूरत होती है, जैसे कि क्रॉसवर्ड, हैंंगमैन या सुडोकू.

मौजूदा स्थिति

हैंडराइटिंग की पहचान करने वाला एपीआई, (Chromium 99) में उपलब्ध है.

लिखावट की पहचान करने वाले एपीआई को इस्तेमाल करने का तरीका

सुविधा की पहचान

नेविगेटर ऑब्जेक्ट पर, createHandwritingRecognizer() तरीके की मौजूदगी की जांच करके, ब्राउज़र पर काम करने की सुविधा का पता लगाएं:

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

मुख्य सिद्धांत

लिखावट की पहचान करने वाला एपीआई, हाथ से लिखे गए इनपुट को टेक्स्ट में बदलता है. इनपुट का तरीका (माउस, टच, पेन) चाहे जो भी हो. इस एपीआई में चार मुख्य इकाइयां हैं:

  1. पॉइंट से यह पता चलता है कि किसी खास समय पर पॉइंटर कहां पर था.
  2. स्ट्रोक में एक या ज़्यादा पॉइंट होते हैं. स्ट्रोक की रिकॉर्डिंग तब शुरू होती है, जब उपयोगकर्ता पॉइंटर को नीचे रखता है (यानी, मुख्य माउस बटन पर क्लिक करता है या अपनी पेन या उंगली से स्क्रीन को छूता है) और पॉइंटर को वापस ऊपर उठाने पर खत्म हो जाता है.
  3. ड्रॉइंग में एक या ज़्यादा स्ट्रोक होते हैं. असली पहचान इसी लेवल पर होती है.
  4. आइडेंटिफ़ायर को सही इनपुट भाषा के साथ कॉन्फ़िगर किया गया है. इसका इस्तेमाल, ड्रॉइंग के ऐसे इंस्टेंस को बनाने के लिए किया जाता है जिसमें आइडेंटिफ़ायर कॉन्फ़िगरेशन लागू होता है.

इन सिद्धांतों को खास इंटरफ़ेस और डिक्शनरी के तौर पर लागू किया गया है. इनके बारे में जल्द ही बताया जाएगा.

हैंडराइटिंग पहचान एपीआई की मुख्य इकाइयां: एक या ज़्यादा पॉइंट से स्ट्रोक बनाया जाता है. एक या उससे ज़्यादा स्ट्रोक से ऐसी ड्रॉइंग बनाई जाती है जिसे आइडेंटिफ़ायर बनाता है. असली पहचान ड्रॉइंग के स्तर पर होती है.

आइडेंटिफ़ायर बनाया जा रहा है

हाथ से लिखे गए इनपुट से टेक्स्ट की पहचान करने के लिए, आपको navigator.createHandwritingRecognizer() को कॉल करके और कंस्ट्रेंट को पास करके, HandwritingRecognizer का इंस्टेंस पाना होगा. पाबंदियां, हैंडराइटिंग की पहचान करने वाले उस मॉडल को तय करती हैं जिसका इस्तेमाल किया जाना चाहिए. फ़िलहाल, भाषाओं की सूची को अपनी पसंद के हिसाब से क्रम में लगाया जा सकता है:

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)

हैंडराइटिंग की पहचान करने वाला एपीआई, Pointer Events के साथ अच्छी तरह से काम करता है. यह किसी भी पॉइंटिंग डिवाइस से इनपुट इस्तेमाल करने के लिए, ऐब्सट्रैक्ट इंटरफ़ेस की सुविधा देता है. पॉइंटर इवेंट आर्ग्युमेंट में, इस्तेमाल किए जा रहे पॉइंटर का टाइप शामिल होता है. इसका मतलब है कि इनपुट टाइप अपने-आप तय होने के लिए, पॉइंटर इवेंट का इस्तेमाल किया जा सकता है. यहां दिए गए उदाहरण में, लिखावट की पहचान करने के लिए ड्रॉइंग, हैंडराइटिंग एरिया में 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);
      });
    },
  );
}

इस जानकारी का इस्तेमाल, कैनवस पर पहचाने गए ग्राफ़ीम को फिर से ट्रैक करने के लिए किया जा सकता है.

पहचाने गए हर ग्राफ़ीम के आस-पास बॉक्स बनाए जाते हैं

पूरी पहचान

पहचान पूरी होने के बाद, HandwritingDrawing पर clear() तरीके को कॉल करके और HandwritingRecognizer पर finish() तरीके को कॉल करके, संसाधनों को खाली किया जा सकता है:

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

डेमो

वेब कॉम्पोनेंट <handwriting-textarea>, बहुत बेहतर का इस्तेमाल करता है. साथ ही, यह हैंडराइटिंग की पहचान करने वाले एडिटिंग कंट्रोल का इस्तेमाल करता है. बदलाव करने से जुड़े कंट्रोल के नीचे दाएं कोने में दिए गए बटन पर क्लिक करके, ड्रॉइंग मोड चालू किया जाता है. जब आप ड्रॉइंग पूरी कर लेंगे, तो वेब कॉम्पोनेंट अपने-आप पहचान शुरू कर देगा और पहचाने गए टेक्स्ट को एडिटिंग कंट्रोल में वापस जोड़ देगा. अगर लिखावट की पहचान करने वाला एपीआई काम नहीं करता या प्लैटफ़ॉर्म, अनुरोध की गई सुविधाओं के साथ काम नहीं करता, तो 'बदलाव करें' बटन नहीं दिखेगा. हालांकि, बदलाव करने के बुनियादी कंट्रोल का इस्तेमाल <textarea> के तौर पर किया जा सकता है.

वेब कॉम्पोनेंट बाहर से पहचान करने के तरीके को तय करने के लिए, प्रॉपर्टी और एट्रिब्यूट ऑफ़र करता है. इनमें languages और recognitiontype भी शामिल हैं. आप value एट्रिब्यूट के ज़रिए, कंट्रोल का कॉन्टेंट सेट कर सकते हैं:

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

वैल्यू में हुए किसी भी बदलाव की जानकारी पाने के लिए, input इवेंट सुनें.

इस कॉम्पोनेंट को इस्तेमाल करने के लिए, Glitch पर मौजूद इस डेमो का इस्तेमाल करें. साथ ही, सोर्स कोड पर ज़रूर नज़र डालें. अपने ऐप्लिकेशन में कंट्रोल का इस्तेमाल करने के लिए, उसे npm से पाएं.

सुरक्षा और अनुमतियां

Chromium की टीम ने हैंडराइटिंग पहचानने वाले एपीआई को डिज़ाइन करने और उसे लागू करने के लिए, वेब प्लैटफ़ॉर्म की बेहतर सुविधाओं के ऐक्सेस को कंट्रोल करना सेक्शन में बताए हैं. इन सिद्धांतों में, उपयोगकर्ता कंट्रोल, पारदर्शिता, और अर्गोनॉमिक्स शामिल हैं.

उपयोगकर्ता नियंत्रण

लिखावट की पहचान करने वाले एपीआई को उपयोगकर्ता बंद नहीं कर सकता. यह सुविधा सिर्फ़ उन वेबसाइटों के लिए उपलब्ध है जिन्हें एचटीटीपीएस के ज़रिए डिलीवर किया गया है. साथ ही, इसे सिर्फ़ टॉप लेवल के ब्राउज़िंग कॉन्टेक्स्ट के ज़रिए ही कॉल किया जा सकता है.

पारदर्शिता

लिखावट की पहचान करने की सुविधा चालू है या नहीं, इसका कोई संकेत नहीं है. फ़िंगरप्रिंट की सुविधा को रोकने के लिए ब्राउज़र, कई तरीकों का इस्तेमाल करता है. जैसे, अगर उपयोगकर्ता को संभावित गलत इस्तेमाल का पता चलता है, तो उन्हें अनुमति का अनुरोध दिखाना.

अनुमति को बरकरार रखना

फ़िलहाल, लिखावट की पहचान करने वाला एपीआई, अनुमतियों से जुड़े कोई अनुरोध नहीं दिखाता है. इसलिए, अनुमति की किसी भी स्थिति में बने रहने की ज़रूरत नहीं है.

सुझाव/राय दें या शिकायत करें

Chromium की टीम, हैंडराइटिंग की पहचान करने वाले एपीआई के साथ आपके अनुभव जानना चाहती है.

हमें इस एपीआई के डिज़ाइन के बारे में बताएं

क्या एपीआई में कुछ ऐसा है जो आपकी उम्मीद के मुताबिक काम नहीं करता? इसके अलावा, क्या अपने आइडिया को लागू करने के लिए कोई तरीका या प्रॉपर्टी मौजूद नहीं है? सुरक्षा मॉडल के बारे में आपका कोई सवाल या टिप्पणी है? संबंधित GitHub रिपो पर कोई खास समस्या दर्ज करें या किसी मौजूदा समस्या में अपने विचार जोड़ें.

लागू करने से जुड़ी समस्या की शिकायत करें

क्या आपको Chromium के लागू होने से जुड़ी कोई गड़बड़ी मिली? या फिर लागू किया जाने वाला तरीका खास जानकारी से अलग है? new.crbug.com पर कोई गड़बड़ी दर्ज करें. ज़्यादा से ज़्यादा जानकारी शामिल करें, कॉन्टेंट फिर से बनाने के आसान निर्देश दें और कॉम्पोनेंट बॉक्स में Blink>Handwriting डालें. Glitch कॉपी करके, उसे तुरंत और आसानी से शेयर करने का बेहतरीन तरीका है.

एपीआई को इस्तेमाल करने की जानकारी दें

क्या आपको हैंडराइटिंग पहचानने वाला एपीआई इस्तेमाल करना है? आपकी सार्वजनिक सहायता से Chromium टीम को सुविधाओं को प्राथमिकता देने में मदद मिलती है. साथ ही, यह दूसरे ब्राउज़र वेंडर को भी यह दिखाती है कि उनकी मदद करना कितना ज़रूरी है.

WICG चर्चा के थ्रेड में बताएं कि इसे कैसे इस्तेमाल करना है. हैशटैग का इस्तेमाल करके, @ChromiumDev को एक ट्वीट भेजें #HandwritingRecognition और हमें बताएं कि आपने इसका इस्तेमाल कहां और कैसे किया है.

स्वीकार हैं

इस लेख की समीक्षा जो मेडली, हॉन्गलिन यू, और जिएवी कियान ने की है. हीरो इमेज समीर बूकेड ने Unsplash पर ली है.