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

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

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

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

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

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

इस्तेमाल के उदाहरणों में ये शामिल हैं:

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

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

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

ग्लिच के बारे में इस डेमो का इस्तेमाल करके, कॉम्पोनेंट को आज़माया जा सकता है. साथ ही, सोर्स कोड पर नज़र डालना न भूलें. अपने ऐप्लिकेशन में कंट्रोल का इस्तेमाल करने के लिए, इसे npm से लें.

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

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

ऐप्लिकेशन पर उपयोगकर्ताओं के कंट्रोल की जानकारी

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

पारदर्शिता

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

अनुमति का एक जैसा होना

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

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

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

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

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

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

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

यह एपीआई काम करता है

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

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

स्वीकार की गई

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