File size: 10,468 Bytes
578213d
 
 
 
 
 
 
 
 
 
 
 
 
a30ddd1
578213d
13c09f9
578213d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56102a9
578213d
 
 
 
 
 
 
 
 
 
56102a9
 
578213d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b09fcf
578213d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8b09fcf
578213d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ddc1053
578213d
 
 
 
 
 
 
 
 
 
ddc1053
578213d
8b09fcf
578213d
 
 
 
 
 
 
 
 
 
 
 
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
import pandas as pd
from PIL import Image
import streamlit as st
from streamlit_drawable_canvas import st_canvas
import numpy as np
from keras.models import load_model
from keras.preprocessing import image
import keras.utils as image
import cv2
from data import Getdetail

st.title('JLPTN5 handwriting Kanji recognition.')

labels = ['一', '七', '万', '三', '上', '下', '中', '九', '二', '五', '人', '今', '休', '何', '先', '入', '八', '六', '円', '出', '分', '前', '北', '十', '千', '午', '半', '南', '友', '右', '名', '四', '国', '土', '外', '大', '天', '女', '子', '学', '小', '山', '川', '左', '年', '後', '日', '明', '時', '書', '月', '木', '本', '来', '東', '校', '母', '毎', '気', '水', '火', '父', '生', '男', '白', '百', '聞', '行', '西', '見', '話', '語', '読', '車', '金', '長', '間', '雨', '電', '食', '高']

model = load_model("./vgg16_unfreeze3.h5")

st.sidebar.title("NihonGO !")
st.sidebar.caption("Handwriting kanji recognition system.")
options = ("Sketchpad input", "Image input", "about JLPTN5", "about NihonGO !")
choice = st.sidebar.selectbox("Select input options",options)
st.sidebar.caption("Dev by : Tanaanan Chalermpan")
st.sidebar.caption("Computer Science Kasetsart U. Thailand")



def predict_img_sketch(img_path):
        st.write("Predicted result.")
        if img_path is not None: 
            img = Image.fromarray(img_path) # use pillow to load a image
            img = img.convert('L')
            img = np.array(img) # convert img to an array
            ret, thresh1 = cv2.threshold(img, 110, 255, cv2.THRESH_BINARY)  # Apply binary threshold
            thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_GRAY2RGB)  # Convert back to RGB
            img_array = cv2.resize(thresh1, (120, 120))  # Resize the image
            img_array = np.expand_dims(img_array, axis=0)
            preds = model.predict(img_array)
            return preds
        
def image_display(img_path):
    st.write("Predicted image.")
    if img_path is not None:
        img = Image.open(img_path)
        img = img.resize((120,120)).convert('L')
        st.image(img, caption='Uploaded Image', use_column_width=True)

def predict_img_input(img_path):
        st.write("Predicted result.")
        if img_path is not None: 
            img = Image.open(img_path) # use pillow to load a image
            img = img.convert('L')
            img = np.array(img) # convert img to an array
            ret, thresh1 = cv2.threshold(img, 110, 255, cv2.THRESH_BINARY)  # Apply binary threshold
            thresh1 = cv2.cvtColor(thresh1, cv2.COLOR_GRAY2RGB)  # Convert back to RGB
            img_array = cv2.resize(thresh1, (120, 120))  # Resize the image
            img_array = np.expand_dims(img_array, axis=0)
            preds = model.predict(img_array)
            return preds

if choice == "Sketchpad input":
        

    col1,col2 = st.columns(2)
    with col2:
        stroke_width = st.slider("Stroke width: ", 8, 25, 8)

    with col1:
        # ref : https://github.com/andfanilo/streamlit-drawable-canvas
        canvas_result = st_canvas(
        fill_color="rgba(255, 165, 0, 0.3)",  # Fixed fill color with some opacity
        stroke_width=stroke_width,
        stroke_color="#000000", # stroke to black
        background_color="#FFFFFF", # background to write
        background_image= None,
        update_streamlit=False,
        height=300,
        width=300,
        drawing_mode="freedraw",
        point_display_radius=0,
        key="canvas",
    )
        # Do something interesting with the image data and paths
        if canvas_result.image_data is not None:
            st.image(canvas_result.image_data, caption='display_show')

    with col2:
        # check if sketchinput is empty from len json_data
        is_empty = 0
        if canvas_result.image_data is not None: # beware of slow loading
            is_empty = canvas_result.json_data["objects"] # need to convert obj to str because PyArrow
        
        if is_empty:
            # display prediction
            pred_raw = predict_img_sketch(canvas_result.image_data)
            if pred_raw is not None:    
                pred_class, accuracy = labels[np.argmax(pred_raw)], np.max(pred_raw)*100
                st.write(f"Class : {labels[np.argmax(pred_raw)]}")
                st.write(f"with probability : {accuracy:.2f} %")

                st.divider()
                strokes = Getdetail()[pred_class]['Strokes']
                meaning = Getdetail()[pred_class]['Meaning']
                onyoumi = Getdetail()[pred_class]['Onyoumi']
                kunyomi = Getdetail()[pred_class]['Kunyoumi']
                link_ref = Getdetail()[pred_class]['Reference']

                st.write(f"Strokes : {strokes}")
                st.write(f"Meaning : {meaning.capitalize()}")
                st.write(f"Onyoumi : {onyoumi}")
                st.write(f"Kunyoumi : {kunyomi}")
                st.write(f"for more detail : [Shirabe jisho]({link_ref})")

elif choice == "Image input":
    upload_img = st.file_uploader("Choose a kanji image", type=['.jpg', '.png', '.jpeg'])
    col1,col2 = st.columns(2)

    with col1:
        image_display(upload_img)

    with col2:
        # display prediction
        pred_raw = predict_img_input(upload_img)
        if pred_raw is not None:    
            pred_class, accuracy = labels[np.argmax(pred_raw)], np.max(pred_raw)*100
            st.write(f"Class : {labels[np.argmax(pred_raw)]}")
            st.write(f"with probability : {accuracy:.2f} %")

            st.write('---------------------------------------')
            strokes = Getdetail()[pred_class]['Strokes']
            meaning = Getdetail()[pred_class]['Meaning']
            onyoumi = Getdetail()[pred_class]['Onyoumi']
            kunyomi = Getdetail()[pred_class]['Kunyoumi']
            link_ref = Getdetail()[pred_class]['Reference']

            st.write(f"Strokes : {strokes}")
            st.write(f"Meaning : {meaning.capitalize()}")
            st.write(f"Onyoumi : {onyoumi}")
            st.write(f"Kunyoumi : {kunyomi}")
            st.write(f"for more detail : [Shirabe jisho]({link_ref})")

elif choice == "about JLPTN5":
    df = pd.read_csv('./passjapanesetest.com_N5_Kanji.csv', encoding='cp932')
    st.subheader("JLPT คืออะไร")
    detail_1 = '''ย่อมาจาก Japanese Language Proficiency Test  การสอบวัดระดับภาษาญี่ปุ่น คือ การสอบที่จัดขึ้นเพื่อวัดความสามารถทางภาษาญี่ปุ่น ของชาวต่างชาติผู้เรียนภาษาญี่ปุ่น
    
การสอบวัดระดับภาษาญี่ปุ่นครั้งแรก จัดขึ้นในปี ค.ศ. 1984  มีผู้สมัครสอบ 7,998 คน และมีผู้สมัครสอบเพิ่มขึ้นมากทุกปี   สถิติในปี ค.ศ. 2019 มีผู้สมัครสอบถึง 1,362,167 คนทั่วโลก'''
    st.markdown(detail_1)
    st.markdown('''- โดยระดับ N5 ถือเป็นระดับที่ง่ายที่สุดในการสอบ แต่พาร์ทที่หินที่สุดส่วนหนึ่งก็คือ พาร์ท คันจิ N5 ***ผู้พัฒนาจึงสร้างระบบที่วิเคราะห์ตัวอักษรคันจิได้จากลายมือเขียน 
                เพื่อที่จะเป็นตัวช่วยหนึ่งในการให้ผู้ใช้งานได้ใช้ในการฝึกฝนได้***''')

    st.caption("List of JLPTN5 Kanji")
    st.write(df)

    st.caption('ref : [jeducation](https://jeducation.com/main/education/jlpt/) , [passjapanesetest](http://www.passjapanesetest.com/jlpt-n5-kanji-list/)')

elif choice == "about NihonGO !":
    st.subheader("NihonGO ! คืออะไร")
    detail_2 = """NihonGO ! : เป็นระบบที่ใช้ในการวิเคราะห์ตัวอักษรคันจิจากลายมือเขียนโดยอัติโนมัติ โดยใช้หลักการของ Deep learning (Convolutional Neural Network) ในการแยกแยะตัวอักษรคันจิ
    เพื่อใช้เป็นตัวช่วยในการฝึกฝนการเขียนคันจิ และเป็นตัวช่วยในการฝึกฝนในการเตรียมสอบวัดระดับ JLPT"""
    st.markdown(detail_2)
    st.caption("Development.")
    st.markdown("- JLPTN5 : ระบบสามารถแยกแยะคันจิจำนวน 80 ตัวพื้นฐานตามเนื้อหาคันจิจากการสอบวัดระดับ JLPTN5")
    st.image('total_kanji.png', caption='JLPTN5 Kanji detail')
    st.subheader("Feature")
    st.markdown("""     1. บอกคันจิที่ระบบตรวจจับได้พร้อมกับค่าความเชื่อมั่น (probability score.)
                
    2. จำนวนเส้น stroke ที่ใช้ในการเขียนคันจิ
                
    3. เสียงอ่านแบบ Onyoumi กับ Kunyoumi พร้อมกับตัวอักษร Romanji
                
    4. Link เนื้อหาเพิ่มเติมโดยระเอียดกับ website Shirabe jisho""")
    st.subheader("Guideline")
    st.markdown(""" - เพื่อความแม่นยำของระบบ ตอนนำข้อมูลรูปภาพเข้า หรือเขียนในระบบแนะนำให้ผู้ใช้งานเขียนตัวคันจิให้อยู่ตรงกลาง และมีขนาดที่ใหญ่พอดีกับขนาดของกรอบ""")
    st.caption("ref : [kanshudo](https://www.kanshudo.com/collections/jlpt_kanji)")