提交 3caa54e2 编写于 作者: xuchaoxin1375's avatar xuchaoxin1375

- initially support the interface language switch:between Chinese and English

  - the approch to achieve the multilanguage support depending on language string resource py file:
    - `zh.py` for Chinese
    - `en.py` for english
  - for convenience,these module was managed by the `multilanguage.py`module.
  - unfortunately,these features was test in `fviewer.py`,the main gui was still unable to work normally because the `windows.close` caused the program broken!
- improve the regex_filter performance by using `re.compile` instead `re.<function>`
上级 7f9bda0c
此差异已折叠。
import PySimpleGUI as sg
# import constants.uiconfig as ufg
from SG.multilanguage import get_your_language_translator
from SG.multilanguage import get_language_translator,lang
lang = get_your_language_translator("English")
import sys
frame_size = (600, 50)
# frame_size=600#给定一个整形数的时候,仅指定宽度,高度被自动设置为1
# frame_size=None
#listbox_size
lb_size = (60, 10)
lb_narrow_size=(20,10)
ml_size = (60, 20)
seperator_color = "blue"
score_ndigits=4
......@@ -22,60 +23,9 @@ tips_bgc='lightyellow'
result_font = ("Arial", 20, "bold underline")
normal_font=("Arial", 10,"italic")
logo = """
░█████╗░░█████╗░░██████╗███████╗██████╗░░░░░░░░█████╗░██╗░░░░░██╗███████╗███╗░░██╗████████╗𝓫𝔂 𝓬𝔁𝔁𝓾
██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗░░░░░░██╔══██╗██║░░░░░██║██╔════╝████╗░██║╚══██╔══╝
██║░░╚═╝██║░░╚═╝╚█████╗░█████╗░░██████╔╝█████╗██║░░╚═╝██║░░░░░██║█████╗░░██╔██╗██║░░░██║░░░
██║░░██╗██║░░██╗░╚═══██╗██╔══╝░░██╔══██╗╚════╝██║░░██╗██║░░░░░██║██╔══╝░░██║╚████║░░░██║░░░
╚█████╔╝╚█████╔╝██████╔╝███████╗██║░░██║░░░░░░╚█████╔╝███████╗██║███████╗██║░╚███║░░░██║░░░
░╚════╝░░╚════╝░╚═════╝░╚══════╝╚═╝░░╚═╝░░░░░░░╚════╝░╚══════╝╚═╝╚══════╝╚═╝░░╚══╝░░░╚═╝░░░
"""
pca_components_tooltip = """
PCA components
Number of components to keep. if n_components is not set all
components are kept:
n_components == min(n_samples, n_features)
If n_components == 'mle' and svd_solver == 'full', Minka’s MLE
is used to guess the dimension. Use of n_components == 'mle' will
interpret svd_solver == 'auto' as svd_solver == 'full'.
If 0 < n_components < 1 and svd_solver == 'full', select
the number of components such that the amount of variance that
needs to be explained is greater than the percentage specified
by n_components.
If svd_solver == 'arpack', the number of components must
be strictly less than the minimum of n_features and n_samples.
Hence, the None case results in:
n_components == min(n_samples, n_features) - 1
"""
pca_svd_solver_tooltip = """
If auto :
The solver is selected by a default policy based on X.shape and
n_components:
if the input data is larger than 500x500 and the number of components
to extract is lower than 80% of the smallest dimension of the data,
then the more efficient ‘randomized’ method is enabled. Otherwise
the exact full SVD is computed and optionally truncated afterwards.
If full :
run exact full SVD calling the standard LAPACK solver via scipy.
linalg.svd and select the components by postprocessing
If arpack :
run SVD truncated to n_components calling ARPACK solver via
scipy.sparse.linalg.svds. It requires strictly
0 < n_components < min(X.shape)
If randomized :
run randomized SVD by the method of Halko et al.
"""
......@@ -256,7 +206,7 @@ def option_frame(
def result_frame(
title=lang["result_frame"],
title=lang.result_frame_prompt,
# result="inputYourContentToHighligt",
layout=None,
title_color=title_color,
......
ASCII_Art_logo = """
░█████╗░░█████╗░░██████╗███████╗██████╗░░░░░░░░█████╗░██╗░░░░░██╗███████╗███╗░░██╗████████╗𝓫𝔂 𝓬𝔁𝔁𝓾
██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗░░░░░░██╔══██╗██║░░░░░██║██╔════╝████╗░██║╚══██╔══╝
██║░░╚═╝██║░░╚═╝╚█████╗░█████╗░░██████╔╝█████╗██║░░╚═╝██║░░░░░██║█████╗░░██╔██╗██║░░░██║░░░
██║░░██╗██║░░██╗░╚═══██╗██╔══╝░░██╔══██╗╚════╝██║░░██╗██║░░░░░██║██╔══╝░░██║╚████║░░░██║░░░
╚█████╔╝╚█████╔╝██████╔╝███████╗██║░░██║░░░░░░╚█████╔╝███████╗██║███████╗██║░╚███║░░░██║░░░
░╚════╝░░╚════╝░╚═════╝░╚══════╝╚═╝░░╚═╝░░░░░░░╚════╝░╚══════╝╚═╝╚══════╝╚═╝░░╚══╝░░░╚═╝░░░
"""
\ No newline at end of file
......@@ -37,8 +37,7 @@ class TablePandas():
layout = self.create_table_window(df)
window = sg.Window("Pandas Table Viewer", layout)
return window
# def show_confution_matrix_window(df):
# window=get_confution_matrix_window(df)
def show_confution_matrix_window(self,df=None):
......
......@@ -8,19 +8,24 @@ from config.MetaPath import speech_dbs_dir, savee
import constants.uiconfig as ufg
import table_show as ts
import constants.beauty as bt
from SG.multilanguage import get_language_translator
# from recognizer.basic import EmotionRecognizer
import data_visualization as dv
# from SG.translations import en,zh
language = "en"
lang = get_language_translator(language)
# 主题设置说明:当主题设置语句防止在程序的末尾时可能是无效的
# 猜测sg.theme()设置完主题后,后续在调用sg的元素创建方法才会有相应主题的配色
# 如果控件都已经创建好了才开始调用sg.theme()修改配色,那来不及起作用了
sg.theme(bt.ccser_theme)
# 常量
listbox_default_value_tip = "hover your mouse in this listbox area to check tooltips!"
audio_listbox_values = [
"click filter or input regex to scan audio file!",
listbox_default_value_tip,
lang.click_filter_prompt,
lang.listbox_default_value_prompt,
]
# 将变量设置在事件循环中可能会反复被初始化,这里我们应该放在事件循环的外部
......@@ -34,25 +39,11 @@ selected_files = []
# er: EmotionRecognizer = None
er = None
t: ts.TableShow = None
filter_tooltip = """
the listbox of files allow you to choose one or more files \n using left button of your mouse,
you can use `Ctrl+Click` to select multiple files(jump to the selected file is allowed too!)
you can right click after you choose one or more files to do something like these:
1.file size
2.file path(absolute path)
3.recognize emotion
4.play file(audio) you choosed
*.all of above could work in multiple files one by one automatically
"""
selected_files_tooltip = """
you can observe the files your choosed in last listBox
Whether it is a continuous selection or a skip selection,
these selected files will be tightly arranged and
the number of files will be displayed at the top
"""
filter_input_key = "filter_input"
selected_files_tooltip = lang.selected_files_tooltip
filter_tooltip = lang.filter_tooltip
filter_input_key = "filter_input"
files_browsed_key = "files browsed"
selected_files_listbox_key = "selected_files_list"
num_selected_files_key = "num_selected_files"
......@@ -64,6 +55,8 @@ audio_file_list_key = "audio_files_list"
confirm_files_selected_key = "confirm files selected"
confirm_folder_selected_key = "confirm folder selected"
filter_audios_key = "filter audios"
speech_folder_path_input_key = "speech_folder_path_input"
speech_folder_path_chooser_key = "speech_folder_path_chooser"
##
......@@ -96,6 +89,15 @@ def get_audios_regex(
)
# 调试模式,切片出一小部分来试验算法
# audios=audios[:50]
# 正则表达式模式
if filter_regex:
if verbose:
print("filter_regex:> ", filter_regex)
# 由于这里需要反复使用正则匹配,因此采用编译的方式来提高性能
p = re.compile(filter_regex, re.IGNORECASE)
# s = re.search(filter_regex, str(path), re.IGNORECASE)
filtered_audios = []
for path in audios:
# print(path)
......@@ -106,11 +108,9 @@ def get_audios_regex(
else:
path = path.absolute()
# 对路径进行正则过滤
#todo 对括号的识别有问题(得益于模块化,可以直接在这个模块内启动图形界面进行调试)
# todo 对括号的识别有问题(得益于模块化,可以直接在这个模块内启动图形界面进行调试)
if filter_regex:
if verbose:
print('filter_regex:> ', filter_regex)
s = re.search(filter_regex, str(path), re.IGNORECASE)
s = p.search(str(path))
if s:
filtered_audios.append(path)
else:
......@@ -154,8 +154,7 @@ def get_audios(folder, exts, pattern="*", recursive=False, flatten=True, verbose
##
# 创建GUI窗口
folder_browse_init_dir = speech_dbs_dir / savee # 作为一个初始值
speech_folder_path_input_key = "speech_folder_path_input"
speech_folder_path_chooser_key = "speech_folder_path_chooser"
default_folder_file_list = get_audios_regex(
recursive=True, speech_folder_root=speech_dbs_dir, short=True
)
......@@ -166,102 +165,131 @@ len_default_folder_file_list = len(default_folder_file_list)
right_click_menu = [
"",
["Show File Path", "Show File Size", "Play Audio", "Emotion Recognize"],
[lang.show_file_path, lang.show_file_size, lang.play_audio, lang.emotion_recognize],
]
audio_viewer_layout = [
[sg.Text("Select a directory:")],
[
sg.InputText(
default_text=speech_folder,
key=speech_folder_path_input_key,
tooltip="you can paste or type a dir path!\n or use the right side Browse button to choose a dir",
),
sg.FolderBrowse(
initial_folder=folder_browse_init_dir,
button_text="folder browse",
change_submits=True,
key=speech_folder_path_chooser_key,
target=speech_folder_path_input_key,
# enable_events=True,
tooltip=f"choose a folder you want to do SER,\nthe default folder is {speech_folder}",
),
],
[sg.B(confirm_folder_selected_key)],
[
sg.Input(
default_text="select multiple files,which will be shown here ",
key=files_browsed_key,
),
# sg.Text(text="files selected by filesBrowse will be shown \n in the listbox below"),
sg.FilesBrowse(
target=files_browsed_key,
key="FilesBrowse",
enable_events=True,
change_submits=True,
),
sg.OK(key="confirm files selected"),
],
[
sg.Text("current directory:"),
sg.Text(f"{speech_folder}", key="current_dir"),
],
[
sg.Checkbox(
text="Recursively scan subdirectories",
default=True,
key=recursive_checkbox_key,
enable_events=True,
),
sg.Checkbox(
text="auto refresh",
default=False,
key=auto_refresh_checkbox_key,
enable_events=True,
),
sg.Checkbox(
text="short path", default=True, key=short_path_checkbox_key, enable_events=True
),
],
[
sg.Text("Filter by regex:"),
sg.InputText(key="filter_input", default_text="", enable_events=True),
],
[
sg.B(filter_audios_key, tooltip="click to manual refresh the files listbox"),
# sg.Button(ufg.close),
],
[sg.Text(f"{len_default_folder_file_list} files", key="num_files_text")],
[
sg.Listbox(
values=default_folder_file_list,
# size=(50, 10),
size=bt.lb_size,
key=audio_file_list_key,
enable_events=True,
bind_return_key=True,
tooltip=filter_tooltip,
# 定义位于列表中条目的右键菜单内容
right_click_menu=right_click_menu,
select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,
no_scrollbar=True,
)
],
[
sg.Text("Selected audio files:"),
sg.Text(f"0 files", key=num_selected_files_key),
],
[
sg.Listbox(
values=audio_listbox_values,
size=bt.lb_size,
key=selected_files_listbox_key,
tooltip=selected_files_tooltip,
right_click_menu=right_click_menu,
select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,
)
],
]
files_selected_prompt = lang.files_selected_prompt
def audio_viewer_layout(theme=""):
if theme:
sg.theme(theme)
audio_viewer_layout = [
[sg.Text(lang.select_dir_prompt),
# change the visible to True to try the language and theme switch!
sg.Button("restart", visible=False)],
[
sg.InputText(
default_text=speech_folder,
key=speech_folder_path_input_key,
tooltip=lang.path_input_tooltip,
),
sg.FolderBrowse(
initial_folder=folder_browse_init_dir,
button_text=lang.folder_browse,
change_submits=True,
key=speech_folder_path_chooser_key,
target=speech_folder_path_input_key,
# enable_events=True,
tooltip=f"{lang.choose_folder_tooltip}{speech_folder}",
),
],
[sg.Button(lang.confirm_folder_selected, key=confirm_folder_selected_key)],
[
sg.Input(
default_text=files_selected_prompt,
key=files_browsed_key,
),
# sg.Text(text="files selected by filesBrowse will be shown \n in the listbox below"),
sg.FilesBrowse(
button_text=lang.files_browse,
target=files_browsed_key,
key="FilesBrowse",
enable_events=True,
change_submits=True,
),
],
[
sg.OK(
button_text=lang.confirm_files_selected_button,
key=confirm_files_selected_key,
),
],
[
sg.Text(lang.current_directory_prompt),
sg.Text(f"{speech_folder}", key="current_dir"),
],
[
sg.Checkbox(
text=lang.recursively_scan_subdir,
default=True,
key=recursive_checkbox_key,
enable_events=True,
),
sg.Checkbox(
text=lang.auto_refresh,
default=False,
key=auto_refresh_checkbox_key,
enable_events=True,
),
sg.Checkbox(
text=lang.short_path,
default=True,
key=short_path_checkbox_key,
enable_events=True,
),
],
[
sg.Text(lang.filter_by_regex_prompt),
sg.InputText(key="filter_input", default_text="", enable_events=True),
],
[
sg.Button(
button_text=lang.filter_audios,
key=filter_audios_key,
tooltip=lang.auto_refresh_tooltip,
),
# sg.Button(ufg.close),
],
[sg.Text(f"{len_default_folder_file_list} files", key="num_files_text")],
[
sg.Listbox(
values=default_folder_file_list,
# size=(50, 10),
size=bt.lb_size,
key=audio_file_list_key,
enable_events=True,
bind_return_key=True,
tooltip=filter_tooltip,
# 定义位于列表中条目的右键菜单内容
right_click_menu=right_click_menu,
select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,
no_scrollbar=True,
)
],
[
sg.Text(lang.selected_audios_prompt),
sg.Text(lang.no_files, key=num_selected_files_key),
],
[
sg.Listbox(
values=audio_listbox_values,
size=bt.lb_size,
key=selected_files_listbox_key,
tooltip=selected_files_tooltip,
right_click_menu=right_click_menu,
select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED,
)
],
]
return audio_viewer_layout
def make_window(theme):
window = sg.Window("Audio Viewer", audio_viewer_layout(theme), resizable=True)
return window
# 定义文件大小计算函数
......@@ -319,14 +347,19 @@ def get_abs_selected_pathes(speech_folder_path, selected_files):
def main():
layout = audio_viewer_layout
window = sg.Window("Audio File Filter", layout, resizable=True)
layout = audio_viewer_layout()
global lang
window = sg.Window(lang.audios_filter, layout, resizable=True)
while True:
event, values = window.read()
print(event, "@{event} main")
if event in (sg.WINDOW_CLOSED, ufg.close):
break
elif event == "restart":
window.close()
print("closed successfully!")
lang = get_language_translator("zh")
window = make_window(theme="Reds")
else:
# 处理事件(小心,如果下面的函数编写不当,可能使得某些控件不能够正常工作)
# 例如,FolderBrowser生成的按钮点击无法呼出系统的资源管理器(或者需要反复点击)
......@@ -355,7 +388,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
# 判断手动输入的路径是否合法
if event == confirm_folder_selected_key:
path = values[speech_folder_path_input_key]
print(path, "was confirmed")
print(path, "was confirmed!")
if Path(path).exists():
speech_folder = path
# 更新当前speech_path控件
......@@ -363,7 +396,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
# 更新文件列表视图
refresh_viewer(window, speech_folder=path, values=values)
else:
sg.popup_error(f"{path} not exist!")
sg.popup_error(f"{path} {lang.not_exist}")
# 刷新文件列表
elif event == filter_input_key and not values[auto_refresh_checkbox_key]:
return
......@@ -387,7 +420,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
refresh_selected_view(window, num_selected_files)
# 处理 "Show File Path" 事件
elif event == "Show File Path":
elif event == lang.show_file_path:
res = []
for file in selected_files:
res.append(get_absolute_path(speech_folder, file))
......@@ -395,7 +428,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
sg.popup(selected_file_pathes, title="File Path")
# 处理 "Show File Size" 事件
elif event == "Show File Size":
elif event == lang.show_file_size:
# selected_file = get_abs_selected_pathes(speech_folder_path, selected_files)
res = []
for selected_file in selected_files:
......@@ -407,7 +440,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
res = "\n".join(res)
sg.popup(f"{res}", title="File Size")
# 处理 "Play Audio" 事件
elif event == "Play Audio":
elif event == lang.play_audio:
pathes = get_abs_selected_pathes(speech_folder, selected_files)
print(pathes, selected_files)
......@@ -421,7 +454,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
# 播放音频
audio_file = AudioSegment.from_file(audio_path, format=ext)
play(audio_file)
elif event == "Emotion Recognize":
elif event == lang.emotion_recognize:
# print()
# 为了完成多选文件(成批识别),经过brainstorm,提出以下idea:
# 委托给ccser_gui模块来处理,通过共享变量来简单通信/创建一个媒介模块来解决相互导入的问题(对于这种简单的场景够用的)
......@@ -431,7 +464,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
# 这里的识别应该在训练阶段完成之后才调用的,否则程序应该组织这样跨阶段的行为,提高robustness
if er == None:
print("请先完成识别器训练,然后再执行识别操作")
sg.popup("please train the SER model and then try angin!")
sg.popup(lang.train_model_warning, text_color="red")
else:
print(f"the emotion recognizer is {er}!")
res_content: list[str] = []
......@@ -448,7 +481,9 @@ def fviewer_events(window, event=None, values=None, verbose=1):
print(emo_res, "@{emo_res}")
print(abs_pathes, "@{abs_pathes}")
t = ts.TableShow(header=["emotion", "path"], data_lists=[emo_res, abs_pathes])
t = ts.TableShow(
header=["emotion", "path"], data_lists=[emo_res, abs_pathes]
)
print(t.lists, "@{t.lists}")
t.run()
......@@ -460,9 +495,7 @@ def fviewer_events(window, event=None, values=None, verbose=1):
def refresh_selected_view(window, num_selected_files):
# 数量
window[num_selected_files_key].Update(
f"Selected audio files: ({num_selected_files} files)"
)
window[num_selected_files_key].Update(f"({num_selected_files}{lang.files_count})")
# 内容
window[selected_files_listbox_key].Update(values=selected_files)
......@@ -479,7 +512,7 @@ def refresh_viewer(window, speech_folder=None, values=None, delay=1, verbose=1):
recursive = values[recursive_checkbox_key]
short = values[short_path_checkbox_key]
filter_regex = values[filter_input_key]
auto_refresh=values[auto_refresh_checkbox_key]
auto_refresh = values[auto_refresh_checkbox_key]
# print(short, "@{short}🎈")
......@@ -496,7 +529,9 @@ def refresh_viewer(window, speech_folder=None, values=None, delay=1, verbose=1):
num_files = len(audio_files)
# 将扫描到的文件更新到窗口对应组件中,在下一次read方法调用时,画面就会显示新的内容
window[audio_file_list_key].update(values=audio_files)
window[num_files_key].update(f"Filtered audio files: ({num_files} files)")
window[num_files_key].update(
f"{lang.filterd_audios}({num_files} {lang.files_count})"
)
if __name__ == "__main__":
......
import PySimpleGUI as sg
import json
from config.MetaPath import trans_en,trans_zh
from config.MetaPath import trans_en_json,trans_zh_json
from SG.translations import en,zh
# lang\["(.+)"\]
#lang.$1
lang=en
English_marks = ('English','英文','en')
Chinese_marks = ('中文',"Chinese",'zh','cn')
def get_your_language_translator(language="English"):
if language in ('English','英文'):
with open(trans_en, 'r',encoding='utf-8') as f:
def get_language_translator(language="English"):
global lang
if language in English_marks:
lang=en
# return en
# return zh
elif language in Chinese_marks:
lang=zh
return lang
def get_language_translator_json(language="Chinese"):
if language in English_marks:
with open(trans_en_json, 'r',encoding='utf-8') as f:
translations = json.load(f)
elif language in ('中文',"Chinese"):
elif language in Chinese_marks:
# encoding='utf-8',否则中文字符报错:UnicodeDecodeError: 'charmap' codec can't decode byte 0x81 in position 53: character maps to <undefined>
with open(trans_zh, 'r',encoding='utf-8') as f:
with open(trans_zh_json, 'r',encoding='utf-8') as f:
translations = json.load(f)
return translations
lang=translations
return lang
......@@ -35,10 +52,11 @@ def run_app():
break
elif event == 'OK':
# 根据用户的选择读取相应的语言翻译文件
translations = get_your_language_translator(values)
translations = get_language_translator(values['language'])
print(translations,values)
# 显示欢迎消息
welcome_message = translations['welcome_message']
# welcome_message = translations['welcome_message']
welcome_message = translations.welcome_message
window['welcome_message'].update(welcome_message)
# 关闭 GUI 窗口
......@@ -46,4 +64,7 @@ def run_app():
if __name__ == '__main__':
run_app()
\ No newline at end of file
# res=get_your_language_translator('中文')
# print('res: ', res)
run_app()
\ No newline at end of file
recursive
\ No newline at end of file
emotion
\ No newline at end of file
import PySimpleGUI as sg
import pandas as pd
from config.MetaPath import recognize_result_dir
from SG.multilanguage import get_language_translator,lang
class TableShow():
def __init__(self,header=None,data_lists=None):
"""将二维列表作为表格数据显示
......@@ -22,7 +24,7 @@ class TableShow():
self.data_df=pd.DataFrame(self.data_rows,columns=self.header)
# 创建表格布局
warning="the save operation will comsume some time to complete!Be patient!"
save_patient_warning=lang.save_patient_warning
self.layout = [
[
sg.Table(
......@@ -37,9 +39,9 @@ class TableShow():
expand_y=True,
)
],
[sg.Text("if you want to recognize the next batch files,please close the window first!\n in the future,the client may be support multiple threads to improve the user experience")],
[sg.Text("save result to a csv file")],
[sg.Button(f"save to file",tooltip=f"click to save to a csv file!\n{warning}")],
[sg.Text(lang.close_table_prompt)],
[sg.Text(lang.save_to_csv_prompt)],
[sg.Button(f"save to file",tooltip=f"{save_patient_warning}")],
]
def run(self):
......
##
import re
p=re.compile(r'\s*(.*)(\s*=.*)')
from config.MetaPath import trans_en,trans_zh,project_dir,translations_dir
res=[]
with open(trans_en,'r',encoding='utf-8')as fe:
with open(trans_zh,'r',encoding='utf-8')as fz:
i=1
for e,z in zip(fe,fz):
# print(e,z)
# print(i)
# i+=1
if e.strip() and z.strip():
varName=p.search(e).group(1)
# print('varName: ', varName)
value=p.search(z).group(2)
line=f'{varName}{value}'
# print(line)
res.append(line)
else:res.append(z.strip())
with open(trans_zh,'w',encoding='utf-8') as fout:
for line in res:
fout.write(line+'\n')
print(line)
\ No newline at end of file
##
import re
from config.MetaPath import trans_en,trans_zh,project_dir,translations_dir
# p=re.compile(r'"(.*)"(=".*")')
text = '"result_training": "result of model training:",'
p = re.compile(r'\s*"(.+?)"(.*?:)(.*".+"),?')
r = "./en.json"
t = "./en.py"
r="./zh.json"
t="./zh.py"
r,t=translations_dir/r,translations_dir/t
with open(file=r,mode='r',encoding='utf-8') as fin:
with open(file=t,mode='w',encoding='utf-8') as fout:
for line in fin:
if line.strip() in ['{','}']:
continue
res=p.sub(r"\1 = \3", line,1)
fout.write(res)
print(res)
# print(res,"@{res}")
# import en
# en.result_frame
......@@ -2,15 +2,15 @@
"welcome_message": "Welcome to My App!",
"choose_emotion_config": "Please select an emotional combination for testing: recommended combinations are AS, HNS, AHNS, AHNPS. \nNote that there is a difference between 'surprise' and 'pleasantSurprise' in the SAVEE dataset, \nso the AHNPS combination is not recommended for use on SAVEE.",
"choose_feature_config": "Please choose one or more features",
"feature_transform_config":"feature transformer config",
"feature_transform_config": "feature transformer config",
"choose_algorithm": "Choose an algorithm for testing",
"choose_audio": "Please select an audio sample file to recognize its emotion.",
"recognize_the_audio_emotion": "Recognize the emotion of the selected audio file.",
"draw_diagram":"choose one diagram to draw",
"draw_diagram": "choose one diagram to draw",
"draw_diagram_detail": "Draw the [waveform|spectrogram|Mel spectrogram] of the selected file:",
"welcome_title": "𝒲ℯ𝓁𝒸ℴ𝓂ℯ 𝓉ℴ ℯ𝓍𝓅ℯ𝓇𝒾ℯ𝓃𝒸ℯ 𝒞𝒞𝒮ℰℛ 𝒞𝓁𝒾ℯ𝓃𝓉!",
"result_training":"result of model training:",
"train_result_title":"Train Result",
"result_frame":"Emotion Of Select File(Predict Result)",
"recognize_it":"Recognize it"
"result_training": "result of model training:",
"train_result_title": "Train Result",
"result_frame": "Emotion Of Select File(Predict Result)",
"recognize_it": "Recognize it"
}
\ No newline at end of file
welcome_message = "Welcome to My App!"
choose_emotion_config = "Please select an emotional combination for testing: recommended combinations are AS, HNS, AHNS, AHNPS. \nNote that there is a difference between 'surprise' and 'pleasantSurprise' in the SAVEE dataset, \nso the AHNPS combination is not recommended for use on SAVEE."
choose_feature_config = "Please choose one or more features"
feature_transform_config = "feature transformer config"
choose_algorithm = "Choose an algorithm for testing"
choose_audio = "Please select an audio sample file to recognize its emotion."
recognize_the_audio_emotion = "Recognize the emotion of the selected audio file."
draw_diagram = "choose one diagram to draw"
draw_diagram_detail = "Draw the [waveform|spectrogram|Mel spectrogram] of the selected file:"
welcome_title = "𝒲ℯ𝓁𝒸ℴ𝓂ℯ 𝓉ℴ ℯ𝓍𝓅ℯ𝓇𝒾ℯ𝓃𝒸ℯ 𝒞𝒞𝒮ℰℛ 𝒞𝓁𝒾ℯ𝓃𝓉!"
result_training = "result of model training:"
train_result_title = "Train Result"
result_frame_prompt = "Emotion Of Select File(Predict Result)"
recognize_it = "Recognize it"
WaveForm = "WaveForm"
FreqGraph = "FreqGraph"
MelFreqGraph = "MelFreqGraph"
algorithmes_chooser_title="Algorithms chooser"
choose_emotion_config_title="choose the emotion config"
emotion_config_legend="Emotion Config chooser"
feature_transform_legend="Feature Transform chooser"
feature_config_legend="Feature Config chooser"
n_components_tooltip="input the number of components to keep."
n_components_prompt='n_components:'
demension_prompt="feature_dimension:"
pending_prompt="pending"
other_parameter_legend="Other Parameter Settings"
select_training_db="Select the training database"
select_testing_db="Select the testing database"
files_selected_prompt="select multiple files,which will be shown here "
confirm_files_selected_button="confirm files selected"
recursively_scan_subdir="Recursively scan subdirectories"
auto_refresh="auto refresh"
auto_refresh_tooltip="click to manual refresh the files listbox"
short_path="short path"
filter_by_regex_prompt="Filter by regex:"
selected_audios_prompt="Selected audio files:"
no_files=f"0 files"
audios_filter="Audio File Filter"
filterd_audios="Filtered audio files: "
files_count=" files"
train_model_warning="please train the SER model and then try angin!"
selected_files_tooltip = """
you can observe the files your choosed in last listBox
Whether it is a continuous selection or a skip selection,
these selected files will be tightly arranged and
the number of files will be displayed at the top
"""
filter_tooltip = """
the listbox of files allow you to choose one or more files \n using left button of your mouse,
you can use `Ctrl+Click` to select multiple files(jump to the selected file is allowed too!)
you can right click after you choose one or more files to do something like these:
1.file size
2.file path(absolute path)
3.recognize emotion
4.play file(audio) you choosed
*.all of above could work in multiple files one by one automatically
"""
not_exist="not exist!"
confirm_folder_selected= "confirm folder selected"
folder_browse="folder browse"
choose_folder_tooltip="choose a folder you want to do SER,\nthe default folder is "
files_browse="browse files"
current_directory_prompt="current directory:"
show_file_path="Show File Path"
show_file_size="Show File Size"
play_audio="Play Audio"
emotion_recognize="Emotion Recognize"
path_input_tooltip="you can paste or type a dir path!\n or use the right side Browse button to choose a dir"
click_filter_prompt="click filter or input regex to scan audio file!"
listbox_default_value_prompt = "hover your mouse in this listbox area to check tooltips!"
filter_audios="filter audios"
select_dir_prompt="Select a directory:"
save_patient_warning="click to save to a csv file!\nthe save operation will comsume some time to complete!Be patient!"
close_table_prompt="if you want to recognize the next batch files,please close the window first!\n in the future,the client may be support multiple threads to improve the user experience"
save_to_csv_prompt="save result to a csv file"
emotion_field="emotion"
proba_field="proba"
show_confusion_matrix="show confusion matrix"
welcome="WelcomeUser"
main_page="MainPage"
analyzer="Analyzer"
settings="Settings"
about="about"
OK="OK"
clear_history="Clear History"
set_theme="Set Theme"
theme_prompt="See how elements look under different themes by choosing a different theme here!"
train_score="train_score"
test_score="test_score"
start_train="start train"
pca_components_tooltip = """
PCA components
Number of components to keep. if n_components is not set all
components are kept:
n_components == min(n_samples, n_features)
If n_components == 'mle' and svd_solver == 'full', Minka’s MLE
is used to guess the dimension. Use of n_components == 'mle' will
interpret svd_solver == 'auto' as svd_solver == 'full'.
If 0 < n_components < 1 and svd_solver == 'full', select
the number of components such that the amount of variance that
needs to be explained is greater than the percentage specified
by n_components.
If svd_solver == 'arpack', the number of components must
be strictly less than the minimum of n_features and n_samples.
Hence, the None case results in:
n_components == min(n_samples, n_features) - 1
"""
pca_svd_solver_tooltip = """
If auto :
The solver is selected by a default policy based on X.shape and
n_components:
if the input data is larger than 500x500 and the number of components
to extract is lower than 80% of the smallest dimension of the data,
then the more efficient ‘randomized’ method is enabled. Otherwise
the exact full SVD is computed and optionally truncated afterwards.
If full :
run exact full SVD calling the standard LAPACK solver via scipy.
linalg.svd and select the components by postprocessing
If arpack :
run SVD truncated to n_components calling ARPACK solver via
scipy.sparse.linalg.svds. It requires strictly
0 < n_components < min(X.shape)
If randomized :
run randomized SVD by the method of Halko et al.
"""
file_browse="BrosweFile"
fold_field="fold"
accu_score_field="accu_score"
application_menu="&Application"
exit_menu="E&xit"
help_menu="Help"
introduction_menu="Introduction"
predict_proba_legend="predict_proba"
current_model_prompt="current model:"
no_result_yet = f"No Result Yet"
language_switch="Switch"
import SG.constants.logo as logo
welcome_message = "欢迎来到我的应用程序!"
choose_emotion_config = """
请选择一个情感组合进行测试:建议使用AS、HNS、AHNS、AHNPS组合。请注意,在SAVEE数据集中,
“surprise”和“pleasantSurprise”之间存在差异,因此不建议在SAVEE上使用AHNPS组合。
"""
choose_feature_config = "请选择一个或多个特征"
feature_transform_config = "特征变换器配置"
choose_algorithm = "选择一个算法进行测试"
choose_audio = "请选择一个音频样本文件以识别其情感"
recognize_the_audio_emotion = "识别所选音频文件的情感"
draw_diagram = "选择一个图表进行绘制"
draw_diagram_detail = "绘制所选文件的[波形图|频谱图|Mel频谱图]:"
welcome_title = "𝒲ℯ𝓁𝒸ℴ𝓂ℯ 𝓉ℴ ℯ𝓍𝓅ℯ𝓇𝒾ℯ𝓃𝒸ℯ 𝒞𝒞𝒮ℰℛ 𝒞𝓁𝒾ℯ𝓃𝓉!"
result_training = "模型训练结果:"
train_result_title = "训练结果"
result_frame_prompt = "所选文件的情感(预测结果)"
recognize_it = "开始识别"
WaveForm = "波形图"
FreqGraph = "频谱图"
MelFreqGraph = "Mel频谱图"
algorithmes_chooser_title = "算法选择器"
choose_emotion_config_title = "情感配置选择器"
emotion_config_legend = "选择情感配置"
feature_transform_legend = "特征变换选择器"
feature_config_legend = "特征配置选择器"
n_components_tooltip = "输入要保留的成分数。"
n_components_prompt = "主成分数:"
demension_prompt = "特征维数:"
pending_prompt = "待处理"
other_parameter_legend = "其他参数设置"
select_training_db = "选择训练数据库"
select_testing_db = "选择测试数据库"
files_selected_prompt = "已选择的文件:"
confirm_files_selected_button = "确认所选文件"
recursively_scan_subdir = "递归扫描子目录"
auto_refresh = "自动刷新"
auto_refresh_tooltip = "点击手动刷新文件列表框"
short_path = "短路径模式"
filter_by_regex_prompt = "使用正则表达式过滤:"
selected_audios_prompt = "已选择的音频文件:"
no_files = "0 个文件"
audios_filter = "音频文件过滤"
filterd_audios = "过滤后的音频文件:"
files_count = " 个文件"
train_model_warning = "请先训练SER模型,然后再试一次!"
selected_files_tooltip = """
您可以观察上一个列表框中选择的文件,无论是连续选择还是跳跃选择,这些选择的文件都将被紧密排列,并在顶部显示文件数量。
"""
filter_tooltip = """
文件列表框允许您使用鼠标的左键选择一个或多个文件,您可以使用Ctrl +单击选择多个文件(还可以跳转到所选文件!)
您可以选择一个或多个文件后右键单击以执行以下操作:
1.文件大小
2.文件路径(绝对路径)
3.识别情感
4.播放所选文件(音频)
*.以上所有内容都可以在多个文件中自动一一工作
"""
not_exist = "不存在!"
confirm_folder_selected = "确认已选择的文件夹"
folder_browse = "浏览文件夹"
choose_folder_tooltip = "选择一个要进行SER的文件夹, 默认文件夹为 "
files_browse = "浏览文件"
current_directory_prompt = "当前目录:"
show_file_path = "显示文件路径"
show_file_size = "显示文件大小"
play_audio = "播放音频"
emotion_recognize = "情感识别"
path_input_tooltip = "您可以粘贴或输入目录路径!或使用右侧的浏览按钮选择目录"
click_filter_prompt = "点击过滤器或输入正则表达式来扫描音频文件!"
listbox_default_value_prompt = "将鼠标悬停在此列表框区域以查看工具提示!"
filter_audios = "过滤音频文件"
select_dir_prompt = "选择语音库目录以浏览语音文件"
save_patient_warning = "点击保存到CSV文件!保存操作将花费一些时间来完成!请耐心等待!"
close_table_prompt = "如果您想识别下一批文件,请先关闭窗口!在未来,客户端可能支持多线程以提高用户体验"
save_to_csv_prompt = "将结果保存到CSV文件"
emotion_field = "情感"
proba_field = "概率"
show_confusion_matrix = "显示混淆矩阵"
welcome = "欢迎"
main_page = "主页"
analyzer = "分析器"
settings = "设置"
about = "关于"
OK = "确定"
clear_history = "清除历史记录"
set_theme = "设置主题"
theme_prompt = "通过在此处选择不同的主题来查看元素在不同主题下的外观!"
train_score = "训练集得分"
test_score = "测试集得分"
start_train = "开始训练"
pca_components_tooltip = """
PCA组件
要保留的组件数。如果未设置n_components,则保留所有组件:
n_components == min(n_samples, n_features)
如果n_components == 'mle'且svd_solver =='full',则使用Minka的MLE猜测维数。使用n_components =='mle'将解释为svd_solver =='auto',即svd_solver =='full'。
如果0 < n_components < 1且svd_solver =='full',则选择组件数,使需要解释的方差量大于n_components指定的百分比。
如果svd_solver =='arpack',则组件数必须严格小于n_features和n_samples的最小值。
因此,None情况的结果为:
n_components == min(n_samples, n_features) - 1
"""
pca_svd_solver_tooltip = """
如果自动:
根据X.shape和n_components选择默认策略选择求解器:
如果输入数据大于500x500并且提取的组件数小于数据的最小维度的80%,
则启用更有效的“随机”方法。否则,计算精确的全SVD,然后可选择截断。
如果完整:
通过scipy运行准确的完整SVD。linalg.svd并通过后处理选择组件
如果arpack:
通过scipy.sparse.linalg.svds调用截断为n_components的SVD ARPACK求解器。它需要 0 < n_components < min(X.shape)
如果随机:
通过Halko等人的方法运行随机SVD。
"""
file_browse = "浏览单个文件"
fold_field = "k-折"
accu_score_field = "准确度"
application_menu = "&应用程序"
exit_menu = "退出(&x)"
help_menu = "帮助"
introduction_menu = "介绍"
predict_proba_legend = "预测概率"
current_model_prompt = "当前模型:"
no_result_yet = "暂无结果"
language_switch="确认切换"
\ No newline at end of file
......@@ -37,8 +37,10 @@ ravdess_files_glob_old = "data/ravdess/Actor_*"
ravdess_files_glob="data/ravdess/Actor_*/*.wav"
savee_files_glob = "data/savee/AudioData/*/*.wav"
translations_dir=project_dir/"SG/translations"
trans_zh=translations_dir/"zh.json"
trans_en=translations_dir/"en.json"
trans_zh_json=translations_dir/"zh.json"
trans_en_json=translations_dir/"en.json"
trans_zh=translations_dir/"zh.py"
trans_en=translations_dir/"en.py"
# print(trans_en.exists())
#计算绝对路径
......
---
marp: true
# header: 'Header content'
footer: '跨库SER系统的设计与实现'
theme: gaia
class: lead
---
# 跨库语音情感识别系统的设计与实现
![bg contain left:45% 98% 在这里插入图片描述](https://img-blog.csdnimg.cn/be61e759517a4f038c3eb69928e097aa.png)
计科1902 徐超信
指导老师:蒋海华
---
<!-- paginate: true -->
## 内容目录
- 背景和意义
- 开发路径
- 实现方案
- 基础情况
---
## 背景&意义
- 语音是人与人之间最重要、便捷的交流方式,不仅包含人类所要传达的语义信息,还包含人们所要表达情感信息,语言种类等各个方面。在20世纪中期,人机交互系统一直停带于语义文本这一类文字信息的理解和表达上,因此,当时所构建的人机交互系统往往只有用户表达出中性语音时才能够有效地识别出用户意图,而对于自然状态下的情感语音理解极为不佳。
- 可见,制约着人机交互系统发展的重要因素之一在于情感智能的缺失。在此背景下,越来越多的研究者们开始着手于对情感信息的探索。语音情感识别在智能车载系统,情感机器人,医疗,服务业等领域都发挥着重要作用。
---
## 开发路径
<!-- _theme:uncover -->
![bg contain right:80% 95% 在这里插入图片描述](https://img-blog.csdnimg.cn/b0fca5b946ea4e20acc513c1ed304c50.png)
---
## 实现方案
---
### 语料库的选用
- EMO-DB : 该数据集是由 10 名演员(分别从5个男性和5个女性说话人的表演语音中获得)模拟 7 种情绪产生的 10 个德语语句, 7 种情绪分别是:中性、愤怒、恐惧、喜悦、悲伤、厌恶和厌倦, 数据库共536 个样本, 该数据库已经成为许多研究的基础。
- SAVEE: 该数据集是一个使用英国英语的多模态情感数据集。 它总共包含了 480 条语音以及 7 种不同的情感: 中性、快乐、悲伤、愤怒、惊讶、恐惧和厌恶。 这些话语由 4 个专业的男性演员产生。 为了保持情感表演的良好质量, 本数据集的所有录音均由 10 位不同的评价者在音频、视觉和视听条件下进行验证这些录音中的脚本选自常规 TIMIT 语料库。
---
- RAVDESS: 该数据集是情感语音和歌曲的多模态语料。 该数据集是性别均衡的, 由 24 名专门演员组成, 他们以中性的北美(英语)发音产生语音和歌曲样本。 对于情感性言语, 它由平静、欢乐、悲伤、愤怒、恐惧、惊讶、厌恶构成。 对于情感性的歌曲, 它由平静、欢乐、悲伤、愤怒、恐惧、惊讶、厌恶和恐惧组成。 每个表情都是在情感强度的两个层次上产生的, 带有一个附加的中性表情。 最后收集的 7 356 份录音在情感有效性、强度和真实性方面分别被评为 10 次。 对于这些收视率, 雇佣了来自北美的 247 名未经培训的研究对象。
---
- 拟选用的上述数据库既可以完成多模态的同语言不同库的跨库识别(SAVEE和RAVDESA)实验,也可以完成跨语言跨库的识别实验(EMO-DB和SAVEE或EMO-DB和RAVDESS)。其中RAVDESS虽然是单模态的语料库库,但是由于其广泛的被采用,可以用来检验SER的基本识别性能,以及和已有的实验进行对比
---
### 语音特征的提取
-
---
### 分类模型的构建
<!-- class: default -->
![ Schematic diagram of automatic encoder; ](https://img-blog.csdnimg.cn/457d8e29cd074d6a90126238ce5fd73e.png)
本系统拟采用栈式堆叠稀疏自编码器与核函数极限学习机结合的复合网络模型(SSAE-KELM)作为识别模型。
Stack Sparse Automatic Encoders - Kernel Extreme Learning Machine
<!-- class: lead -->
复合网络SSAE-KELM 的结构图解
![bg contain right:70% ](https://img-blog.csdnimg.cn/63f31dd95c74414dbde9804b71b73811.png)
---
![image-20230112193055545](D:\repos\blogs\graduationDesign\assets\image-20230112193055545.png)
识别的流程
![ 在这里插入图片描述](https://img-blog.csdnimg.cn/17fd1086b50043b2aaab511b6a675151.png)
---
基于复合网络 SSAE-KELM 语音情感识别的详细步骤如下:
1) 多层稀疏自编码器堆叠构成栈式稀疏自编码网络,初始化 SSAE 网络参数;
2) 选择情感语音库,按照大致 2:1 的比例将其分为训练集与测试集,并提取语音情感全局特征 GF;
3) 从上到下无监督逐层贪婪训练每一层 SAE,实现局部最优;
4) 结合标签通过 BP 算法微调整体网络参数,达到全局最优;
5) 提取经过SSAE 无监督预训练有监督微调后的深度特征用于训练KELM 分类器,得到相应的KELM 参数;
6) 保存训练好的网络参数,利用测试集对语音情感识别性能进行测试。
---
### 小结
- 本系统采用一种复合网络栈式稀疏自编码网络——核函数极限学习机,首先通过栈式稀疏自编码网络对原始特征进行无监督预训练。
- 然后结合数据标签利用反向传播算法有监督微调,重构得到更符合大脑稀疏性且更具有区分情感信息的深度特征。
- 最后采用人工蜂群优化算法优化的核函数极限学习机对情感进行识别分类。
---
### 语音情感识别系统的开发:
- 本系统将在windows上开发,采用python语言和PyQT技术进行图形界面的开发。深度学习框架使用pytorch。
- 系统功能:可视化地展示模型的训练过程和语音情感的识别过程。拟实现一个抑郁症患者情绪跟踪管理系统,比如日常性对病人发送问题,根据患者的回答进行情感分析,辅助医生分析患者病情走势
---
各部分间的关系
![ 在这里插入图片描述](https://img-blog.csdnimg.cn/10f77de059604bd8be125e1dd3c39d55.png)
## 系统开发
![image-20230510185320088](D:\repos\CCSER\SER\assets\image-20230510185320088.png)
## 总结
-
......@@ -23,7 +23,17 @@
- **<u>input version under this line:</u>**
- new notes:"Sort update records in descending order of time".That would be convenient to update new version notes in the future.
-
- *<u>current modifing:</u>*
- ...
- 2023-05-10@20:06:02
- initially support the interface language switch:between Chinese and English
- the approch to achieve the multilanguage support depending on language string resource py file:
- `zh.py` for Chinese
- `en.py` for english
- for convenience,these module was managed by the `multilanguage.py`module.
- unfortunately,these features was test in `fviewer.py`,the main gui was still unable to work normally because the `windows.close` caused the program broken!
- improve the regex_filter performance by using `re.compile` instead `re.<function>`
- 2023-05-09@19:10:05
- fix some bugs.
- certain adjustments to the project code.
......
var=100
def check_var():
print(var,"@{var}",__file__)
\ No newline at end of file
import m1
m1.var=1
m1.check_var()
# print(m1.var,"@{m1.var}")
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册