Spaces:
Running
on
A10G
Running
on
A10G
import gradio as gr | |
from evaluate import eval | |
from datetime import datetime | |
import os, shutil | |
import warnings | |
from audio import gen_audio | |
warnings.filterwarnings("ignore") | |
warnings.simplefilter("ignore") | |
videos = { | |
"教學視頻1": "teach/00.mp4", | |
"教學視頻2": "teach/01.mp4", | |
"教學視頻3": "teach/02.mp4", | |
"教學視頻4": "teach/03.mp4", | |
"(病症)高峰期": "teach/(病症)高峰期.mp4", | |
"公園": "teach/公園.mp4", | |
"健康": "teach/健康.mp4", | |
"刷牙": "teach/刷牙.mp4", | |
"圖書館": "teach/圖書館.mp4", | |
"下午": "teach/下午.mp4", | |
"中風": "teach/中風.mp4", | |
"中暑": "teach/中暑.mp4", | |
"主題": "teach/主題.mp4", | |
"住院證明": "teach/住院證明.mp4" | |
} | |
jsons = { | |
"教學視頻1": "teach/00.json", | |
"教學視頻2": "teach/01.json", | |
"教學視頻3": "teach/02.json", | |
"教學視頻4": "teach/03.json", | |
"(病症)高峰期": "teach/(病症)高峰期.json", | |
"公園": "teach/公園.json", | |
"健康": "teach/健康.json", | |
"刷牙": "teach/刷牙.json", | |
"圖書館": "teach/圖書館.json", | |
"下午": "teach/下午.json", | |
"中風": "teach/中風.json", | |
"中暑": "teach/中暑.json", | |
"主題": "teach/主題.json", | |
"住院證明": "teach/住院證明.json" | |
} | |
def get_video_url(option): | |
return videos[option] | |
def evaluate_sign_language(user_video, standard_video_option): | |
tmpdir = tempfile.TemporaryDirectory() | |
new_path = tmpdir + "/user.mp4" | |
# 将文件从临时路径复制到新路径 | |
shutil.copy(user_video, new_path) | |
shutil.copy(videos[standard_video_option], tmpdir + "/standard.mp4") | |
shutil.copy(jsons[standard_video_option], tmpdir + "/standard.json") #comment if produce standard json files | |
###### | |
test, standard = user_video, videos[standard_video_option] | |
score, final_merged_intervals, comments = eval(test, standard, tmpdir) | |
# return None # comment if NOT produce standard json files | |
if score < 95: | |
score = 0 | |
elif score < 98: | |
score = 50 * (score - 95) / 3 # 将95到98之间的数映射到0到50 | |
elif 98 <= score <= 100: | |
score = 50 * (score - 98) / 2 + 50 | |
# 获取当前日期 | |
current_date = datetime.now().strftime("%Y年%m月%d日") | |
# 初始化反馈报告 | |
qualification = "不合格" if score < 60 else "合格" | |
advice = f"""<div style='font-family: "Heiti SC"; text-align: center; font-size: 24px;'><b>\n手語表現反饋報告</b></div> | |
<br><br><br><b>日期:</b> {current_date}<br><b>整體評估:</b> {qualification}。在您的手語練習中,我們註意到一些動作可以改進以提升流暢性,感謝您的努力,繼續加油。<br><br><b>改進建議(供參考):</b><br>""" | |
part_translation = { | |
'Right Hand': '右手細節、', | |
'Left Hand': '左手細節、', | |
'Right Arm': '右臂、', | |
'Left Arm': '左臂、' | |
} | |
# 为每个问题区间生成具体观察结果 | |
f = 0 | |
subtitles = [] | |
for interval, errors in final_merged_intervals: | |
advice += f"<b> - 時間區間:{interval[0]}-{interval[1]}秒</b><br>" | |
parts = "" | |
for error in errors: | |
part = part_translation[error] | |
parts += part | |
advice += f" 觀察結果:您的{parts[:-1]}動作與標準手語手勢不太一致。<br>" | |
f = 1 | |
subtitles.append([[interval[0], interval[1]], parts[:-1]]) | |
if not f: | |
advice = advice[:-4] | |
advice += "無" | |
advice += "<br>建議:請參考標準視頻,模仿正確的動作,保持速度一致。<br><br>" | |
advice += f"<b>綜合評分:</b> 您本次的總評分為 {score:.2f}/100分。<br>" | |
ret_video = gen_audio(subtitles, tmpdir) | |
return advice, ret_video | |
font = ["Heiti SC", "FangSong"] | |
title = """<h1 style="text-align: center;"> | |
<div style="width: 1.4em; height: 1.4em; display: inline-block;"><img src="https://github.com/ZiyuGuo99/ZiyuGuo99.github.io/blob/main/assets/img/sl.png?raw=true" style='width: 100%; height: 100%; object-fit: contain;' /></div> | |
<span style="font-family: """ + font[0] + """; font-variant: small-caps; font-weight: bold;">手語教學與評估系統</span> | |
</h1> | |
""" | |
with gr.Blocks( | |
css=""" | |
.contain { display: flex; flex-direction: column; } | |
.gradio-container { height: 200vh !important; | |
overflow-y: auto; /* 添加垂直滚动条 */ | |
} | |
#col_container { height: 100%; } | |
pre { | |
white-space: pre-wrap; /* Since CSS 2.1 */ | |
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ | |
white-space: -pre-wrap; /* Opera 4-6 */ | |
white-space: -o-pre-wrap; /* Opera 7 */ | |
word-wrap: break-word; /* Internet Explorer 5.5+ */ | |
}""", | |
js=""" | |
function refresh() { | |
const url = new URL(window.location); | |
if (url.searchParams.get('__theme') !== 'light') { | |
url.searchParams.set('__theme', 'light'); | |
window.location.href = url.href; | |
} | |
}""", | |
title="手語教學與評估系統", | |
theme=gr.themes.Soft(), | |
) as app: | |
gr.HTML(title) | |
with gr.Row(): | |
with gr.Column(): | |
video_selector = gr.Dropdown(list(videos.keys()), label="請選擇教學視頻") | |
video_player = gr.Video(label="請觀看教學視頻演示") | |
video_selector.change(get_video_url, inputs=video_selector, outputs=video_player) | |
with gr.Column(): | |
upload_video = gr.Video(label="請錄製/上傳您的視頻,點擊\'開始評估\'") | |
evaluate_button = gr.Button("開始評估") | |
with gr.Row(): | |
with gr.Column(): | |
advice_output = gr.HTML(label="反饋報告") | |
with gr.Column(): | |
compare_video_player = gr.Video(label="評估結果") | |
evaluate_button.click( | |
evaluate_sign_language, | |
inputs=[upload_video, video_selector], | |
outputs=[advice_output, compare_video_player] | |
) | |
app.launch(share=True) | |