Spaces:
Configuration error
Configuration error
Update app.py
Browse files
app.py
CHANGED
@@ -1,89 +1,74 @@
|
|
1 |
# app.py
|
|
|
2 |
import gradio as gr
|
3 |
import numpy as np
|
4 |
-
import
|
5 |
-
import librosa
|
6 |
from deepface import DeepFace
|
7 |
|
8 |
-
# —— 1.
|
9 |
-
#
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
输出:DeepFace 分析出的 dominant_emotion(字符串)
|
17 |
-
"""
|
18 |
-
# DeepFace.analyze 接受 RGB np.array
|
19 |
-
res = DeepFace.analyze(
|
20 |
-
img_path=frame,
|
21 |
-
actions=['emotion'],
|
22 |
enforce_detection=False
|
23 |
)
|
24 |
-
#
|
25 |
-
|
26 |
-
emo = res[0].get('dominant_emotion', 'unknown')
|
27 |
-
else:
|
28 |
-
emo = res.get('dominant_emotion', 'unknown')
|
29 |
-
return emo
|
30 |
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
"""
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
|
39 |
mf = np.mean(mfccs.T, axis=0)
|
40 |
return audio_model.predict([mf])[0]
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
if any(w in text for w in ["怕","恐懼","緊張","懼","膽怯","畏"]): return "fear"
|
51 |
-
return "neutral"
|
52 |
|
53 |
-
|
|
|
54 |
gr.Markdown("## 📱 多模態即時情緒分析")
|
55 |
-
|
56 |
tabs = gr.Tabs()
|
57 |
-
with tabs:
|
58 |
-
with gr.TabItem("🔴 Face(即時)"):
|
59 |
-
gr.Markdown("⚠️ Spaces 無法直接打開攝像頭,請本機 `python app.py` 測試;手機/電腦瀏覽器可用以下方式:")
|
60 |
-
camera = gr.Image(
|
61 |
-
source="webcam",
|
62 |
-
type="numpy",
|
63 |
-
label="請對準鏡頭"
|
64 |
-
)
|
65 |
-
face_out = gr.Textbox(label="偵測結果")
|
66 |
-
camera.change(fn=analyze_face, inputs=camera, outputs=face_out)
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
)
|
73 |
-
audio_out = gr.Textbox(label="偵測結果")
|
74 |
-
wav.upload(fn=analyze_audio, inputs=wav, outputs=audio_out)
|
75 |
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
)
|
81 |
-
text_btn = gr.Button("開始分析")
|
82 |
-
text_out = gr.Textbox(label="偵測結果")
|
83 |
-
text_btn.click(fn=analyze_text, inputs=txt, outputs=text_out)
|
84 |
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# app.py
|
2 |
+
|
3 |
import gradio as gr
|
4 |
import numpy as np
|
5 |
+
import base64, io, os
|
6 |
+
import librosa, joblib
|
7 |
from deepface import DeepFace
|
8 |
|
9 |
+
# —— 1. 预加载 DeepFace、语音模型 ——
|
10 |
+
# DeepFace 会自动把权重缓存到 DEEPFACE_HOME 下的 /weights
|
11 |
+
os.environ["DEEPFACE_HOME"] = "/tmp/.deepface"
|
12 |
+
def load_models():
|
13 |
+
# a) 热身 DeepFace
|
14 |
+
DeepFace.analyze(
|
15 |
+
img_path = np.zeros((224,224,3), dtype=np.uint8),
|
16 |
+
actions = ['emotion'],
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
enforce_detection=False
|
18 |
)
|
19 |
+
# b) 加载本地训练好的语音模型
|
20 |
+
return joblib.load("src/voice_model.joblib")
|
|
|
|
|
|
|
|
|
21 |
|
22 |
+
audio_model = load_models()
|
23 |
+
|
24 |
+
# —— 2. 文本情绪函数 ——
|
25 |
+
def analyze_text_fn(text):
|
26 |
+
if any(w in text for w in ["開心","快樂","愉快","喜悅","歡喜","興奮","歡","高興"]): return "😊 happy"
|
27 |
+
if any(w in text for w in ["生氣","憤怒","不爽","發火","火大","氣憤"]): return "😠 angry"
|
28 |
+
if any(w in text for w in ["傷心","難過","哭","難受","心酸","憂","悲","哀","痛苦","慘","愁"]): return "😢 sad"
|
29 |
+
if any(w in text for w in ["驚訝","意外","嚇","驚詫","詫異","訝異","好奇"]): return "😲 surprise"
|
30 |
+
if any(w in text for w in ["怕","恐懼","緊張","懼","膽怯","畏"]): return "😨 fear"
|
31 |
+
return "😐 neutral"
|
32 |
+
|
33 |
+
# —— 3. 语音情绪函数 ——
|
34 |
+
def analyze_audio_fn(wav_bytes):
|
35 |
+
y, sr = librosa.load(io.BytesIO(wav_bytes), sr=None)
|
36 |
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
|
37 |
mf = np.mean(mfccs.T, axis=0)
|
38 |
return audio_model.predict([mf])[0]
|
39 |
|
40 |
+
# —— 4. 人脸情绪函数 ——
|
41 |
+
def analyze_face_fn(img: np.ndarray):
|
42 |
+
res = DeepFace.analyze(
|
43 |
+
img, actions=['emotion'], enforce_detection=False
|
44 |
+
)
|
45 |
+
# 兼容 list/dict 返回
|
46 |
+
emo = res[0]['dominant_emotion'] if isinstance(res, list) else res['dominant_emotion']
|
47 |
+
return emo
|
|
|
|
|
48 |
|
49 |
+
# —— 5. 用 Gradio Blocks 组织界面 ——
|
50 |
+
with gr.Blocks() as demo:
|
51 |
gr.Markdown("## 📱 多模態即時情緒分析")
|
|
|
52 |
tabs = gr.Tabs()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
+
with tabs.add_tab("🔴 Face(Browser→Webcam)"):
|
55 |
+
camera = gr.Image(source="webcam", tool="editor", label="對準你的臉")
|
56 |
+
out_face = gr.Textbox(label="偵測到的情緒")
|
57 |
+
camera.change(analyze_face_fn, camera, out_face)
|
|
|
|
|
|
|
58 |
|
59 |
+
with tabs.add_tab("🎤 上傳 WAV 檔"):
|
60 |
+
wav = gr.File(label="上傳 .wav")
|
61 |
+
out_audio = gr.Textbox(label="語音檢測情緒")
|
62 |
+
wav.upload(analyze_audio_fn, wav, out_audio)
|
|
|
|
|
|
|
|
|
63 |
|
64 |
+
with tabs.add_tab("⌨️ 輸入文字"):
|
65 |
+
txt = gr.Textbox(label="在此輸入文字")
|
66 |
+
btn = gr.Button("開始分析")
|
67 |
+
out_text = gr.Textbox(label="文字檢測情緒")
|
68 |
+
btn.click(analyze_text_fn, txt, out_text)
|
69 |
+
|
70 |
+
gr.Markdown("---")
|
71 |
+
gr.Markdown("ℹ️ 內建 DeepFace、librosa & sklearn 進行多模態情緒分析")
|
72 |
+
|
73 |
+
if __name__ == "__main__":
|
74 |
+
demo.launch()
|