forked from yeungchenwa/FontDiffuser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
font_complex_ui.py
550 lines (503 loc) · 21.3 KB
/
font_complex_ui.py
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
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
import random
import shutil
import time
import os
import re
from datetime import datetime
import gradio as gr
from font_easy_ui import run_fontdiffuer, example_list, example_list2
import uvicorn
from fastapi import FastAPI
import subprocess
from utils_2 import duplicate_image, fix_one_pic
from dataset.font2image import process_fonts
from PIL import Image
from sample import arg_parse, sampling, load_fontdiffuer_pipeline
def get_latest_png_within_3_hours(directory):
latest_time = None
for file in os.listdir(directory):
if file.endswith(".png") or file.endswith(".jpg"):
full_path = os.path.join(directory, file)
modification_time = os.path.getmtime(full_path)
file_time = datetime.fromtimestamp(modification_time)
if latest_time is None or file_time > latest_time:
latest_time = file_time
# 如果目录下没有png文件
if latest_time is None:
return False, None
# 检查最近的png文件是否在3小时内修改过
if (datetime.now() - latest_time).total_seconds() <= 3 * 3600:
return True, "还在生成"
# 如果没有png文件在3小时内修改过
return False, None
def generate_font(upload_pic_style, font_name, font_version, test_font):
if len(font_name) < 1 or font_name == "try_name_it":
return gr.update(value="字体名字没有取", visible=True)
if not upload_pic_style or len(upload_pic_style) < 12:
return gr.update(value="请上传至少12张相同风格图片", visible=True)
gen_path = f"data_examples/test_style/{font_name}/"
if not os.path.exists(gen_path):
os.makedirs(gen_path)
print(upload_pic_style)
result, _ = get_latest_png_within_3_hours(gen_path)
if result:
return gr.update(
value="字体已经在生成中,大约需要80分钟,请勿重复点击", visible=True
)
duplicate_image(upload_pic_style[0], gen_path, 24)
free_gpu = str(get_most_idle_gpu())
print(font_name)
print(font_version)
print(free_gpu)
basic_path = (
"data_examples/basic/test/"
if test_font
else "data_examples/basic/LXGWWenKaiGB-Light/"
)
os.makedirs(basic_path, exist_ok=True)
command = [
"nohup",
"python",
"run_all.py",
"--input",
gen_path,
"--name",
font_name,
"--v",
font_version,
"--cuda",
f"cuda:{free_gpu}",
"--basic_path",
basic_path,
]
with open(f"output_{font_name}.log", "w") as outfile:
subprocess.Popen(command, stdout=outfile, stderr=subprocess.STDOUT)
time.sleep(10)
return gr.update(value="开始字体生成!大约需要80分钟,请等待", visible=True)
def generate_font_pics(
font_name_input,
font_not_exists,
wrong_character_input,
sampling_step2,
guidance_scale2,
):
if font_not_exists == "该名称字体不存在":
return [], gr.update(value="请先确认字体名称")
style_pic_path_list = os.path.join("data_examples/test_style", font_name_input)
style_pic = os.path.join(style_pic_path_list, os.listdir(style_pic_path_list)[0])
style_pic = Image.open(style_pic).convert("RGB")
generated_images = []
result = re.sub(r"[^\u4e00-\u9fff]", "", wrong_character_input)
result = "".join(sorted(set(result), key=result.index))
print(result, sampling_step2, guidance_scale2)
for char in result.strip():
temp = {}
source_image = args.ttf_pic_path + "/" + char + ".png"
if not os.path.exists(source_image):
try:
process_fonts("ttf", "ttf_pics", char)
except Exception as e:
print(e)
source_image = Image.open(source_image).convert("RGB")
args.character_input = False if source_image is not None else True
args.content_character = char
args.sampling_step = sampling_step2
args.guidance_scale = guidance_scale2
args.seed = random.randint(0, 10000)
out_image = sampling(
args=args, pipe=pipe, content_image=source_image, style_image=style_pic
)
output_dir = "data_examples/test/lch"
os.makedirs(output_dir, exist_ok=True)
new_filename = f"{char}.png"
new_file_path = os.path.join(output_dir, new_filename)
# if char == "一":
# fix_one_pic("QAQ", "一", output_dir)
out_image.save(new_file_path)
temp["render"] = False
temp["path_pic"] = new_file_path
random_number = datetime.now().strftime("%H%M%S")
temp["current_time"] = random_number
generated_images.append(temp)
return generated_images, gr.update(value="字体图片如下,请逐一确认")
def get_most_idle_gpu():
# 运行 nvidia-smi 命令
result = subprocess.run(
[
"nvidia-smi",
"--query-gpu=index,memory.used,utilization.gpu",
"--format=csv,noheader,nounits",
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
)
# 检查是否有错误
if result.stderr:
print("Error running nvidia-smi:", result.stderr)
return None
# 处理输出
gpu_data = result.stdout.strip().split("\n")
min_utilization = 100 # 初始化最大可能的利用率 (100%)
idle_gpu_index = -1
for gpu in gpu_data[::-1]:
index, memory_used, utilization = gpu.split(", ")
utilization = int(utilization)
index = int(index)
# 找到具有最低利用率的GPU
if utilization < min_utilization:
min_utilization = utilization
idle_gpu_index = index
return idle_gpu_index
def download_font(name):
# 获取当前工作目录路径
current_dir = os.getcwd()
output_dir = os.path.join(current_dir, "outputs", name)
# 构建字体文件路径
ttf_file = os.path.join(current_dir, f"{name}.ttf")
os.makedirs(output_dir, exist_ok=True)
# 获取图片
files = [f for f in os.listdir(output_dir) if f.endswith(".png")]
if not files:
print(f"No image files found in '{output_dir}'.")
if os.path.isfile(ttf_file):
return None, ttf_file
return None, None
# 随机选择一张图片
random_pic = random.choice(files)
random_pic_path = os.path.join(output_dir, random_pic)
print(f"Random pic file '{random_pic_path}' selected.")
# 检查文件是否存在
if os.path.isfile(ttf_file):
print(f"Font file '{ttf_file}' found.")
return random_pic_path, ttf_file
else:
print(f"Font file '{ttf_file}' not found.")
return random_pic_path, None
def re_gen_font(old_name, new_name):
# 如果没有输入old_name,则不会报错,直接返回初始值
if len(old_name) < 1:
return gr.update(value="请输入字体名称"), gr.update(visible=True), "no_file.txt"
# 如果new_name为空,则使用old_name作为new_name
if len(new_name) < 1:
new_name = old_name
new_font_path = new_name + ".ttf"
old_font_pic_dir = os.path.join("outputs", old_name)
# 检查路径是否存在
if not os.path.isdir(old_font_pic_dir):
return (
gr.update(value="旧字体目录不存在"),
gr.update(visible=True),
new_font_path,
)
subprocess.run(
[
"python",
"run_gen.py",
"--input",
f"{old_font_pic_dir}",
"--name",
f"{new_name}",
"--v",
f"v1.1",
]
)
print(f"生成字体路径: {old_font_pic_dir}, 新字体名称: {new_name}")
return (
gr.update(value="已生成,点击下载"),
gr.update(value="已生成,点击下载", visible=False),
new_font_path,
)
if __name__ == "__main__":
"""
conda activate fontdiffuser
python font_complex_ui.py
nohup python font_complex_ui.py > s_words2.log &
"""
# Initialize FastAPI
app = FastAPI()
args = arg_parse()
args.demo = True
args.ckpt_dir = "ckpt"
args.ttf_path = "ttf/LXGWWenKaiGB-Light.ttf"
args.ttf_pic_path = "ttf_pics/LXGWWenKaiGB-Light/"
upload_default_path = "./upload_pic_default_dir"
if not os.path.exists(upload_default_path):
os.makedirs(upload_default_path)
# load fontdiffuer pipeline
pipe = load_fontdiffuer_pipeline(args=args)
with gr.Blocks(title="🎉字体生成🎉") as demo:
with gr.Tab(label="📙风格测试选择"):
gr.Markdown("---")
with gr.Row():
with gr.Column(scale=2):
with gr.Row():
reference_image = gr.Image(
width=320,
label=" 1️⃣:上传风格文字",
image_mode="RGB",
type="pil",
height=320,
)
gr.Examples(
label=" 1️⃣:点击选择风格字体",
examples=example_list2,
inputs=reference_image,
)
with gr.Row():
character = gr.Textbox(value="道", label="2️⃣:输入要生成的文字")
with gr.Column(scale=2):
fontdiffuer_output_image = gr.Image(
height=200, label="输出字体", image_mode="RGB", type="filepath"
)
sampling_step = gr.Slider(
20, 50, value=20, step=10, label="推理步数", info="默认20"
)
guidance_scale = gr.Slider(
1,
12,
value=7.5,
step=0.5,
label="分类器引导指数",
info="默认7.5",
)
FontDiffuser = gr.Button("3️⃣:点击生成图片", variant="primary")
with gr.Tab(label="👉字体生成"):
with gr.Row():
with gr.Column(scale=2):
upload_pic_style = gr.File(
label="🛠️上传字体图片(12-24张)",
file_count="multiple",
file_types=[".png", ".jpg"],
)
upload_pic_style.GRADIO_CACHE = upload_default_path
with gr.Row():
font_name = gr.Textbox(
label="输入字体名称",
value="try_name_it",
info="字体取名,必输值",
interactive=True,
)
font_version = gr.Textbox(
label="输入字体版本号",
value="v1.0",
placeholder="v1.0",
interactive=True,
info="字体附加版本号,非必选,一般默认v1.0即可",
)
test_font_checkbox = gr.Checkbox(
label="仅选择测试字体生成-五于天末开下理事画现玫珠表...",
value=True,
info="仅测试-约20分钟",
)
with gr.Row():
Generate_Font = gr.Button(
"点击生成字体",
icon="data_examples/using_files/shoot.ico",
variant="primary",
size="lg",
)
show = gr.Textbox(visible=False)
with gr.Column(scale=2):
with gr.Row():
preview_image = gr.Image(
width=200,
label="字体预览",
image_mode="RGB",
type="pil",
height=200,
)
refreshing = gr.Button(
"📖刷新图片/字体-注意:\n名字需要填自己命名的字体名称(否则会报错)",
variant="secondary",
)
download = gr.File(label="字体下载")
with gr.Tab(label="🔧字体样式修改"):
tasks = gr.State([])
with gr.Row():
with gr.Column() as column1:
with gr.Row():
font_name_input = gr.Textbox(
label="字体修改",
placeholder="输入字体名称",
interactive=True,
)
make_sure_font_name = gr.Button("确认字体名称", variant="stop")
font_not_exists = gr.Textbox(
value="该名称字体不存在", visible=False, interactive=False
)
wrong_character_input = gr.Textbox(
label="不满意文字", placeholder="输入需要修改的文字"
)
with gr.Row():
upload_wrong_char_img = gr.File(
label='手动修改文字上传(尺寸严格96*96,仅上传"道.png"格式文字图片,可多图)',
file_count="multiple",
file_types=[".png"],
)
upload_button = gr.Button("点击确认上传")
upload_wrong_char = gr.Textbox(
value="上传完成", visible=False, interactive=False
)
def sure_name(font_name):
if len(font_name.strip()) < 1:
return gr.update(value="再次确认字体名称"), gr.update(
visible=True
)
if not os.path.exists(
os.path.join("data_examples/test_style", font_name)
):
return gr.update(value="再次确认字体名称"), gr.update(
visible=True
)
else:
return gr.update(visible=False), gr.update(
value="字体存在", visible=True
)
def upload_wrong_func(image_list, font_name, font_exists):
if font_exists != "字体存在":
return gr.update(
value="该名称字体不存在,再次确认字体名称", visible=True
)
destination_path = os.path.join("outputs", font_name)
if not os.path.exists(destination_path):
return gr.update(
value="该名称字体不存在,再次确认字体名称", visible=True
)
# print(image_list)
for image in image_list:
# print(os.path.basename(image))
if not re.match(
r"^[\u4e00-\u9fff]\.png$", os.path.basename(image)
):
return gr.update(
value="图片格式有问题,文件名应为单个中文字符且以.png结尾",
visible=True,
)
img = Image.open(image)
if img.size != (96, 96):
return gr.update(
value="图片尺寸不为96x96", visible=True
)
shutil.copy2(
image,
os.path.join(destination_path, os.path.basename(image)),
)
return gr.update(visible=True)
upload_button.click(
upload_wrong_func,
inputs=[
upload_wrong_char_img,
font_name_input,
font_not_exists,
],
outputs=[upload_wrong_char],
)
make_sure_font_name.click(
sure_name,
inputs=[font_name_input],
outputs=[make_sure_font_name, font_not_exists],
)
with gr.Column() as column2:
sampling_step2 = gr.Slider(
20, 60, value=40, step=5, label="推理步数"
)
guidance_scale2 = gr.Slider(
1,
12,
value=7.5,
step=0.5,
label="分类器引导指数",
info="默认7.5",
)
re_gen = gr.Button("点击生成图片", variant="stop")
re_gen_before_name_sure = gr.Textbox(value="", interactive=False)
# 需要有一个一键复制的剩余的有问题的字的框
# show_left_character_input = gr.Textbox(label='不满意文字剩余', interactive=False, value='', visible=False)
@gr.render(inputs=tasks)
def render_add_rules(task_list):
incomplete = [
task for task in task_list if not task["render"]
] # 过滤出渲染未完成的任务
if len(incomplete) < 1:
return
for task in incomplete:
with gr.Row():
sure_images = gr.Image(task["path_pic"])
sure_button = gr.Button("确认", variant="secondary")
def sure_ok_image(sure_images_path, font_name_input, task=task):
task["render"] = True
shutil.copy2(
task["path_pic"],
os.path.join("outputs", font_name_input),
)
return task_list
sure_button.click(
sure_ok_image,
inputs=[sure_images, font_name_input],
outputs=tasks,
)
re_gen.click(
generate_font_pics,
inputs=[
font_name_input,
font_not_exists,
wrong_character_input,
sampling_step2,
guidance_scale2,
],
outputs=[tasks, re_gen_before_name_sure],
)
with gr.Tab(label="🛠️字体再生成"):
with gr.Column():
with gr.Row():
old_name = gr.Textbox(
label="旧字体名称", placeholder="请输入需要重新生成的旧字体名称"
)
new_name = gr.Textbox(
label="新字体名称",
placeholder="请输入需要重新生成的新字体名称,如果为空.则默认旧名称不变",
)
alert = gr.Textbox(
interactive=False,
visible=False,
value="请再确认一下旧字体名称,其不存在",
)
gen_new_font_button = gr.Button(
"🎢重新生成,约5分钟", variant="secondary"
)
progress = gr.Textbox(interactive=False, value="")
download_button = gr.DownloadButton(label="🎁点击下载", variant="stop")
gen_new_font_button.click(
fn=re_gen_font,
inputs=[old_name, new_name],
outputs=[progress, alert, download_button],
)
def dummy_function(image):
return image
Generate_Font.click(
fn=generate_font, # 当用户点击确认后调用的函数
inputs=[upload_pic_style, font_name, font_version, test_font_checkbox],
outputs=show,
)
refreshing.click(
fn=download_font, inputs=[font_name], outputs=[preview_image, download]
)
reference_image.upload(
dummy_function, inputs=reference_image, outputs=reference_image
)
FontDiffuser.click(
fn=run_fontdiffuer,
inputs=[
character,
reference_image,
sampling_step,
guidance_scale,
],
outputs=fontdiffuer_output_image,
)
# Add Gradio app as a FastAPI route
app = gr.mount_gradio_app(app, demo, path="/")
uvicorn.run(app, host="0.0.0.0", port=813, log_level="info")
# python font_complex_ui.py
# nohup python font_complex_ui.py > v_complex.log &