You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<h3align="center">Long-Form Human Handwriting Synthesis Engine</h3>
7
7
8
8
<palign="center">
9
-
<strong>Stroke-level generative ML model trained on real human handwriting — not a font.</strong>
9
+
<strong>Generate full pages of realistic handwriting — paragraphs, essays, letters — with natural fatigue, drift, and writer personality. Not a font. Not a single-line demo. A complete document-level handwriting engine.</strong>
10
10
</p>
11
11
12
12
<palign="center">
@@ -41,39 +41,76 @@
41
41
42
42
## Executive Summary
43
43
44
-
Every existing text-to-handwriting tool is, under the hood, a **font renderer**. Static handwriting fonts produce a single fixed glyph per character — perfectly uniform stroke width, zero baseline drift, no ligatures, no pressure variance. The human eye detects this inauthenticity instantly.
44
+
Every existing text-to-handwriting tool falls into one of two traps:
45
45
46
-
**Inkforge replaces the font rendering pipeline entirely** with a stroke-level generative ML model trained on real human handwriting corpora.
46
+
1.**Font renderers** — Static handwriting fonts that produce identical glyphs every time. The human eye detects this instantly.
47
+
2.**Single-line demo generators** (e.g., Calligrapher AI) — RNN-based tools that generate one short line at a time with basic style controls. They can produce a convincing sentence, but ask them for a full page? They have no concept of paragraphs, margins, page layout, or the way human handwriting evolves over long passages.
48
+
49
+
**Inkforge is different.** It generates **entire documents** — full paragraphs, multi-page letters, long-form essays — where the handwriting looks like it was written by a real human sitting at a desk for 20 minutes, not generated one line at a time and stitched together.
50
+
51
+
### How Inkforge Differs from Calligrapher AI & Others
52
+
53
+
| Feature | Calligrapher AI / Font Tools |**Inkforge**|
| Inter-line Consistency | Each line generated independently |**Lines are coherent within a page** — consistent writer personality with natural drift |
60
+
| Character Memory | Stateless per generation |**Writer-consistent evolution** — the same character looks subtly different each time, but consistently "from the same hand" |
61
+
| Page Layout | Not applicable |**Full page composition** — margins, headers, line spacing, multi-page support |
62
+
| Output Length |~1 line (typically <100 chars) |**Up to 2,000+ characters** — full page A4/Letter output |
63
+
| Export | SVG only |**PNG (300 DPI), PDF (A4/US Letter), SVG**|
47
64
48
65
### Target Users
49
66
50
67
| Persona | Goal | Pain Point |
51
68
|---------|------|------------|
52
-
|**Portfolio Builder**| Technically impressive ML project with live demo | Existing generators all use fonts — no real ML differentiator |
53
-
|**D2C Marketer**| Personalised handwritten notes in shipments at scale | Font-based tools look fake; robot pens cost $5–8/letter |
54
-
|**Real Estate Agent**| Handwritten outreach letters for 3–5x response rates | No tool combines realistic generation with mail pipeline |
69
+
|**Portfolio Builder**| Technically impressive ML project with live demo | Existing generators produce short demos — no long-form document generation |
70
+
|**D2C Marketer**| Personalised handwritten notes in shipments at scale | Font-based tools look fake; single-line generators can't produce full letters |
71
+
|**Real Estate Agent**| Handwritten outreach letters for 3–5x response rates | No tool generates a convincing full-page handwritten letter |
72
+
|**Student / Creator**| Handwritten essays, assignments, or journal pages | Need realistic multi-paragraph output, not one line at a time |
55
73
56
74
---
57
75
58
76
## The Problem
59
77
60
-
Real human handwriting is defined by its **imperfections**:
78
+
Real human handwriting over a **full page**is defined by its **imperfections at every scale**:
61
79
80
+
### Character Level
62
81
- Pressure builds and releases mid-stroke
63
82
- Letters lean inconsistently
64
-
- The baseline wanders
83
+
- The same letter is written slightly differently every time — but consistently "from the same hand"
84
+
85
+
### Line Level
86
+
- The baseline wanders across a line
65
87
- Adjacent characters influence each other through natural ligatures
66
-
- Writing degrades in consistency over long passages
88
+
- Word spacing varies naturally — tighter in fast sections, looser in deliberate ones
89
+
90
+
### Document Level (what no other tool handles)
91
+
- Writing quality **degrades over long passages** — fatigue is real
92
+
- Letter size subtly **grows or shrinks** over paragraphs
93
+
- Margins aren't perfectly straight — the left edge drifts
94
+
- Line spacing isn't uniform — it loosens as the writer reaches the bottom of a page
95
+
- Paragraph indentation varies between paragraphs
96
+
- The overall slant may shift across the page as the writer's hand position changes
67
97
68
-
**No font can replicate this**because fonts are context-free and deterministic by design.
98
+
**No font can replicate this.**And no single-line generator even attempts it.
69
99
70
100
---
71
101
72
102
## The Solution
73
103
74
-
Inkforge synthesizes handwriting as **sequences of pen strokes** with learned distributions over pressure, velocity, slant, and inter-character spacing. Every generation is unique. Every line drifts naturally. Every character is subtly different from its previous instance.
104
+
Inkforge synthesizes handwriting as **sequences of pen strokes** with learned distributions over pressure, velocity, slant, and inter-character spacing — but unlike short-snippet generators, it operates at the **document level**.
75
105
76
-
> **This is not a filter applied to a font. It is synthesized handwriting — generated stroke-by-stroke by a deep learning model trained on thousands of real human writers.**
106
+
When you feed Inkforge a 500-word essay:
107
+
- It plans the **page layout** — margins, line count, paragraph breaks
108
+
- It generates each line within the context of the **full document** — the model knows where it is on the page
109
+
- It simulates **writing fatigue** — the 30th line isn't as crisp as the 1st
110
+
- It maintains **writer consistency** — every character comes from the same "hand", with natural per-instance variation
111
+
- Every generation is **unique** — regenerating the same text produces a completely different manuscript
112
+
113
+
> **This is not a filter applied to a font. This is not a single-line demo. It is a full document synthesis engine — generating pages of handwriting stroke-by-stroke, with the realism of a human writer sitting at a desk.**
77
114
78
115
---
79
116
@@ -90,17 +127,32 @@ Each parameter is implemented at the **model level**, not as post-processing. Th
90
127
|**Slant Angle**| Global slant bias + per-word variance from learned distribution | -30° to +30° | 5° |
91
128
|**Baseline Drift**| Slow-varying sinusoidal noise on y-axis across a line | 0.0 – 1.0 | 0.3 |
92
129
|**Ligature Formation**| Contextual stroke connections between adjacent characters | On / Off | On |
93
-
|**Fatigue Simulation**|Increasing noise in latent space over token position | On / Off|Off|
130
+
|**Fatigue Simulation**|Progressive degradation over long passages — stroke precision decreases, letter size drifts, spacing loosens | 0.0 – 1.0|0.3|
**MDN output per timestep:**`(π, μx, μy, σx, σy, ρ, e)` for M=20 components. Temperature `τ` controls generation randomness.
158
211
212
+
**Document-Level Generation Pipeline — How It Actually Works:**
213
+
214
+
Unlike single-line generators (Calligrapher AI, etc.) that generate each line in isolation and discard all state, Inkforge uses a **4-step pipeline** that maintains writer consistency across the entire document:
215
+
216
+
#### Step 1 — Smart Text Chunking
217
+
218
+
The full input text (up to 2,000+ characters) is broken into **individual words or short phrases**. Each chunk becomes a separate inference call to the LSTM — but critically, these calls are **not independent**.
#### Step 2 — LSTM State Passing (The Secret Sauce)
228
+
229
+
This is what makes Inkforge fundamentally different from tools that generate text line-by-line. When the model generates strokes for "Word 1", the **final LSTM hidden state `h_t`** is captured and used as the **initial hidden state for "Word 2"**.
230
+
231
+
```
232
+
Word 1: "Thank"
233
+
LSTM processes → generates strokes → final state h₁
234
+
│
235
+
Word 2: "you" │
236
+
LSTM starts with h₁ → generates strokes → final state h₂
237
+
│
238
+
Word 3: "for" │
239
+
LSTM starts with h₂ → generates strokes → final state h₃
240
+
│
241
+
... and so on for the entire document
242
+
```
243
+
244
+
**Why this matters:** The hidden state carries all the accumulated "writer personality" — slant tendencies, pressure habits, letter-formation quirks, and fatigue. Every word inherits the full writing history, so word 50 naturally looks like it was written by the same hand that wrote word 1 — just a bit more tired.
245
+
246
+
#### Step 3 — 2D Typewriter Layout Algorithm
247
+
248
+
A **classical Python layout engine** (outside the ML model) acts like a typewriter to place each generated word on the page:
249
+
250
+
```
251
+
For each generated word chunk:
252
+
1. Measure the rendered stroke width of the word
253
+
2. Place it at current cursor position (x, y)
254
+
3. Advance x by: word_width + random_space(base=10px, noise=±3px)
255
+
4. If x > right_margin:
256
+
→ Line break: reset x to left_margin + slight_random_offset
257
+
→ Shift y down by: line_height + random_noise(±0.5mm)
258
+
→ Apply subtle baseline drift to new line
259
+
5. If paragraph break detected:
260
+
→ Extra y shift (1.2× line height)
261
+
→ Apply paragraph indent to x (1.5cm ± natural variation)
262
+
```
263
+
264
+
This keeps all layout logic **deterministic and debuggable** — no ML model is wasting capacity learning where to put spaces and line breaks.
265
+
266
+
#### Step 4 — Global Baseline Variance (Sine-Wave Drift)
267
+
268
+
A slow-moving **sinusoidal function** is applied to the y-axis across the entire page, making lines gently curve up and down rather than sitting on perfectly ruled baselines:
269
+
270
+
```
271
+
y_offset(line_n) = A × sin(2π × line_n / period + phase)
272
+
273
+
Where:
274
+
A = amplitude (1–3px) — subtle enough to look natural
275
+
period = 8–12 lines — one full wave across ~half a page
276
+
phase = random per generation — so no two pages curve the same way
277
+
```
278
+
279
+
This is applied **on top of** the per-line baseline drift from the LSTM, creating two layers of natural variation: the model's own stroke-level jitter, plus a global page-level undulation that mimics how a human's hand position shifts as they write down a page.
@@ -317,7 +439,15 @@ This project is licensed under the MIT License — see [LICENSE](LICENSE) for de
317
439
318
440
---
319
441
442
+
## How We Differ from Existing Tools
443
+
444
+
> **Calligrapher AI** and similar tools are impressive single-line demos. They generate a short sentence with style controls — and that's where they stop.
445
+
>
446
+
> **Inkforge generates documents.** Feed it an entire essay and get back a realistic handwritten manuscript — with natural paragraph breaks, margin awareness, writing fatigue, and the kind of page-level coherence that only comes from treating the document as a whole, not as a collection of independent lines.
447
+
448
+
---
449
+
320
450
<palign="center">
321
451
<strong>Built with ❤️ using PyTorch · FastAPI · React</strong><br/>
322
-
<sub>Inkforge — because handwriting should never be a font.</sub>
452
+
<sub>Inkforge — because handwriting should never be a font, and a real letter is more than one line.</sub>
0 commit comments