3morrrrr commited on
Commit
d754187
·
verified ·
1 Parent(s): ba4df28

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +201 -46
app.py CHANGED
@@ -1,63 +1,218 @@
1
  import gradio as gr
2
  import os
 
 
 
3
  from huggingface_hub import hf_hub_download
4
-
5
- # 1. Import your model logic directly, not via HTTP
6
  from handwriting_api import InputData, validate_input
7
  from hand import Hand
8
 
 
 
9
 
10
- # 2. Initialize your model once
11
  hand = Hand()
12
 
13
- # 3. Directly call the model logic in the Gradio function
14
- def generate_handwriting_interface(text: str, style: int) -> str:
15
- lines = text.split('\n')
16
- stroke_colors = ["#000000"] * len(lines)
17
- stroke_widths = [2] * len(lines)
18
-
19
- data = InputData(
20
- text=text,
21
- style=style,
22
- bias=0.75,
23
- stroke_colors=stroke_colors,
24
- stroke_widths=stroke_widths
25
- )
26
-
27
- # Validate the input
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- # Generate the handwriting
30
- lines = data.text.split('\n')
31
- biases = [data.bias] * len(lines)
32
- styles = [data.style] * len(lines)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- hand.write(
35
- filename='img/output.svg',
36
- lines=lines,
37
- biases=biases,
38
- styles=styles,
39
- stroke_colors=data.stroke_colors,
40
- stroke_widths=data.stroke_widths
41
- )
 
 
 
 
 
 
 
42
 
43
- # Return the SVG contents
44
- with open("img/output.svg", "r") as f:
45
- return f.read()
 
 
 
46
 
47
- # 4. Set up the Gradio UI
48
- with gr.Blocks() as demo:
49
- gr.Markdown("# Handwriting Synthesis")
 
50
  with gr.Row():
51
- text_input = gr.Textbox(label="Input Text", lines=3)
52
- style_select = gr.Slider(minimum=0, maximum=12, step=1, label="Style", value=0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- output_svg = gr.HTML(label="Generated Handwriting")
55
- generate_button = gr.Button("Generate")
56
-
57
- generate_button.click(
58
- fn=generate_handwriting_interface,
59
- inputs=[text_input, style_select],
60
- outputs=output_svg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  )
62
 
63
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
1
  import gradio as gr
2
  import os
3
+ import threading
4
+ import subprocess
5
+ import time
6
  from huggingface_hub import hf_hub_download
 
 
7
  from handwriting_api import InputData, validate_input
8
  from hand import Hand
9
 
10
+ # Create img directory if it doesn't exist
11
+ os.makedirs("img", exist_ok=True)
12
 
13
+ # Initialize the handwriting model
14
  hand = Hand()
15
 
16
+ # Create a function to generate handwriting
17
+ def generate_handwriting(
18
+ text,
19
+ style,
20
+ bias=0.75,
21
+ color="#000000",
22
+ stroke_width=2,
23
+ multiline=True
24
+ ):
25
+ """Generate handwritten text using the model"""
26
+ try:
27
+ # Process the text
28
+ if multiline:
29
+ lines = text.split('\n')
30
+ else:
31
+ lines = [text]
32
+
33
+ # Create arrays for parameters
34
+ stroke_colors = [color] * len(lines)
35
+ stroke_widths = [stroke_width] * len(lines)
36
+ biases = [bias] * len(lines)
37
+ styles = [style] * len(lines)
38
+
39
+ # Input validation
40
+ for line_num, line in enumerate(lines):
41
+ if len(line) > 75:
42
+ return f"Error: Line {line_num+1} is too long (max 75 characters)"
43
+
44
+ data = InputData(
45
+ text=text,
46
+ style=style,
47
+ bias=bias,
48
+ stroke_colors=stroke_colors,
49
+ stroke_widths=stroke_widths
50
+ )
51
+
52
+ try:
53
+ validate_input(data)
54
+ except ValueError as e:
55
+ return f"Error: {str(e)}"
56
+
57
+ # Generate the handwriting
58
+ hand.write(
59
+ filename='img/output.svg',
60
+ lines=lines,
61
+ biases=biases,
62
+ styles=styles,
63
+ stroke_colors=stroke_colors,
64
+ stroke_widths=stroke_widths
65
+ )
66
+
67
+ # Read the generated SVG
68
+ with open("img/output.svg", "r") as f:
69
+ svg_content = f.read()
70
+
71
+ return svg_content
72
+ except Exception as e:
73
+ return f"Error: {str(e)}"
74
 
75
+ def export_to_png(svg_content):
76
+ """Convert SVG to PNG using CairoSVG"""
77
+ try:
78
+ import cairosvg
79
+
80
+ if not svg_content or svg_content.startswith("Error:"):
81
+ return None
82
+
83
+ # Save SVG to a temporary file
84
+ with open("img/temp.svg", "w") as f:
85
+ f.write(svg_content)
86
+
87
+ # Convert SVG to PNG
88
+ cairosvg.svg2png(url="img/temp.svg", write_to="img/output.png", scale=2.0)
89
+
90
+ return "img/output.png"
91
+ except Exception as e:
92
+ return None
93
 
94
+ def generate_lyrics_sample():
95
+ """Generate a sample using lyrics"""
96
+ from lyrics import all_star
97
+ return all_star.split("\n")[0:4]
98
+
99
+ def generate_handwriting_wrapper(
100
+ text,
101
+ style,
102
+ bias,
103
+ color,
104
+ stroke_width,
105
+ multiline=True
106
+ ):
107
+ svg = generate_handwriting(text, style, bias, color, stroke_width, multiline)
108
+ return svg
109
 
110
+ css = """
111
+ .container {max-width: 900px; margin: auto;}
112
+ .output-container {min-height: 300px;}
113
+ .gr-box {border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1);}
114
+ .footer {text-align: center; margin-top: 20px; font-size: 0.8em; color: #666;}
115
+ """
116
 
117
+ with gr.Blocks(css=css) as demo:
118
+ gr.Markdown("# 🖋️ Handwriting Synthesis")
119
+ gr.Markdown("Generate realistic handwritten text using neural networks. Based on Alex Graves' [paper](https://arxiv.org/abs/1308.0850).")
120
+
121
  with gr.Row():
122
+ with gr.Column(scale=2):
123
+ text_input = gr.Textbox(
124
+ label="Text Input",
125
+ placeholder="Enter text to convert to handwriting...",
126
+ lines=5,
127
+ max_lines=10,
128
+ )
129
+
130
+ with gr.Row():
131
+ with gr.Column(scale=1):
132
+ style_select = gr.Slider(
133
+ minimum=0,
134
+ maximum=12,
135
+ step=1,
136
+ value=9,
137
+ label="Handwriting Style"
138
+ )
139
+ with gr.Column(scale=1):
140
+ bias_slider = gr.Slider(
141
+ minimum=0.5,
142
+ maximum=1.0,
143
+ step=0.05,
144
+ value=0.75,
145
+ label="Neatness (Higher = Neater)"
146
+ )
147
+
148
+ with gr.Row():
149
+ with gr.Column(scale=1):
150
+ color_picker = gr.ColorPicker(
151
+ label="Ink Color",
152
+ value="#000000"
153
+ )
154
+ with gr.Column(scale=1):
155
+ stroke_width = gr.Slider(
156
+ minimum=1,
157
+ maximum=4,
158
+ step=0.5,
159
+ value=2,
160
+ label="Stroke Width"
161
+ )
162
+
163
+ with gr.Row():
164
+ generate_btn = gr.Button("Generate Handwriting", variant="primary")
165
+ clear_btn = gr.Button("Clear")
166
+
167
+ with gr.Accordion("Examples", open=False):
168
+ sample_btn = gr.Button("Insert Sample Text")
169
+
170
+ with gr.Column(scale=3):
171
+ output_svg = gr.HTML(label="Generated Handwriting", elem_classes=["output-container"])
172
+
173
+ with gr.Row():
174
+ download_btn = gr.Button("Download SVG")
175
 
176
+ gr.Markdown("""
177
+ ### Tips:
178
+ - Try different styles (0-12) to get various handwriting appearances
179
+ - Adjust the neatness slider to make writing more or less tidy
180
+ - Each line should be 75 characters or less
181
+ - The model works best for English text
182
+ """)
183
+
184
+ gr.Markdown("""
185
+ <div class="footer">
186
+ Created with Gradio • Model based on Alex Graves' <a href="https://arxiv.org/abs/1308.0850">Handwriting Synthesis paper</a>
187
+ </div>
188
+ """)
189
+
190
+ # Define interactions
191
+ generate_btn.click(
192
+ fn=generate_handwriting_wrapper,
193
+ inputs=[text_input, style_select, bias_slider, color_picker, stroke_width],
194
+ outputs=[output_svg]
195
+ )
196
+
197
+ clear_btn.click(
198
+ fn=lambda: ("", 9, 0.75, "#000000", 2),
199
+ inputs=None,
200
+ outputs=[text_input, style_select, bias_slider, color_picker, stroke_width]
201
+ )
202
+
203
+ sample_btn.click(
204
+ fn=lambda: ("\n".join(generate_lyrics_sample())),
205
+ inputs=None,
206
+ outputs=[text_input]
207
+ )
208
+
209
+ download_btn.click(
210
+ fn=lambda x: x,
211
+ inputs=[output_svg],
212
+ outputs=[gr.File(label="Download SVG", file_count="single", file_types=[".svg"])]
213
  )
214
 
215
+ if __name__ == "__main__":
216
+ # Set port based on environment variable or default to 7860
217
+ port = int(os.environ.get("PORT", 7860))
218
+ demo.launch(server_name="0.0.0.0", server_port=port)