จดจำลายมือของผู้ใช้

Handwrite Recognition API ช่วยให้คุณจดจำข้อความจากการป้อนข้อมูลด้วยลายมือได้แบบเรียลไท��์

Christian Liebel
Christian Liebel
Thomas Steiner
Thomas Steiner

Handwrite Recognition API คืออะไร

Handwrite Recognition API ช่วยให้คุณสามารถแปลงการเขียนด้วยลายมือ (หมึก) จากผู้ใช้เป็นข้อความ ระบบปฏิบัติการบางระบบมี API ดังกล่าวมานานแล้ว และด้วยความสามารถใหม่นี้ เว็บแอปของคุณสามารถใช้ฟังก์ชันนี้ได้ในที่สุด Conversion จะเกิดขึ้นในอุปกรณ์ของผู้ใช้โดยตรงและทำงานได้แม้ในโหมดออฟไลน์ โดยไม่ต้องเพิ่มไลบรารีหรือบริการของบุคคลที่สาม

API นี้ใช้การจดจำที่เรียกกันว่า "ออนไลน์" หรือการจดจำที่เกือบจะเป็นแบบเรียลไทม์ ซึ่งหมายความว่าระบบจะจดจำข้อมูลที่เขียนด้วยลายมือได้ในขณะที่ผู้ใช้กำลังวาดรูปโดยบันทึกและวิเคราะห์เส้นเดียว อัลกอริทึมออนไลน์สามารถให้ความแม่นยำในระดับที่สูงขึ้นเนื่องจากสัญญาณเพิ่มเติม เช่น ลำดับเชิงเวลาและแรงกดของเส้นหมึกแต่ละเส้น ซึ่งแตกต่างจากกระบวนการ "ออฟไลน์" เช่น Optical Character Recognition (OCR)

กรณีการใช้งานที่แนะนำสำหรับ API การรู้จำลายมือ

ตัวอย่างการใช้งานมีดังนี้

  • แอปพลิเคชันสำหรับจดโน้ตที่ผู้ใช้ต้องจับโน้ตที่เขียนด้วยลายมือและแปลเป็นข้อความ
  • แอปพลิเคชันฟอร์มที่ผู้ใช้สามารถใช้การป้อนข้อมูลด้วยลายมือหรือนิ้วได้เนื่องด้วยข้อจำกัดด้านเวลา
  • เกมที่ต้องมีการเติมตัวอักษรหรือตัวเลข เช่น อักษรไขว้ ฮันแมน หรือซูโดกุ

สถานะปัจจุบัน

API การจดจำลายมือมีให้บริการจาก (Chromium 99)

วิธีใช้ API การรู้จำลายมือ

การตรวจหาฟีเจอร์

ตรวจหาการรองรับเบราว์เซอร์โดยตรวจหาการมีอยู่ของเมธอด createHandwritingRecognizer() ในออบเจ็กต์ตัวนำทาง ดังนี้

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

แนวคิดหลัก

Handwrite Recognition API จะแปลงการป้อนข้อมูลด้วยลายมือเป็นข้อความ โดยไม่คำนึงถึงวิธีการป้อนข้อมูล (เมาส์ การแตะ ปากกา) API มี 4 เอนทิตีหลักดังนี้

  1. จุดแสดงถึงตำแหน่งของตัวชี้ในช่วงเวลาหนึ่งๆ
  2. โรคหลอดเลือดสมองประกอบด้วยจุดอย่างน้อย 1 จุด การบันทึกเส้นโครงร่างจะเริ่มต้นเมื่อผู้ใช้วางตัวชี้ลง (เช่น คลิกปุ่มหลักของเมาส์ หรือใช้ปากกาหรือนิ้วแตะหน้าจอ) และสิ้นสุดลงเมื่อผู้ใช้ยกตัวชี้ขึ้นอีกครั้ง
  3. ภาพวาดประกอบด้วยเส้นอย่างน้อย 1 เส้น ซึ่งการรับรู้จริงจะเกิด��ึ้นในระดับนี้
  4. โปรแกรมรู้จำได้รับการกำหนดค่าด้วยภาษาสำหรับป้อนข้อมูลที่ต้องการ ซึ่งใช้เพื่อสร้างอินสแตนซ์ของภาพวาดที่ใช้การกำหนดค่าโปรแกรมรู้จำ

แนวคิดเหล่านี้จะนำมาใช้เป็นอินเทอร์เฟซและพจนานุกรมเฉพาะ ซึ่งผมจะพูดถึงในเร็วๆ นี้

เอนทิตีหลักของ API การจดจำลายมือ: จุดอย่างน้อย 1 จุดเขียนเส้นโครงร่าง เส้นอย่างน้อย 1 เส้นสำหรับเขียนภาพวาดที่เครื่องมือรู้จำสร้างขึ้น การจดจำจริงจะเกิดขึ้นในระดับภาพวาด

การสร้างโปรแกรมรู้จำ

หากต้องการจดจำข้อความจากอินพุตที่เขียนด้วยลายมือ คุณต้องรับอินสแตนซ์ของ 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 คุณสามารถใช้ข้อมูลนี้เพื่อเปิดใช้หรือปิดใช้ฟีเจอร์บางอย่างภายในแอปพลิเคชันของคุณ หรือเพื่อปรับการค้นหาแล้วส่งการค้นหาใหม่

เริ่มวาดภาพ

ภายในแอปพลิเคชันของคุณ คุณควรจัดเตรียมพื้นที่สำหรับป้อนข้อมูลให้ผู้ใช้เขียนรายการที่เขียนด้วยลายมือของตน สำหรับเหตุผลด้านประสิทธิภาพ เราขอแนะนำให้ดำเนินการนี้โดยใช้ออบเจ็กต์ Canvas แทน การใช้งานในส่วนนี้อยู่นอกเหนือขอบเขตของบทควา��นี้ แต่คุณสามารถดูวิธีการใช้งานได้ในการสาธิต

หากต้องการเริ่มภาพวาดใหม่ ให้เรียกใช้เมธอด startDrawing() ในการจดจำ วิธีนี้จะนำออบเจ็กต์ที่มีคำแนะนำต่างๆ มาปรับแต่งอัลกอริทึมการจดจำ คำใบ้ทั้งหมดเป็นตัวเลือก:

  • ประเภทข้อความที่ป้อน ได้แก่ ข้อความ อีเมล ตัวเลข หรืออักขระเดี่ยว (recognitionType)
  • ประเภทของอุปกรณ์อินพุต ได้แก่ การป้อนข้อมูลด้วยเมาส์ การแตะ หรือปากกา (inputType)
  • ข้อความก่อนหน้า (textContext)
  • จำนวนการคาดการณ์ทางเลือกที่มีแนวโน้มน้อยกว่าที่ควรแสดงผล (alternatives)
  • รายการอักขระที่ระบุตัวบุคคลได้ ("กราฟ") ที่ผู้ใช้มีแนวโน้มที่จะป้อนมากที่สุด (graphemeSet)

Handwrite Recognition API ทำงานได้ดีกับเหตุการณ์ของ 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() ในภาพวาด โดยปกติการจดจำจะใช้เวลาไม่ถึง 2-3 มิลลิวินาที คุณจึงเรียกใช้การคาดการณ์ซ้ำๆ ได้หากจำเป็น ตัวอย่างต่อไปนี้เรียกใช้การคาดการณ์ใหม่หลังจากแต่ละเส้นเสร็จสมบูรณ์

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> จะใช้การควบคุมการแก้ไขที่ปรับปรุงอย่างต่อเนื่องซึ่งมีความสามารถในการจดจำลายมือ การคลิกปุ่มที่มุมขวาล่างของตัวควบคุมการแก้ไขจะเป็นการเปิดใช้งานโหมดการวาด เมื่อวาดเสร็จแล้ว คอมโพเนนต์เว็บจะเริ่มการจดจำโดยอัตโนมัติและเพิ่มข้อความที่รู้จักกลับไปยังตัวควบคุมการแก้ไข หากระบบไม่รองรับ API การจดจำลายมือเลย หรือแพลตฟอร์มไม่รองรับฟีเจอร์ที่ขอ ระบบจะซ่อนปุ่มแก้ไขไว้ แต่การควบคุมการแก้ไขพื้นฐานจะยังคงใช้งานได้ในฐานะ <textarea>

คอมโพเนนต์เว็บมีพร็อพเพอร์ตี้และแอตทริบิวต์เพื่อกำหนดพฤติกรรมการจดจำจากภายนอก ซึ่งรวมถึง languages และ recognitiontype คุณตั้งค่าเนื้อหาของตัวควบคุมผ่านแอตทริบิวต์ value ได้ดังนี้

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

หากต้องการทราบเกี่ยวกับการเปลี่ยนแปลงมูลค่า ให้ฟังเหตุการณ์ input

คุณลองใช้คอมโพเนนต์ได้โดยใช้การสาธิตเกี่ยวกับ Glitch และอย่าลืมดู ซอร์สโค้ดด้วย หากต้องการใช้การค��บคุมในแอปพลิเคชันของคุณ ให้รับการควบคุมจาก npm

ความปลอดภัยและสิทธิ์

ทีม Chromium ออกแบบและใช้งาน API การรู้จำลายมือโดยใช้หลักการสำคัญที่ระบุไว้ในการควบคุมการเข้าถึงฟีเจอร์แพลตฟอร์มเว็บที่มีประสิทธิภาพ ซึ่งรวมถึงการควบคุมผู้ใช้ ความโปร่งใส และการยศาสตร์

การควบคุมของผู้ใช้

ผู้ใช้จะปิด Handwrite Recognition API ไม่ได้ โดยจะใช้ได้กับเว็บไซต์ที่แสดงผ่าน HTTPS เท่านั้น และอาจเรียกใช้จากบริบทการท่องเว็บระดับบนสุดเท่านั้น

ความโปร่งใส

ไม่มีการระบุโดยใช้การจดจำลายมือว่าเปิดใช้งานอยู่หรือไม่ เพื่อป้องกันการเก็บฟิงเกอร์ปรินต์ เบราว์เซอร์ใช้มาตรการรับมือ เช่น การแสดงข้อความแจ้งสิทธิ์แก่ผู้ใช้เมื่อตรวจพบว่าอาจมีการละเมิด

ความต่อเนื่องของสิทธิ์

ขณะนี้ Handwrite Recognition API ไม่แสดงข้อความแจ้งสิทธิ์ จึงไม่จำเป็นต้องคงสิทธิ์ไว้ ไม่ว่าด้วยวิธีใด

ความคิดเห็น

ทีม Chromium ต้องการทราบประสบการณ์ของคุณเกี่ยวกับ Handwrite Recognition API

บอกเราเกี่ยวกับการออกแบบ API

มีบางอย่างเกี่ยวกับ API ที่ไม่ทำงานตามที่คุณคาดหวังหรือไม่ หรือยังไม่มีวิธีการหรือคุณสมบัติ ที่คุณต้องใช้เพื่อนำไอเดียของคุณไปปฏิบัติ หากมีข้อสงสัยหรือความคิดเห็น เกี่ยวกับรูปแบบการรักษาความปลอดภัย แจ้งปัญหาเกี่ยวกับ���ี่เก็บ GitHub ที่เกี่ยวข้อง หรือเพิ่มความคิดเห็นของคุณเกี่ยวกับปัญหาที่มีอยู่

รายงานปัญหาเกี่ยวกับการติดตั้งใช้งาน

คุณพบข้อบกพร่องในการใช้งาน Chromium ไหม หรือการติดตั้งใช้งานแตกต่างจากข้อกําหนดหรือไม่ รายงานข้อบกพร่องที่ new.crbug.com ตรวจสอบว่าได้ใส่รายละเอียดให้มากที่สุดเท่าที่จะเป็นไปได้ วิธีการง่ายๆ ในการสร้างอีกครั้ง และป้อน Blink>Handwriting ในช่องคอมโพเนนต์ ภาพ Glitch เหมาะสำหรับการแชร์ซ้ำที่ง่ายและรวดเร็ว

แสดงการรองรับ API

คุณวางแผนที่จะใช้ Handwrite Recognition API ไหม การสนับสนุนแบบสาธารณะของคุณช่วยให้ทีม Chromium สามารถจัดลำดับความสำคัญของฟีเจอร์ต่างๆ และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นเห็นว่าการสนับสนุนฟีเจอร์เหล่านี้นั้นสำคัญเพียงใด

แชร์วิธีที่คุณวางแผนจะใช้ในชุดข้อความของ WICG Discourse ส่งทวีตไปที่ @ChromiumDev โดยใช้แฮชแท็ก #HandwritingRecognition และแจ้งให้เราทราบว่าคุณใช้งานที่ไหนและอย่างไร

กิตติกรรมประกาศ

บทความนี้ได้รับการตรวจสอบโดย Joe Medley, Honglin Yu และ Jiewei Qian รูปภาพหลักโดย Samir Bouaked ใน Unsplash