1 คะแนน โดย GN⁺ 2024-05-20 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • เริ่มจากตัวสร้างตัวอักษรแบบบล็อกใน JavaScript แล้วขยายจนสามารถสร้าง ลายมือแบบตัวเขียน ด้วยโค้ดได้ภายในสองเดือน
  • ตัวอักษรถูกสร้างโดยกำหนด จุดพิกัดหลัก ด้วยเครื่องมือ p5js แล้วเกลารูปทรงด้วยเส้นโค้ง Chaikin ก่อนแปลงเป็นเส้นทางที่มีความหนาแปรผัน
  • สำหรับลายมือแบบตัวเขียน การเชื่อมต่อระหว่างคู่ตัวอักษรแตกต่างกัน จึงติด แท็ก 0~3 ไว้ที่จุดเริ่มและจุดจบของเส้นทางเพื่อแยกสถานะว่าเชื่อมไม่ได้, ที่ baseline, เหนือ baseline, หรือใกล้ x-height
  • เมื่อต้องสร้างคำ ระบบจะเลือกหนึ่งเส้นทางจาก 2~3 แบบของแต่ละตัวอักษร แล้วเพิ่ม, ลบ, หรือแทนที่จุดตามระดับการเชื่อมของตัวอักษรข้างเคียง ก่อนเติมความสั่นไหวด้วย Perlin noise
  • หลังย่อขนาดแล้ว คลาสตัวอักษรแบบตัวเขียนมีขนาด 26.1kb ซึ่งใหญ่กว่าตัวแบบบล็อกที่ 9.7kb โดยมีสาเหตุมาจากหลายเส้นทางและฟังก์ชันปรับแก้ตามตัวอักษรข้างเคียง

ขยายจากวิธีสร้างตัวอักษรแบบบล็อกไปสู่ลายมือแบบตัวเขียน

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

เครื่องมือออกแบบเส้นทางตัวอักษรใน p5js

  • สร้างและใช้งาน เครื่องมือกำหนดและแสดงจุดหลัก ในตัวแก้ไข p5js
  • เครื่องมือนี้มีทั้งตัวอักษรตัวอย่างเพื่อแสดงสเกลและบริบท พร้อมพื้นที่สำหรับออกแบบตัวอักษรใหม่
    • เมื่อคลิกเพื่อวางจุดหลักของเส้นทาง จะแสดงผลลัพธ์ที่ผ่านเส้นโค้ง Chaikin
    • กดปุ่ม p เพื่อสลับไปยังโหมดแก้ไข
    • เลือกจุดแล้วลากเพื่อปรับตำแหน่ง
    • กดปุ่ม enter เพื่อส่งออกเส้นทางไปยังคอนโซล
  • สำหรับแต่ละตัวอักษร ได้สร้าง ตัวเลือก 2~3 แบบ และเส้นทางที่ได้จะอยู่ในรูปอาร์เรย์พิกัด {x, y}
  • เพื่อใช้ลายมือตัวเองเป็นต้นแบบ จึงเขียนตัวอย่างตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ด้วยมือตรง ๆ แล้วนำภาพนั้นเข้าไปในเครื่องมือสร้างตัวอักษรเพื่อวาดตาม
    • ใช้ปุ่ม w/a/s/d เพื่อเลื่อนภาพ
    • ใช้ปุ่ม r/e เพื่อขยายหรือย่อภาพ
    • ตัวเลขที่เขียนไว้บนกระดาษคือพิกัด x/y สำหรับจัดพื้นที่นั้นให้พอดีกับหน้าต่างสร้างตัวอักษร

ปัญหาการเชื่อมลายมือแบบตัวเขียนและแท็ก 0~3

  • คู่ตัวอักษรบางคู่สามารถเชื่อมได้อย่างเป็นธรรมชาติ เพียงนำเส้นทางจุดหลักของตัวอักษรถัดไปมาต่อท้ายเส้นทางของตัวก่อนหน้า แล้วใช้เส้นโค้ง Chaikin กับทั้งหมดในครั้งเดียว
  • แต่ในบางชุด การลากเส้นเชื่อมกลับทำให้รูปทรงของตัวอักษรเสีย
    • ใน na จุดสุดท้ายของ n อยู่ต่ำ แต่จุดแรกของ a อยู่สูง ทำให้เส้นเชื่อมพาดเฉียงผ่าน a จนดูคล้าย e
    • ใน ti ตัว t จบเหนือ baseline เล็กน้อย ขณะที่ i เริ่มที่ baseline จึงเกิดสันที่ดูไม่เป็นธรรมชาติ
  • แทนที่จะเขียนกฎแยกสำหรับทุกคู่ตัวอักษร จึงแนบข้อมูล ระดับความสูงของจุดเชื่อม เป็นตัวเลขไว้ที่ต้นและท้ายของแต่ละเส้นทาง
    • 0: เชื่อมกับตัวอักษรอื่นไม่ได้
    • 1: เชื่อมกับตัวอักษรอื่นใกล้ baseline
    • 2: เชื่อมกับตัวอักษรอื่นเหนือ baseline เล็กน้อย
    • 3: เชื่อมกับตัวอักษรอื่นใกล้ x-height
  • แม้จะเป็นตัวอักษรเดียวกัน วิธีเพิ่มหรือลบจุดก็เปลี่ยนไปตามว่าอยู่ต้นคำหรือมีตัวอักษรใดอยู่หน้าและหลัง
    • ถ้า a อยู่ต้นคำ การเพิ่มจุดอาจดูแปลก
    • ใน a ที่ตามหลัง w เส้นอาจพาดข้าม a ด้วยวิธีที่ต่างออกไป
    • ถ้า t ต่อกับ k รูปทรงอาจบิดเปลี่ยน
  • ได้ทดสอบทุกคู่ตัวอักษร และสร้าง ความแปรผัน ด้วยตัวเลือกเส้นทางหลายแบบและการแก้ไขตามตัวอักษรข้างเคียง
  • ในอุดมคติอยากให้แต่ละตัวอักษรมีตัวเลือกเส้นทาง 5~6 แบบ แต่ต้องรักษาสมดุลกับขนาดไฟล์

ขั้นตอนการสร้างคำ

  • เมื่อต้องสร้างคำ ระบบจะเลือกหนึ่งเส้นทางจาก เส้นทางพื้นฐาน 2~3 แบบ ของแต่ละตัวอักษรก่อน
  • ข้อมูลการเชื่อมที่ต้นและท้ายของเส้นทางที่เลือกจะถูกส่งต่อไปยังตัวอักษรข้างเคียง
    • แม้จะเป็นตัวอักษรเดียวกัน ข้อมูลจุดปลายก็อาจต่างกันตามตัวเลือกเส้นทางที่ถูกเลือก ดังนั้นจึงต้องเลือกเส้นทางของทุกตัวอักษรก่อน
  • จากนั้นเส้นทางพื้นฐานจะถูกปรับให้เข้ากับตัวอักษรข้างเคียง
    • ถ้าความสูงปลายของตัวก่อนหน้าเป็น 2 อาจลบจุดเริ่มต้นหนึ่งจุดของเส้นทางปัจจุบันออก
    • ถ้าความสูงเริ่มต้นของตัวถัดไปเป็น 1 อาจเพิ่มจุดในตำแหน่งที่กำหนด
  • ฟังก์ชันปรับแต่งทำงานต่างกันไปในแต่ละตัวอักษร
    • ฟังก์ชันปรับของ q มีโอกาส 70% ที่จะเพิ่มรอยขาดไว้ที่ท้าย และจะสลับหรือเพิ่มจุดตามข้อมูลปลายของตัวก่อนหน้าหรือข้อมูลต้นของตัวถัดไป
    • ฟังก์ชันปรับของ n จะสร้างรอยขาดด้วยโอกาส 30% หรือย้ายจุดสุดท้าย เมื่ออักษรถัดไปเริ่มจาก 3
  • เมื่อนำเส้นทางพื้นฐานของทุกตัวอักษรมารวมกัน ค่า 1, 2, 3 จะถูกมองข้าม และหากเจอ 0 จะเริ่มเส้นทางใหม่เพื่อสร้าง รอยขาด
  • จากนั้นจึงใช้เส้นโค้ง Chaikin กับเส้นทางที่รวมแล้ว แปลงให้เป็นรูปทรงความหนาแปรผัน และเพิ่มความสั่นไหวเล็กน้อยด้วย Perlin noise

ขนาดไฟล์และรูปแบบการใช้งาน

  • คลาสตัวอักษรสำหรับแบบบล็อกมีขนาด 9.7kb ส่วนคลาสตัวอักษรแบบตัวเขียนที่ผ่านการย่อขนาดแล้วปัจจุบันมีขนาด 26.1kb
  • เหตุผลที่ฝั่งตัวเขียนใหญ่กว่า เพราะแต่ละตัวอักษรมีหลายเส้นทาง และมีฟังก์ชันที่ปรับจุดให้เข้ากับตัวอักษรข้างเคียง
  • ยังมีแนวคิดสำหรับลดขนาดเพิ่มเติมอยู่
    • ตอนนี้ตัวอักษรถูกออกแบบโดยอิงขนาดฟอนต์พื้นฐาน 20 แล้วค่อยปรับขนาดอีกที
    • ทำให้มีพิกัดอย่าง x: 14.5 อยู่จำนวนมาก
    • ถ้าเปลี่ยนขนาดพื้นฐานเป็น 200 ก็จะเขียนเป็น 145 ได้และตัดเลขทศนิยมออกเพื่อลดขนาดของแต่ละตัวอักษร
    • การเปลี่ยนนี้ต้องทำอย่างระมัดระวัง จึงถูกเก็บไว้ในรายการงานภายหลัง
  • การใช้งานหลักของลายมือนี้คือใช้กับชื่อเรื่อง, ป้ายกำกับ และบันทึกขีดเขียนใน ไดอะแกรม ที่กำลังทำอยู่
  • การใช้เส้นทางที่เข้ารหัสไว้แทนฟอนต์ ทำให้สามารถ จัดการเส้นทาง ได้โดยตรง เช่น เปลี่ยนตำแหน่งตัวอักษรหรือความหนาภายในของตัวอักษรแต่ละตัว
  • ยังมีการจำหน่ายงานพิมพ์ Meaningful Nonsense ที่ใช้เวอร์ชันพัฒนาของโค้ดลายมือนี้ โดยงานพิมพ์แต่ละชิ้นจะเป็นผลลัพธ์เฉพาะตัวที่สร้างขึ้นเมื่อมีการสั่งซื้อ

1 ความคิดเห็น

 
GN⁺ 2024-05-20
ความคิดเห็นจาก Hacker News
  • ถ้า เข้ารหัสลายมือ ของฉัน ก็คงมองว่าเป็นแฮชทางเดียวได้เหมือนกัน
    เพราะพอกลับมาอ่านทีหลัง ก็ไม่มีทางถอดได้เลยว่าจริง ๆ ตั้งใจจะเขียนว่าอะไร

    • ฟังดูเหมือนเป็นโจทย์ท้าทายนะ! https://www.handwritingocr.com :)
    • เพราะงั้นตอนเรียนมหาวิทยาลัย ฉันเลยต้อง เลิกเขียนหวัดโดยตั้งใจ
    • ฉันก็เหมือนกัน แค่ผ่านไปไม่กี่ชั่วโมงก็ ถอดรหัสเองไม่ได้ แล้ว
  • มีวิดีโอ YouTube ของ Stuff Made Here ที่พูดถึงเรื่องคล้ายกัน ซึ่งเจ๋งมาก: https://www.youtube.com/watch?v=cQO2XTP7QDw
    เขาอธิบายทั้งขั้นตอนลองผิดลองถูกด้วย เลยดูเพลินมาก และคลังสำหรับสังเคราะห์ลายมือก็น่าสนใจด้วย: https://github.com/sjvasquez/handwriting-synthesis

  • งานภาพ ตอนท้ายนี่สวยมาก
    สงสัยว่าขั้นต่อไปจะเป็นการทำให้มันกลายเป็นฟอนต์จริง ๆ เพื่อให้พิมพ์ได้ในโปรแกรมไหนก็ได้หรือเปล่า

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

    • ประโยคที่ว่า “แก่นของการเขียนหวัดคือการไม่ยกปากกาขึ้นจากกระดาษ” นั้นก็ถูกอยู่ แต่ตีความต่างกัน
      ในการเขียนหวัด การเชื่อมระหว่างตัวอักษรนั้น ขึ้นกับบริบท
      อย่างเช่นหลัง b ถัดไปเป็น a หรือ o รูปร่างอาจเปลี่ยนไปเพื่อให้อ่านง่ายขึ้น และแม้แต่ภายในคำเดียวกัน บางกรณีก็อาจอยากยกปากการะหว่างตัวอักษร
      แต่นั่นก็ไม่ได้ถือว่าผิด “กฎ” ของการเขียนหวัด
      คุณอาจเรียนมาอีกแบบและสิ่งที่เรียนมาก็อาจถูกต้อง แต่ฉันไม่ค่อยรู้จักรูปแบบการเขียนหวัดที่การเชื่อมไม่ควรขึ้นกับบริบท
    • ประเด็นสำคัญดูเหมือนจะเป็นว่าแต่ละ คู่ตัวอักษร มีวิธี ประกบเข้าหากัน ไม่เหมือนกัน และต้องจัดการตรงนี้
    • คู่ตัวอักษรทุกคู่เชื่อมกันคนละแบบ
      แม้ในฟอนต์ที่ไม่เชื่อมติดกัน ก็ยังต้องเข้ารหัสว่าลำดับหลายตัวอักษรจะดูออกมาอย่างไร คล้ายกับ kerning
  • งดงาม! อยากให้มี ฟอนต์ลายมือแบบเขียนหวัด มากกว่านี้
    งานที่ฉันทำไว้เมื่อ 2 ปีก่อนอยู่ที่นี่: https://certik.github.io/slabikar-otf/

  • เจ๋งดีนะ แต่ฉันอยากให้ลายมือของตัวเองดีพอที่จะอยากเอาไปทำเป็นฟอนต์ส่วนตัว :)
    ถ้าเปลี่ยนขนาดตั้งต้นเป็น 200 แทน < 14.5 ก็จะกำหนดจุดเป็น 145 ได้ ทำให้ลดอักขระจุดทศนิยมไปได้หนึ่งตัว
    เห็นมีฟังก์ชันชื่อ adjust อยู่ ฉันไม่ได้รู้สเปกฟอนต์มากนัก แต่สงสัยว่าถ้าทำ serialization ของ 0,{x:12.2,y:13.2} เป็นแบบอื่น เช่น 0,[12.2,13.2] แล้วค่อยแปลงในฟังก์ชัน adjust จะเป็นยังไง

    • เช่นเดียวกับทักษะอื่น ๆ ลายมือ ก็พัฒนาให้ดีขึ้นได้ด้วยความพยายามอีกนิดหน่อย