File size: 3,227 Bytes
357796f
 
 
a2a4ab6
 
357796f
 
a2a4ab6
 
 
 
 
 
357796f
a2a4ab6
 
357796f
a2a4ab6
357796f
a2a4ab6
357796f
 
 
a2a4ab6
357796f
 
 
 
 
 
a2a4ab6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357796f
a2a4ab6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# app.py
import gradio as gr
import numpy as np
import joblib, io
import librosa
from deepface import DeepFace

# —— 1. 预加载模型 —— 
# DeepFace 热身 + 载入语音模型
audio_model = joblib.load("src/voice_model.joblib")
# 你也可以包一层 try/except

def analyze_face(frame: np.ndarray):
    """
    输入:摄像头采到的 RGB numpy 数组
    输出:DeepFace 分析出的 dominant_emotion(字符串)
    """
    # DeepFace.analyze 接受 RGB np.array
    res = DeepFace.analyze(
        img_path=frame,
        actions=['emotion'],
        enforce_detection=False
    )
    # 兼容 dict / list 返回
    if isinstance(res, list):
        emo = res[0].get('dominant_emotion', 'unknown')
    else:
        emo = res.get('dominant_emotion', 'unknown')
    return emo

def analyze_audio(wav_file):
    """
    输入:上传的 wav(二进制)
    输出:语音情绪分类标签
    """
    data = wav_file.read()
    y, sr = librosa.load(io.BytesIO(data), sr=None)
    mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
    mf = np.mean(mfccs.T, axis=0)
    return audio_model.predict([mf])[0]

def analyze_text(txt):
    """
    简单的基于关键词的中文情绪分析
    """
    if any(w in text for w in ["開心","快樂","愉快","喜悅","歡喜","興奮","歡","高興"]): return "happy"
    if any(w in text for w in ["生氣","憤怒","不爽","發火","火大","氣憤"]): return "angry"
    if any(w in text for w in ["傷心","難過","哭","難受","心酸","憂","悲","哀","痛苦","慘","愁"]): return "sad"
    if any(w in text for w in ["驚訝","意外","嚇","驚詫","詫異","訝異","好奇"]):       return "surprise"
    if any(w in text for w in ["怕","恐懼","緊張","懼","膽怯","畏"]):       return "fear"
    return "neutral"

with gr.Blocks(title="多模態即時情緒分析") as demo:
    gr.Markdown("## 📱 多模態即時情緒分析")

    tabs = gr.Tabs()
    with tabs:
        with gr.TabItem("🔴 Face(即時)"):
            gr.Markdown("⚠️ Spaces 無法直接打開攝像頭,請本機 `python app.py` 測試;手機/電腦瀏覽器可用以下方式:")
            camera = gr.Image(
                source="webcam",
                type="numpy",
                label="請對準鏡頭"
            )
            face_out = gr.Textbox(label="偵測結果")
            camera.change(fn=analyze_face, inputs=camera, outputs=face_out)

        with gr.TabItem("🎤 上傳語音"):
            wav = gr.File(
                label="請選擇 .wav 音檔",
                file_types=["wav"]
            )
            audio_out = gr.Textbox(label="偵測結果")
            wav.upload(fn=analyze_audio, inputs=wav, outputs=audio_out)

        with gr.TabItem("⌨️ 文本輸入"):
            txt = gr.Textbox(
                label="在此輸入文字",
                placeholder="輸入想要分析的句子…"
            )
            text_btn = gr.Button("開始分析")
            text_out = gr.Textbox(label="偵測結果")
            text_btn.click(fn=analyze_text, inputs=txt, outputs=text_out)

    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        share=False
    )