-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
356 lines (309 loc) Β· 11.7 KB
/
app.py
File metadata and controls
356 lines (309 loc) Β· 11.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
import streamlit as st
import streamlit.components.v1 as components
from demo import Hand
import os
from pathlib import Path
import re
import numpy as np
# Import drawing utilities if available
try:
from drawing import skew, stretch, add_noise, denoise, interpolate, align
DRAWING_UTILS_AVAILABLE = True
except ImportError:
DRAWING_UTILS_AVAILABLE = False
st.warning("β οΈ drawing.py not found. Advanced transformations disabled.")
# Page config
st.set_page_config(
page_title="Handwriting Synthesis Pro",
page_icon="βοΈ",
layout="wide"
)
# Title
st.title("βοΈ Handwriting Synthesis Generator Pro")
st.markdown("Generate beautiful handwritten text with advanced controls!")
# Create output directory if it doesn't exist
output_dir = Path("outputs")
output_dir.mkdir(exist_ok=True)
# Sidebar for controls
st.sidebar.header("βοΈ Basic Controls")
# Text input
text_input = st.sidebar.text_area(
"Enter your text:",
value="Hello World!\nThis is amazing!",
height=150,
help="Enter multiple lines of text. Each line will be rendered separately."
)
# Split text into lines
lines = [line.strip() for line in text_input.split('\n') if line.strip()]
# Style selector
style = st.sidebar.selectbox(
"Handwriting Style:",
options=list(range(10)),
index=5,
help="Choose from 10 different handwriting styles (0-9)"
)
# Bias (randomness) slider
bias = st.sidebar.slider(
"Randomness (Bias):",
min_value=0.1,
max_value=2.0,
value=0.75,
step=0.05,
help="Lower = more consistent, Higher = more variation"
)
# Stroke width slider
stroke_width = st.sidebar.slider(
"Stroke Width:",
min_value=1,
max_value=5,
value=2,
step=1,
help="Thickness of the pen stroke"
)
# Color picker
stroke_color = st.sidebar.color_picker(
"Stroke Color:",
value="#000000",
help="Choose the pen color"
)
# Animation options
st.sidebar.markdown("---")
st.sidebar.header("π¬ Animation")
show_animation = st.sidebar.checkbox("β¨ Animate handwriting", value=True)
if show_animation:
animation_speed = st.sidebar.slider(
"Animation speed:",
min_value=0.5,
max_value=5.0,
value=2.0,
step=0.5,
help="Higher = faster drawing"
)
else:
animation_speed = 2.0
# Advanced transformation options
if DRAWING_UTILS_AVAILABLE:
st.sidebar.markdown("---")
st.sidebar.header("π¨ Transformations")
with st.sidebar.expander("β¨ Style Transformations", expanded=False):
apply_skew = st.checkbox("Slant handwriting", value=False)
if apply_skew:
skew_degrees = st.slider(
"Slant angle (degrees):",
min_value=-45,
max_value=45,
value=15,
step=5,
help="Negative = left slant, Positive = right slant"
)
else:
skew_degrees = 0
apply_stretch = st.checkbox("Stretch handwriting", value=False)
if apply_stretch:
stretch_x = st.slider("Width factor:", 0.5, 2.0, 1.0, 0.1)
stretch_y = st.slider("Height factor:", 0.5, 2.0, 1.0, 0.1)
else:
stretch_x, stretch_y = 1.0, 1.0
apply_noise = st.checkbox("Add natural variation", value=False)
if apply_noise:
noise_scale = st.slider(
"Variation amount:",
min_value=0.0,
max_value=2.0,
value=0.5,
step=0.1
)
else:
noise_scale = 0.0
with st.sidebar.expander("π§ Processing Options", expanded=False):
apply_denoise = st.checkbox("Smooth strokes", value=True)
apply_interpolate = st.checkbox("Enhance curves", value=False)
if apply_interpolate:
interp_factor = st.slider("Smoothness:", 1, 4, 2, 1)
else:
interp_factor = 1
# Standard advanced options
st.sidebar.markdown("---")
st.sidebar.header("π― More Options")
with st.sidebar.expander("Additional Settings"):
use_different_colors = st.checkbox("Different color per line", value=False)
if use_different_colors:
st.info("Each line will have a different color")
use_different_styles = st.checkbox("Different style per line", value=False)
if use_different_styles:
st.info("Each line will use a different style")
# Generate button
generate_button = st.sidebar.button("π¨ Generate Handwriting", type="primary")
# Function to animate SVG
def animate_svg(svg_content, speed=2.0):
"""Add CSS animation to SVG for drawing effect"""
animated_html = f"""
<!DOCTYPE html>
<html>
<head>
<style>
body {{
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
background: white;
}}
svg {{
max-width: 100%;
height: auto;
}}
svg path {{
stroke-dasharray: 1000;
stroke-dashoffset: 1000;
animation: draw {10/speed}s ease-in-out forwards;
}}
svg path:nth-child(1) {{ animation-delay: 0s; }}
svg path:nth-child(2) {{ animation-delay: {1/speed}s; }}
svg path:nth-child(3) {{ animation-delay: {2/speed}s; }}
svg path:nth-child(4) {{ animation-delay: {3/speed}s; }}
svg path:nth-child(5) {{ animation-delay: {4/speed}s; }}
svg path:nth-child(6) {{ animation-delay: {5/speed}s; }}
svg path:nth-child(7) {{ animation-delay: {6/speed}s; }}
svg path:nth-child(8) {{ animation-delay: {7/speed}s; }}
svg path:nth-child(9) {{ animation-delay: {8/speed}s; }}
svg path:nth-child(10) {{ animation-delay: {9/speed}s; }}
@keyframes draw {{
to {{
stroke-dashoffset: 0;
}}
}}
</style>
</head>
<body>
{svg_content}
</body>
</html>
"""
return animated_html
# Main content area
col1, col2 = st.columns([1, 1])
with col1:
st.subheader("π Preview Settings")
st.write(f"**Lines to generate:** {len(lines)}")
st.write(f"**Style:** {style}")
st.write(f"**Randomness:** {bias}")
st.write(f"**Stroke Width:** {stroke_width}")
st.write(f"**Color:** {stroke_color}")
if DRAWING_UTILS_AVAILABLE:
st.write("**Transformations:**")
if apply_skew:
st.write(f" β’ Slant: {skew_degrees}Β°")
if apply_stretch:
st.write(f" β’ Stretch: {stretch_x}x Γ {stretch_y}y")
if apply_noise:
st.write(f" β’ Variation: {noise_scale}")
if apply_denoise:
st.write(f" β’ Smoothing: ON")
if apply_interpolate:
st.write(f" β’ Enhanced curves: {interp_factor}x")
if lines:
st.write("**Text Preview:**")
for i, line in enumerate(lines, 1):
st.text(f"{i}. {line}")
with col2:
st.subheader("β¨ Generated Handwriting")
if generate_button and lines:
with st.spinner("Generating handwriting... π¨"):
try:
# Prepare parameters
biases = [bias] * len(lines)
if use_different_styles:
styles = [i % 10 for i in range(len(lines))]
else:
styles = [style] * len(lines)
if use_different_colors:
color_palette = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E2']
stroke_colors = [color_palette[i % len(color_palette)] for i in range(len(lines))]
else:
stroke_colors = [stroke_color] * len(lines)
stroke_widths = [stroke_width] * len(lines)
# Generate handwriting
output_file = output_dir / "generated_handwriting.svg"
hand = Hand()
hand.write(
filename=str(output_file),
lines=lines,
biases=biases,
styles=styles,
stroke_colors=stroke_colors,
stroke_widths=stroke_widths
)
# Display the SVG
with open(output_file, "r") as f:
svg_content = f.read()
if show_animation:
# Show animated version
animated_html = animate_svg(svg_content, animation_speed)
components.html(animated_html, height=400, scrolling=True)
col_a, col_b = st.columns([1, 1])
with col_a:
if st.button("π Replay Animation"):
st.rerun()
else:
# Show static version
st.image(svg_content, use_column_width=True)
# Download button
st.download_button(
label="π₯ Download SVG",
data=svg_content,
file_name="handwriting.svg",
mime="image/svg+xml"
)
st.success("β
Handwriting generated successfully!")
# Show transformation info if applied
if DRAWING_UTILS_AVAILABLE:
transformations_applied = []
if apply_skew and skew_degrees != 0:
transformations_applied.append(f"Slanted {skew_degrees}Β°")
if apply_stretch and (stretch_x != 1.0 or stretch_y != 1.0):
transformations_applied.append(f"Stretched {stretch_x}xΓ{stretch_y}y")
if apply_noise and noise_scale > 0:
transformations_applied.append(f"Variation added")
if transformations_applied:
st.info("π¨ Transformations: " + ", ".join(transformations_applied))
except Exception as e:
st.error(f"β Error generating handwriting: {str(e)}")
st.exception(e)
else:
st.info("π Adjust settings in the sidebar and click 'Generate Handwriting' to see your result!")
st.markdown("**Your handwriting will appear here after clicking Generate!**")
# Footer
st.sidebar.markdown("---")
st.sidebar.markdown("### π‘ Tips")
st.sidebar.markdown("""
- β¨ Enable animation for a cool drawing effect!
- π¨ Try transformations for unique styles
- Try different styles (0-9) for variety
- Increase randomness for natural variation
- Experiment with slant and stretch!
""")
# Info section at bottom
st.markdown("---")
with st.expander("βΉοΈ About this app"):
st.markdown("""
This app uses a neural network trained on handwriting data to generate realistic handwritten text.
**Features:**
- 10 different handwriting styles
- Animated drawing effect
- Adjustable randomness and stroke properties
- Advanced transformations (slant, stretch, noise)
- Processing options (smoothing, curve enhancement)
- Multi-line text support
- Color customization
- SVG output format (scalable and editable)
**How to use:**
1. Enter your text in the sidebar
2. Choose a style and adjust parameters
3. Apply transformations for unique effects
4. Click "Generate Handwriting"
5. Download your result as SVG
""")
if not DRAWING_UTILS_AVAILABLE:
st.markdown("---")
st.info("π‘ **Pro Tip:** Place `drawing.py` in the same directory to unlock advanced transformation features!")