Spaces:
Sleeping
Sleeping
File size: 4,043 Bytes
3b86270 09633a1 3b86270 d05d4ae 8837f64 d05d4ae 8837f64 3b86270 8837f64 09633a1 8837f64 09633a1 8837f64 09633a1 8837f64 3b86270 09633a1 8837f64 09633a1 d05d4ae 8837f64 3b86270 8837f64 d05d4ae 8837f64 d05d4ae 3b86270 8837f64 d05d4ae 09633a1 d05d4ae ba0dd03 09633a1 8837f64 ba0dd03 8837f64 09633a1 8837f64 09633a1 8837f64 09633a1 8837f64 d05d4ae |
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 |
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()
|