Kỹ thuật mã hóa nét chữ viết tay của tôi
(amygoodchild.com)- Bắt đầu từ trình tạo chữ cái dạng khối bằng JavaScript, rồi sau hai tháng mở rộng để dựng cả chữ viết tay liền nét bằng mã
- Các ký tự được đặt tọa độ cốt lõi bằng công cụ p5js, làm mượt bằng đường cong Chaikin rồi chuyển thành đường nét có độ dày thay đổi
- Với chữ viết tay liền nét, cách nối khác nhau tùy từng cặp chữ, nên phần đầu và cuối đường nét được gắn thẻ 0~3 để phân biệt trạng thái không thể nối, đường cơ sở, phía trên đường cơ sở và gần x-height
- Khi tạo từ, hệ thống chọn một trong 2~3 đường nét cho mỗi chữ, rồi thêm, xóa hoặc thay điểm theo độ cao nối của chữ kề bên, sau đó thêm độ rung bằng Perlin noise
- Sau khi thu gọn, lớp chữ viết tay liền nét có kích thước 26.1kb, lớn hơn 9.7kb của chữ dạng khối, do có nhiều đường nét và các hàm hiệu chỉnh theo chữ lân cận
Mở rộng từ cách tạo chữ dạng khối sang chữ viết tay liền nét
- Trình tạo bảng chữ cái dạng khối trước đó định nghĩa các điểm cốt lõi của đường nét từng chữ bằng mã
- Mỗi chữ đặt khoảng 10 điểm
- Dùng thuật toán đường cong Chaikin để làm mượt đường nét
- Chuyển đường nét thành dạng có độ dày thay đổi theo chiều dài
- Dùng p5js để vẽ hình dạng cuối cùng
- Với chữ dạng khối, các tọa độ được viết trực tiếp trong mã, và phải chỉnh tay các điểm cho đến khi chữ trông tự nhiên
- Khi triển khai chữ viết tay, tác giả tạo riêng một công cụ thiết kế chữ cái để giảm bớt công việc lặp đi lặp lại này
Công cụ thiết kế đường nét chữ trong p5js
- Tác giả tạo và dùng một công cụ để định nghĩa và xuất các điểm cốt lõi trong trình biên tập p5js
- Công cụ hiển thị đồng thời các chữ mẫu để tham chiếu về tỷ lệ và ngữ cảnh, cùng vùng để thiết kế chữ mới
- Khi nhấp chuột để đặt các điểm cốt lõi của đường nét, kết quả sau khi áp dụng đường cong Chaikin sẽ được hiển thị
- Nhấn phím
pđể chuyển sang chế độ chỉnh sửa - Chọn một điểm rồi kéo để điều chỉnh vị trí
- Nhấn phím
enterđể xuất đường nét ra console
- Mỗi chữ có 2~3 phương án và đường nét kết quả có dạng mảng tọa độ
{x, y} - Để lấy chính nét chữ của mình làm chuẩn, tác giả tự viết ví dụ chữ thường và chữ hoa, rồi nạp ảnh đó vào công cụ tạo chữ để đồ theo
- Dùng phím
w/a/s/dđể di chuyển ảnh - Dùng phím
r/eđể phóng to hoặc thu nhỏ ảnh - Các con số viết trên giấy là tọa độ x/y để khớp vùng đó với cửa sổ tạo chữ
- Dùng phím
Bài toán nối nét và thẻ 0~3
- Với một số cặp chữ, chỉ cần nối đường các điểm cốt lõi của chữ sau vào cuối đường của chữ trước rồi áp dụng đường cong Chaikin một lần là đã cho kết quả tự nhiên
- Nhưng ở một số tổ hợp, nét nối lại làm hỏng hình dạng chữ
- Trong
na, điểm cuối củanthấp còn điểm đầu củaacao, nên nét nối có thể cắt chéo quaavà khiến nó trông giốnge - Trong
ti,tkết thúc ngay trên đường cơ sở cònibắt đầu từ đường cơ sở, tạo ra một gờ nối không tự nhiên
- Trong
- Thay vì viết quy tắc cho từng cặp chữ cụ thể, tác giả gắn thông tin độ cao nối bằng số vào phần đầu và cuối của mỗi đường nét
0: không thể nối với chữ khác1: nối với chữ khác ở gần đường cơ sở2: nối với chữ khác ngay trên đường cơ sở3: nối với chữ khác ở gần x-height
- Ngay cả cùng một chữ, cách thêm hoặc xóa điểm cũng thay đổi tùy vị trí đầu từ hay chữ đứng trước, đứng sau
- Nếu
ađứng đầu từ thì điểm thêm vào sẽ trông gượng - Với
asauw, nét có thể cắt quaatheo cách khác - Khi
tnối vớik, hình dạng có thể bị biến đổi
- Nếu
- Tác giả đã thử mọi cặp chữ và tạo ra tính biến thể bằng nhiều lựa chọn đường nét cùng các chỉnh sửa theo chữ lân cận
- Lý tưởng nhất là mỗi chữ có 5~6 phương án đường nét, nhưng vẫn phải cân bằng với kích thước tệp
Quy trình tạo từ
- Khi tạo từ, trước hết hệ thống chọn một trong 2~3 đường nét cơ sở cho mỗi ký tự
- Thông tin nối ở đầu và cuối của đường nét được truyền cho các chữ liền kề
- Ngay cả cùng một chữ, thông tin điểm cuối cũng có thể khác tùy phương án đường nét được chọn, nên phải chọn xong toàn bộ đường nét chữ trước
- Sau đó các đường nét cơ sở sẽ được điều chỉnh để khớp với chữ lân cận
- Nếu độ cao kết thúc của chữ trước là
2, có thể xóa một điểm đầu của đường nét hiện tại - Nếu độ cao bắt đầu của chữ sau là
1, có thể thêm một điểm ở vị trí nhất định
- Nếu độ cao kết thúc của chữ trước là
- Hàm điều chỉnh hoạt động khác nhau tùy từng chữ
- Hàm điều chỉnh của
qcó 70% xác suất thêm một chỗ ngắt ở cuối, đồng thời thay hoặc thêm điểm tùy thông tin kết thúc của chữ trước hay thông tin bắt đầu của chữ sau - Hàm điều chỉnh của
ncó 30% xác suất tạo ngắt hoặc di chuyển điểm cuối khi chữ sau bắt đầu từ3
- Hàm điều chỉnh của
- Khi ghép các đường nét cơ sở của mọi chữ, các giá trị
1,2,3bị bỏ qua, còn nếu gặp0thì bắt đầu một đường mới để tạo chỗ ngắt - Đường đã ghép sau đó được áp dụng đường cong Chaikin, chuyển thành dạng có độ dày thay đổi, rồi thêm chút rung nhẹ bằng Perlin noise
Dung lượng và cách sử dụng
- Lớp chữ cho dạng khối có kích thước 9.7kb, còn lớp chữ viết tay liền nét sau khi minify hiện là 26.1kb
- Lý do chữ viết tay lớn hơn là vì mỗi chữ có nhiều đường nét và có các hàm điều chỉnh điểm theo chữ lân cận
- Vẫn còn một số ý tưởng để tiếp tục cắt giảm
- Hiện tại các chữ được thiết kế theo cỡ font cơ sở 20 rồi mới resize
- Vì vậy có nhiều tọa độ như
x: 14.5 - Nếu đổi cỡ cơ sở thành 200 thì có thể dùng
145thay cho số thập phân, nhờ đó giảm được dung lượng cho từng chữ - Thay đổi này cần làm cẩn thận nên đang nằm trong danh sách việc cần làm sau
- Mục đích chính của bộ chữ viết tay này là dùng cho tiêu đề, nhãn và ghi chú nguệch ngoạc trong diagram mà tác giả đang thực hiện
- Dùng các đường nét được mã hóa thay cho font giúp thao tác trực tiếp trên đường path, chẳng hạn thay đổi vị trí ký tự hoặc độ dày bên trong từng chữ riêng lẻ
- Tác giả cũng cung cấp bản in
Meaningful Nonsensedùng phiên bản phát triển hơn của mã chữ viết tay này; mỗi bản in là một kết quả riêng được tạo ra khi có đơn đặt hàng
1 bình luận
Ý kiến trên Hacker News
Nếu mã hóa chữ viết tay của tôi thì có vẻ có thể xem nó như một hàm băm một chiều
Đọc lại sau này thì hoàn toàn không có cách nào giải mã được rốt cuộc mình đã định viết gì
Video YouTube của Stuff Made Here nói về nội dung tương tự khá hay: https://www.youtube.com/watch?v=cQO2XTP7QDw
Họ còn giải thích cả quá trình thử-sai nên xem rất thú vị, và kho lưu trữ tổng hợp chữ viết tay này cũng đáng xem: https://github.com/sjvasquez/handwriting-synthesis
Tác phẩm nghệ thuật ở cuối khá đẹp
Không biết bước tiếp theo có phải là biến nó thành một phông chữ thực sự để có thể gõ trong bất kỳ chương trình nào không
Khác với phông chữ mà ta thường nghĩ tới, nó phải là đường dẫn để lần theo chứ không phải đường viền để tô kín
Chỉ là có thể sẽ hơi tẻ nhạt nếu phải làm thủ công hoặc muốn làm theo cách đó
Tôi không thật sự hiểu đoạn nói rằng việc nối chữ không khớp
Với tôi, cốt lõi của chữ viết tay nối nét là không nhấc bút khỏi giấy, nên cách nối các chữ vốn đã là một phần của hành động viết rồi
Có vẻ tác giả thực ra không viết theo kiểu đó nên mới nảy sinh vấn đề
Dù vậy, phần còn lại của bài về cách giải quyết bằng phương pháp đơn giản nhất để vẽ nhiều chữ trên màn hình mà không đụng vào phông chữ thì rất thú vị
Trong chữ viết tay nối nét, liên kết giữa các chữ phụ thuộc vào ngữ cảnh
Ví dụ, hình dạng có thể thay đổi để dễ đọc tùy việc sau
blàahayo, và ngay cả trong một từ đôi khi bạn vẫn muốn nhấc bút giữa các chữNhư vậy cũng không có nghĩa là phá vỡ “quy tắc” của chữ viết tay nối nét
Có thể bạn đã được dạy khác và cách dạy đó cũng đúng, nhưng tôi không biết kiểu chữ viết tay nối nét nào mà các liên kết lại không phụ thuộc vào ngữ cảnh
Ngay cả với những phông chữ không nối nét, cũng cần mã hóa việc các chuỗi nhiều chữ trông ra sao, tương tự như kerning
Đẹp quá! Tôi mong sẽ có thêm nhiều phông chữ chữ viết tay nối nét hơn nữa
Đây là tác phẩm tôi làm cách đây 2 năm: https://certik.github.io/slabikar-otf/
Hay thật, nhưng giá như chữ của tôi đủ đẹp để đáng làm thành phông chữ của riêng mình :)
Thay vì
< 14.5, nếu đổi kích thước mặc định thành 200 thì có thể định nghĩa dấu chấm là 145, nhờ vậy bớt được một ký tự dấu thập phânTôi thấy có một hàm tên
adjust; tôi không rành đặc tả phông chữ, nhưng có lẽ có thể serialize0,{x:12.2,y:13.2}thành dạng khác như0,[12.2,13.2]rồi chuyển đổi trong hàmadjustchăng