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

Handwriting Recognition API จะช่วยให้คุณจดจำข้อความจากการป้อนข้อมูลที่เขียนด้วยลายมือในขณะที่เกิดขึ้น

Handwriting Recognition API คืออะไร

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

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

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

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

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

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

Handwriting Recognition API สำหรับ (Chromium 99)

วิธีใช้ Handwriting Recognition API

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

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

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

แนวคิดหลัก

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

คุณสามารถใช้ข้อมูลนี้เพื่อติดตามกราฟที่รู้จักบนผืนผ้าใบได้อีกครั้ง

จะมีกรอบล้อมรอบ Graeme ที่ระบบรู้จักแต่ละภาพ

การจดจำอย่างสมบูรณ์

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

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

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

ความโปร่งใส

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

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

ปัจจุบัน Handwriting Recognition API ยังไม่แสดงข้อความแจ้งสิทธิ์ ดังนั้น ไม่จำเป็นต้องมี การยืนยันสิทธิ์ไม่ว่าด้วยวิธีใด

ความคิดเห็น

ทีม Chromium ต้องการทราบข้อมูลเกี่ยวกับประสบการณ์การใช้งาน Handwriting Recognition API ของคุณ

บอกให้เราทราบเกี่ยวกับการออกแบบ API

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

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

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

แสดงการสนับสนุนสำหรับ API

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

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

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

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