PhilipL commited on
Commit
8c9b916
·
verified ·
1 Parent(s): 39f503c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -25
app.py CHANGED
@@ -20,7 +20,7 @@ from deepface import DeepFace
20
  warnings.filterwarnings("ignore")
21
 
22
  # ==========================================
23
- # 0. 環境變數與 RAG 初始化
24
  # ==========================================
25
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
26
  HF_TOKEN = os.getenv("HF_TOKEN")
@@ -86,7 +86,7 @@ if not df.empty and 'RAG_Content' in df.columns:
86
  print(f"⚠️ RAG 初始化失敗: {e}")
87
 
88
  # ==========================================
89
- # 1. 核心功能函式 (餐廳推薦邏輯)
90
  # ==========================================
91
 
92
  def get_restaurant_data(mood_score_str, food_choice):
@@ -208,7 +208,7 @@ def mood_agent_logic(score_input, food_input, diary_input, debug_mode):
208
  yield final_response, image_output, map_html
209
 
210
  # ==========================================
211
- # 2. 情緒辨識整合模組 (維持不變)
212
  # ==========================================
213
 
214
  # 定義中文字典 (繪圖用)
@@ -231,10 +231,23 @@ def putText(img, x, y, text, size=50, color=(255, 255, 255)):
231
  except:
232
  return img
233
 
234
- # 關鍵功能:偵測情緒並回傳「分數選項」 (維持不變)
235
- def detect_emotion_and_map(frame):
236
- if frame is None:
237
- return frame, None
 
 
 
 
 
 
 
 
 
 
 
 
 
238
 
239
  detected_emotion = "neutral"
240
  mapped_score = "3 (普通)"
@@ -248,7 +261,7 @@ def detect_emotion_and_map(frame):
248
  # 2. 畫在圖片上
249
  frame = putText(frame, 20, 40, detected_emotion)
250
 
251
- # 3. 橋樑:將情緒轉換為餐廳系統的分數
252
  if detected_emotion == 'happy':
253
  mapped_score = "5 (超棒)"
254
  elif detected_emotion == 'surprise':
@@ -261,17 +274,19 @@ def detect_emotion_and_map(frame):
261
  mapped_score = "1 (心情差)"
262
 
263
  except Exception as e:
264
- print(f"DeepFace Error: {e}")
265
  pass
266
 
267
  return frame, mapped_score
268
 
269
  # ==========================================
270
- # 5. Gradio 介面建構 (修改版:鏡頭與結果分離)
271
  # ==========================================
272
 
273
  with gr.Blocks(title="AI 心情食堂") as demo:
274
 
 
 
 
275
  with gr.Column(visible=True) as main_app_col:
276
  gr.Markdown(f"## 🍱 AI 心情食堂導航")
277
  gr.Markdown("請看著鏡頭,讓 AI 幫你判斷今天的心情分數!")
@@ -280,23 +295,20 @@ with gr.Blocks(title="AI 心情食堂") as demo:
280
  # 左側:輸入區
281
  with gr.Column(scale=1):
282
 
283
- # ★ 修改重點:將鏡頭與結果分開顯示 ★
284
  gr.Markdown("### 📸 步驟 1:心情偵測 (選用)")
285
-
286
- # 這裡用 Row 把兩個影像並排 (左邊鏡頭,右邊截圖)
287
  with gr.Row():
288
- # 左邊:永遠是即時鏡頭 (不設為 output)
289
- webcam_input = gr.Image(sources=["webcam"], label="即時鏡頭 (請看這裡)", streaming=True)
290
-
291
- # 右邊:顯示偵測後的「靜態截圖」
292
- captured_image = gr.Image(label="偵測結果截圖", interactive=False)
293
 
294
- detect_btn = gr.Button("📸 截圖並偵測心情 👇", variant="secondary")
 
295
 
296
  gr.Markdown("### 📝 步驟 2:確認與補充")
297
  score_input = gr.Radio(
298
  ["1 (心情差)", "2 (不太好)", "3 (普通)", "4 (不錯)", "5 (超棒)"],
299
- label="1. 心情分數 (AI 會自動填入,也可手動改)",
300
  value="3 (普通)"
301
  )
302
  food_input = gr.Radio(["吃飯", "吃麵", "隨便"], label="2. 想吃什麼", value="隨便")
@@ -305,7 +317,7 @@ with gr.Blocks(title="AI 心情食堂") as demo:
305
  debug_mode_btn = gr.Checkbox(label="🔧 顯示 Prompt 除錯資訊", value=False)
306
  submit_btn = gr.Button("🚀 送出給 Agent", variant="primary")
307
 
308
- # 右側:Agent 輸出區 (維持不變)
309
  with gr.Column(scale=1):
310
  agent_output = gr.Markdown(label="AI 回應")
311
  image_output = gr.Image(label="AI 推薦美食圖", type="pil", width=400)
@@ -313,11 +325,19 @@ with gr.Blocks(title="AI 心情食堂") as demo:
313
 
314
  # Events
315
 
316
- # ★ 修改重點:按鈕點擊後,輸出目標改為 captured_image,不再覆蓋 webcam_input
317
  detect_btn.click(
318
- fn=detect_emotion_and_map,
319
- inputs=[webcam_input],
320
- outputs=[captured_image, score_input] # 輸出到「右邊的截圖」和「分數選項」
 
 
 
 
 
 
 
 
321
  )
322
 
323
  # 提交按鈕
 
20
  warnings.filterwarnings("ignore")
21
 
22
  # ==========================================
23
+ # 環境變數與 RAG 初始化
24
  # ==========================================
25
  GROQ_API_KEY = os.getenv("GROQ_API_KEY")
26
  HF_TOKEN = os.getenv("HF_TOKEN")
 
86
  print(f"⚠️ RAG 初始化失敗: {e}")
87
 
88
  # ==========================================
89
+ # 核心功能函式 (餐廳推薦邏輯)
90
  # ==========================================
91
 
92
  def get_restaurant_data(mood_score_str, food_choice):
 
208
  yield final_response, image_output, map_html
209
 
210
  # ==========================================
211
+ # [修改] 情緒辨識整合模組
212
  # ==========================================
213
 
214
  # 定義中文字典 (繪圖用)
 
231
  except:
232
  return img
233
 
234
+ # ★ 新增:按鈕切換函式 (控制按鈕的文字與顏色)
235
+ def toggle_recording(is_recording):
236
+ # 切換狀態 (True <-> False)
237
+ new_state = not is_recording
238
+
239
+ if new_state:
240
+ # 如果變成錄製中,按鈕變成紅色「停止」
241
+ return new_state, gr.Button(value="🛑 停止錄製 (鎖定結果)", variant="stop")
242
+ else:
243
+ # 如果變成停止,按鈕變成綠色「開始」
244
+ return new_state, gr.Button(value="📸 開始即時偵測", variant="secondary")
245
+
246
+ # ★ 修改:偵測邏輯 (加入 is_recording 判斷)
247
+ def detect_emotion_stream(frame, is_recording):
248
+ # 如果沒有在錄製,或是沒有畫面,就什麼都不更新 (讓畫面凍結在最後一幀)
249
+ if not is_recording or frame is None:
250
+ return gr.update(), gr.update()
251
 
252
  detected_emotion = "neutral"
253
  mapped_score = "3 (普通)"
 
261
  # 2. 畫在圖片上
262
  frame = putText(frame, 20, 40, detected_emotion)
263
 
264
+ # 3. 分數轉換
265
  if detected_emotion == 'happy':
266
  mapped_score = "5 (超棒)"
267
  elif detected_emotion == 'surprise':
 
274
  mapped_score = "1 (心情差)"
275
 
276
  except Exception as e:
 
277
  pass
278
 
279
  return frame, mapped_score
280
 
281
  # ==========================================
282
+ # Gradio 介面建構 (修改版)
283
  # ==========================================
284
 
285
  with gr.Blocks(title="AI 心情食堂") as demo:
286
 
287
+ # ★ 1. 定義一個變數來記錄狀態 (預設是 False 停止中)
288
+ recording_state = gr.State(value=False)
289
+
290
  with gr.Column(visible=True) as main_app_col:
291
  gr.Markdown(f"## 🍱 AI 心情食堂導航")
292
  gr.Markdown("請看著鏡頭,讓 AI 幫你判斷今天的心情分數!")
 
295
  # 左側:輸入區
296
  with gr.Column(scale=1):
297
 
 
298
  gr.Markdown("### 📸 步驟 1:心情偵測 (選用)")
 
 
299
  with gr.Row():
300
+ # 左邊:即時鏡頭
301
+ webcam_input = gr.Image(sources=["webcam"], label="即時鏡頭", streaming=True)
302
+ # 右邊:結果畫面 (互動模式設為 False)
303
+ captured_image = gr.Image(label="即時偵測結果", interactive=False)
 
304
 
305
+ # 按鈕預設為「開始」
306
+ detect_btn = gr.Button("📸 開始即時偵測", variant="secondary")
307
 
308
  gr.Markdown("### 📝 步驟 2:確認與補充")
309
  score_input = gr.Radio(
310
  ["1 (心情差)", "2 (不太好)", "3 (普通)", "4 (不錯)", "5 (超棒)"],
311
+ label="1. 心情分數 (AI 自���填入)",
312
  value="3 (普通)"
313
  )
314
  food_input = gr.Radio(["吃飯", "吃麵", "隨便"], label="2. 想吃什麼", value="隨便")
 
317
  debug_mode_btn = gr.Checkbox(label="🔧 顯示 Prompt 除錯資訊", value=False)
318
  submit_btn = gr.Button("🚀 送出給 Agent", variant="primary")
319
 
320
+ # 右側:Agent 輸出區
321
  with gr.Column(scale=1):
322
  agent_output = gr.Markdown(label="AI 回應")
323
  image_output = gr.Image(label="AI 推薦美食圖", type="pil", width=400)
 
325
 
326
  # Events
327
 
328
+ # ★ 事件 1:按鈕點擊 -> 切換錄製狀態 -> 更新按鈕樣子
329
  detect_btn.click(
330
+ fn=toggle_recording,
331
+ inputs=[recording_state],
332
+ outputs=[recording_state, detect_btn]
333
+ )
334
+
335
+ # ★ 事件 2:鏡頭串流 (Stream) -> 只要鏡頭有畫面就會觸發
336
+ # 它會檢查 recording_state,如果是 True 才會更新右邊的圖
337
+ webcam_input.stream(
338
+ fn=detect_emotion_stream,
339
+ inputs=[webcam_input, recording_state],
340
+ outputs=[captured_image, score_input]
341
  )
342
 
343
  # 提交按鈕