KanaWrite / app.py
penut85420's picture
implement shuffle queue
09633a1
import os
import random
from copy import deepcopy
import gradio as gr
import numpy as np
from romkan import to_roma
from ocr import Recognizer
kana_list = """
あいうえお
かきくけこ
がぎぐげご
さしすせそ
ざじずぜぞ
たちつてと
だぢづでど
なにぬねの
はひふへほ
ばびぶべぼ
ぱぴぷぺぽ
まみむめも
やゆよ
らりるれろ
わを
アイウエオ
カキクケコ
ガギグゲゴ
サシスセソ
ザジズゼゾ
タチツテト
ダヂヅデド
ナニヌネノ
ハヒフヘホ
バビブベボ
パピプペポ
マミムメモ
ヤユヨ
ラリルレロ
ワヲ
"""
kana_list = [c for c in kana_list if c.strip()]
chars = [os.path.join(dn, fn) for dn, _, ff in os.walk("chars") for fn in ff]
def init_chars():
curr_chars = deepcopy(chars)
random.shuffle(curr_chars)
return curr_chars
def get_char(ch=None, assist=True, kana=True, curr_chars: list = []):
if not curr_chars:
curr_chars = init_chars()
if ch is None:
img_path = curr_chars.pop()
ch = img_path[-5]
else:
img_path = f"chars/{ch}.png"
if not assist:
img_path = "bg.png"
info = f"{ch} ({to_roma(ch)})"
if not kana:
info = f"{to_roma(ch)}"
return ch, img_path, info, curr_chars
font = gr.themes.GoogleFont("Noto Sans")
theme = gr.themes.Soft(font=font)
with gr.Blocks(theme=theme, title="Kana Writer") as app:
ch = "あ"
char_img = "chars/あ.png"
roma = "あ (a)"
curr_img_path = gr.State(char_img)
curr_char = gr.State(ch)
curr_chars = gr.State([])
recog = Recognizer("model/model.xml", "model/char_list.txt")
with gr.Tab("寫字練習"):
brush = gr.Brush(default_color="#111", default_size=15)
sketch = gr.Sketchpad(
char_img,
type="numpy",
brush=brush,
layers=False,
image_mode="RGB",
eraser=False,
show_label=False,
)
with gr.Row():
header = gr.Textbox(roma, label="目標")
result = gr.Textbox(label="辨識結果")
with gr.Row():
with gr.Row():
assist = gr.Checkbox(True, label="輔助")
kana = gr.Checkbox(True, label="假名")
rand_btn = gr.Button("隨機")
check_btn = gr.Button("辨識")
def parse_item(item):
prob = item["prob"]
char = item["char"]
return f"{char} ({to_roma(char)}): {prob:.2%}"
def valid_item(item):
if item["prob"] < 1e-2:
return False
if item["char"] not in kana_list:
return False
return True
def do_recog(img: dict[str, np.ndarray]):
img: np.ndarray = img["layers"][0]
img[img == 0] = 255
img[img != 255] = 0
_, nbest = recog(img)
return ", ".join(parse_item(item) for items in nbest for item in items if valid_item(item))
def rand_char(assist, kana, chars):
char, img, roma, chars = get_char(None, assist, kana, chars)
return char, img, img, roma, None, chars
def clear(curr_char):
return curr_char
def change_opt(char, assist, kana, chars):
char, img, roma, chars = get_char(char, assist, kana, chars)
return char, img, img, roma, chars
check_btn.click(do_recog, sketch, result, show_progress="minimal")
rand_btn.click(
rand_char,
[assist, kana, curr_chars],
[curr_char, sketch, curr_img_path, header, result, curr_chars],
show_progress="minimal",
)
sketch.clear(clear, curr_img_path, sketch, show_progress="minimal")
assist.change(
change_opt,
[curr_char, assist, kana, curr_chars],
[curr_char, sketch, curr_img_path, header, curr_chars],
show_progress="minimal",
)
kana.change(
change_opt,
[curr_char, assist, kana, curr_chars],
[curr_char, sketch, curr_img_path, header, curr_chars],
show_progress="minimal",
)
app.launch()