Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| from google import genai | |
| from google.genai import types | |
| from PIL import Image | |
| import io | |
| import base64 | |
| # 載入環境變數(本機開發時需要) | |
| try: | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| except ImportError: | |
| pass | |
| # 配置Google AI | |
| def configure_google_ai(): | |
| """配置Google AI API""" | |
| api_key = os.getenv("GOOGLE_API_KEY") | |
| if not api_key: | |
| raise ValueError("請設定GOOGLE_API_KEY環境變數") | |
| # 使用新的 Gen AI 客戶端 | |
| client = genai.Client(api_key=api_key) | |
| return client | |
| # 初始化模型 | |
| try: | |
| client = configure_google_ai() | |
| model_name = "gemini-1.5-flash" | |
| except Exception as e: | |
| print(f"警告:無法初始化Google AI模型 - {e}") | |
| client = None | |
| def analyze_food_calories(image): | |
| """ | |
| 分析圖片中的食物並估算卡路里 | |
| Args: | |
| image: PIL Image 物件 | |
| Returns: | |
| str: 分析結果 | |
| """ | |
| if client is None: | |
| return "錯誤:Google AI模型未正確初始化,請檢查API KEY設定" | |
| try: | |
| # 將圖片轉換為 base64 | |
| img_byte_arr = io.BytesIO() | |
| image.save(img_byte_arr, format='PNG') | |
| img_byte_arr = img_byte_arr.getvalue() | |
| img_base64 = base64.b64encode(img_byte_arr).decode('utf-8') | |
| # 準備提示詞 | |
| prompt = """ | |
| 請分析這張圖片中的內容: | |
| 1. 首先判斷圖片中是否包含食物 | |
| 2. 如果不是食物,請回答:「這個不是食物」 | |
| 3. 如果是食物,請: | |
| - 識別食物種類 | |
| - 估算大概的份量 | |
| - 計算大概的卡路里含量 | |
| - 以繁體中文回答 | |
| 請以以下格式回答: | |
| - 食物名稱:[食物名稱] | |
| - 估算份量:[份量描述] | |
| - 預估卡路里:[卡路里數值] 大卡 | |
| - 營養說明:[簡短的營養價值說明] | |
| 如果不是食物,就直接回答「這個不是食物」。 | |
| """ | |
| # 建立內容,包含文字和圖片 | |
| contents = [ | |
| types.Content( | |
| role="user", | |
| parts=[ | |
| types.Part.from_text(text=prompt), | |
| types.Part.from_bytes( | |
| data=img_byte_arr, | |
| mime_type="image/png" | |
| ) | |
| ] | |
| ) | |
| ] | |
| # 生成回應 | |
| response = client.models.generate_content( | |
| model=model_name, | |
| contents=contents, | |
| config=types.GenerateContentConfig( | |
| temperature=0.4, | |
| max_output_tokens=1024, | |
| ) | |
| ) | |
| if response.text: | |
| return response.text | |
| else: | |
| return "無法生成回應" | |
| except Exception as e: | |
| return f"分析時發生錯誤:{str(e)}" | |
| def process_image(image): | |
| """ | |
| 處理上傳的圖片 | |
| Args: | |
| image: Gradio上傳的圖片 | |
| Returns: | |
| str: 分析結果 | |
| """ | |
| if image is None: | |
| return "請上傳一張圖片" | |
| try: | |
| # 確保圖片是PIL Image格式 | |
| if isinstance(image, str): | |
| # 如果是路徑字串,載入圖片 | |
| pil_image = Image.open(image) | |
| else: | |
| pil_image = image | |
| # 分析圖片 | |
| result = analyze_food_calories(pil_image) | |
| return result | |
| except Exception as e: | |
| return f"處理圖片時發生錯誤:{str(e)}" | |
| # 建立Gradio介面 | |
| def create_interface(): | |
| """建立Gradio使用者介面""" | |
| # 自訂CSS樣式 | |
| css = """ | |
| .gradio-container { | |
| font-family: 'Microsoft JhengHei', sans-serif; | |
| } | |
| .title { | |
| text-align: center; | |
| color: #2E7D32; | |
| margin-bottom: 20px; | |
| } | |
| .description { | |
| text-align: center; | |
| color: #666; | |
| margin-bottom: 30px; | |
| } | |
| """ | |
| with gr.Blocks(css=css, title="食物卡路里檢測器") as demo: | |
| gr.HTML("<h1 class='title'>🍎 食物卡路里檢測器</h1>") | |
| gr.HTML("<p class='description'>上傳食物照片,AI會幫你識別食物種類並估算卡路里含量</p>") | |
| with gr.Row(): | |
| with gr.Column(): | |
| # 圖片上傳元件 | |
| image_input = gr.Image( | |
| label="上傳食物照片", | |
| type="pil", | |
| height=400 | |
| ) | |
| # 分析按鈕 | |
| analyze_btn = gr.Button( | |
| "🔍 分析卡路里", | |
| variant="primary", | |
| size="lg" | |
| ) | |
| with gr.Column(): | |
| # 結果顯示 | |
| result_output = gr.Textbox( | |
| label="分析結果", | |
| lines=10, | |
| placeholder="上傳圖片後點擊分析按鈕...", | |
| interactive=False | |
| ) | |
| # 使用說明 | |
| gr.HTML(""" | |
| <div style="margin-top: 30px; padding: 20px; background-color: #f5f5f5; border-radius: 10px;"> | |
| <h3>📋 使用說明:</h3> | |
| <ul> | |
| <li>📸 上傳一張包含食物的清晰照片</li> | |
| <li>🤖 AI會自動識別食物種類</li> | |
| <li>📊 獲得卡路里估算和營養資訊</li> | |
| <li>⚠️ 如果不是食物,系統會提醒您</li> | |
| </ul> | |
| <p><strong>注意:</strong>卡路里估算僅供參考,實際數值可能因烹飪方式和份量而有所差異。</p> | |
| </div> | |
| """) | |
| # 設定事件處理 | |
| analyze_btn.click( | |
| fn=process_image, | |
| inputs=[image_input], | |
| outputs=[result_output] | |
| ) | |
| # 也可以在上傳圖片後自動分析 | |
| image_input.change( | |
| fn=process_image, | |
| inputs=[image_input], | |
| outputs=[result_output] | |
| ) | |
| return demo | |
| # 主程式 | |
| if __name__ == "__main__": | |
| # 建立介面 | |
| demo = create_interface() | |
| # 啟動應用 | |
| # HuggingFace Spaces 使用預設設定 | |
| demo.launch() |