Узнайте, как превратить фото рукописного текста в настоящий TTF-шрифт. Пошаговое руководство с Python-кодом, без системных зависимостей. Попробуйте прямо сейчас!
Вы когда-нибудь хотели, чтобы ваш сайт или документ был написан именно вашим почерком? Теперь это возможно: сфотографируйте буквы на бумаге и получите готовый TTF-шрифт за пару минут. В этой статье я покажу, как работает конвейер от фото до веб-шрифта, и вы сможете повторить это самостоятельно.
Всё работает локально, без отправки данных в облако. Нужен только Node.js 18+ и одна фотография вашего почерка. Весь код открыт (MIT) и доступен на GitHub.
Конвейер состоит из шести этапов, каждый из которых использует проверенные open-source библиотеки. Ниже — подробное объяснение с примерами кода на Python (для понимания логики, хотя реальная реализация на JavaScript).
Обычная пороговая фильтрация не работает на реальных фото из-за теней. Адаптивный порог подстраивается под локальный фон, поэтому даже снимок при тусклом свете даёт чистый результат.
import cv2
import numpy as np
# Загрузка изображения
img = cv2.imread('handwriting.jpg', cv2.IMREAD_GRAYSCALE)
# Адаптивная бинаризация
binary = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2)
cv2.imwrite('binary.png', binary)Находим все области чернил. Точка над 'i' объединяется с палочкой по расстоянию.
from scipy import ndimage
# Маркировка связных компонент
labeled, num_features = ndimage.label(binary)
# Фильтрация маленьких шумов
sizes = ndimage.sum(binary, labeled, range(1, num_features+1))
min_size = 50
for i in range(1, num_features+1):
if sizes[i-1] < min_size:
binary[labeled == i] = 0Каждая найденная область должна быть опознана как конкретная буква. В нашем инструменте это делает ИИ (Claude Vision), который смотрит на пронумерованный контактный лист и говорит: «blob 14 — это строчная g».
# Пример: после получения меток от ИИ
labels = ['A', 'b', 'c', 'g', 'o'] # упрощённо
blobs = [...] # список контуровРастровое изображение каждой буквы превращается в кривые Безье. Используется Potrace — тот же движок, что в FontForge и Inkscape.
import subprocess
# Вызов potrace (должен быть установлен)
subprocess.run(['potrace', '-s', '--svg', '-o', 'output.svg', 'input.bmp'])В нашем инструменте Potrace скомпилирован в WASM и работает прямо в браузере.
Этот шаг превращает набор букв в настоящий шрифт. Каждому символу назначаются вертикальные метрики: высота заглавных, строчных, выносные элементы (как у 'g' ниже базовой линии).
# Метрики для шрифта
units_per_em = 1000
ascender = 800
descender = -200
# Для каждой буквы: bounding box и смещение
char_metrics = {
'A': {'width': 600, 'left_bearing': 50, 'right_bearing': 50},
'b': {'width': 500, 'left_bearing': 30, 'right_bearing': 30},
# ...
}Финальный этап — объединение контуров и метрик в TTF, WOFF2 и CSS-фрагмент для вставки на сайт.
from fontTools.ttLib import TTFont
from fontTools.pens.t2Pen import T2Pen
# Создание минимального шрифта (упрощённо)
font = TTFont()
font.setGlyphOrder(['.notdef', 'A', 'B', ...])
# Добавление контуров и метрик
# ...
font.save('myfont.ttf')Чтобы создать свой шрифт прямо сейчас:
npx skills add danilo-znamerovszkij/draw-your-fontnpx draw-your-font make photo.jpg --chars "ABCabc" --name "My Hand"Попробуйте демо в браузере: danilo-znamerovszkij.github.io/draw-your-font/. Весь код на GitHub: github.com/danilo-znamerovszkij/draw-your-font. Если проект вам полезен, поставьте звёздочку — это поможет другим найти его.
Хочешь закрепить знания на практике?
Решай задачи на Algolit — интерактивная платформа для обучения
Начать бесплатно →