Spaces:
Sleeping
Sleeping
Download app.py from mno2/lab3: direct link, hf CLI and curl.
- Browser
- Download file 7.89 kB
-
https://huggingface.co/spaces/mno2/lab3/resolve/main/app.py
- Command line
-
hf download hf://spaces/mno2/lab3/app.py
-
curl -L -o app.py https://huggingface.co/spaces/mno2/lab3/resolve/main/app.py
7.89 kB
| import gradio as gr | |
| from transformers import pipeline | |
| from PIL import Image | |
| import torch | |
| # ----------------------------------------------------------------- | |
| # 1. 載入模型 (這會在 App 啟動時執行一次) | |
| # (此部分與你的程式碼完全相同) | |
| # ----------------------------------------------------------------- | |
| print("正在載入模型...") | |
| # 模型 1: Image Captioning (圖片標註) | |
| captioner = pipeline( | |
| "image-to-text", | |
| model="Salesforce/blip-image-captioning-base") | |
| # 模型 2: Visual Question Answering (VQA) | |
| vqa = pipeline( | |
| "visual-question-answering", | |
| model="dandelin/vilt-b32-finetuned-vqa") | |
| print("模型載入完成!") | |
| # ----------------------------------------------------------------- | |
| # 2. 定義 AI 功能的函式 | |
| # (此部分與你的程式碼完全相同) | |
| # ----------------------------------------------------------------- | |
| def get_image_caption(pil_image): | |
| """ | |
| 接收一個 PIL 圖片,返回 AI 生成的文字描述。 | |
| """ | |
| if pil_image is None: | |
| return "錯誤:請先上傳一張圖片。" | |
| try: | |
| caption = captioner(pil_image) | |
| if caption and isinstance(caption, list) and 'generated_text' in caption[0]: | |
| return caption[0]['generated_text'].capitalize() # 讓首字母大寫 | |
| else: | |
| return "錯誤:模型返回了非預期的格式。" | |
| except Exception as e: | |
| return f"處理時發生錯誤: {e}" | |
| def answer_visual_question(pil_image, question_text): | |
| """ | |
| 接收一個 PIL 圖片和一個問題字串,返回 AI 的回答。 | |
| """ | |
| if pil_image is None: | |
| return "錯誤:請先上傳一張圖片。" | |
| if not question_text: | |
| return "錯誤:請輸入你的問題。" | |
| try: | |
| answer = vqa(image=pil_image, question=question_text) | |
| if answer and isinstance(answer, list) and 'answer' in answer[0]: | |
| return answer[0]['answer'].capitalize() # 讓首字母大寫 | |
| else: | |
| return "錯誤:模型返回了非預期的格式。" | |
| except Exception as e: | |
| return f"處理時發生錯誤: {e}" | |
| # ----------------------------------------------------------------- | |
| # 3. (全新設計) 建立 Gradio Web UI | |
| # ----------------------------------------------------------------- | |
| # (新增) 自訂 CSS 樣式 | |
| # 我們將使用這些 CSS 來打造卡片佈局和美化元件 | |
| my_custom_css = """ | |
| /* --- 1. 整體頁面背景 --- */ | |
| .gradio-container { | |
| background: linear-gradient(to right, #e0eafc, #cfdef3); /* 淡雅的漸層背景 */ | |
| padding: 20px; | |
| } | |
| /* --- 2. 美化主標題 --- */ | |
| #main-title { | |
| text-align: center; | |
| color: #2c3e50; | |
| font-size: 3em; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.1); | |
| margin-bottom: 20px; | |
| } | |
| /* --- 3. 卡片式佈局 (gr.Group) --- */ | |
| .gradio-group { | |
| background: rgba(255, 255, 255, 0.9); /* 半透明白色背景 */ | |
| border-radius: 20px; | |
| box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15); /* 更柔和的陰影 */ | |
| border: 1px solid rgba(255, 255, 255, 0.18); | |
| padding: 25px !important; | |
| margin-bottom: 20px !important; | |
| } | |
| /* --- 4. 美化功能標題 (h3) --- */ | |
| .gradio-group h3 { | |
| color: #34495e; | |
| font-size: 1.5em; | |
| border-bottom: 2px solid #4a90e2; /* 標題底線 */ | |
| padding-bottom: 5px; | |
| } | |
| /* --- 5. 美化主要按鈕 --- */ | |
| .gr-button-primary { | |
| background: linear-gradient(to right, #4a90e2, #50E3C2) !important; | |
| border: none !important; | |
| border-radius: 10px !important; | |
| font-size: 1.1em !important; | |
| color: white !important; | |
| padding: 12px 24px !important; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1) !important; | |
| transition: all 0.3s ease !important; | |
| } | |
| .gr-button-primary:hover { | |
| transform: translateY(-2px) !important; | |
| box-shadow: 0 6px 12px rgba(0,0,0,0.15) !important; | |
| } | |
| /* --- 6. 美化輸出文字框 (使其看起來像"顯示面板") --- */ | |
| #output-caption textarea, #output-vqa textarea { | |
| background: #f4f7f6 !important; | |
| border: 2px solid #bdc3c7 !important; | |
| border-radius: 10px !important; | |
| font-size: 1.15em !important; | |
| color: #2c3e50 !important; | |
| font-weight: 500 !important; | |
| } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), css=my_custom_css) as demo: | |
| # App 標題 (使用 elem_id 以便 CSS 選取) | |
| gr.Markdown( | |
| """ | |
| # 🎨 視覺語言 AI 展示 (Vision Language AI Demo) | |
| """, | |
| elem_id="main-title" | |
| ) | |
| gr.Markdown("### 統一上傳圖片,然後在下方體驗兩種不同的 AI 功能。") | |
| with gr.Row(variant="panel"): | |
| # --- (重新設計) 佈局:左側為輸入 --- | |
| with gr.Column(scale=2): | |
| with gr.Group(): | |
| gr.Markdown("### 1. 上傳圖片 (Input)") | |
| # 建立一個共用的圖片輸入元件 | |
| shared_image_input = gr.Image(type="pil", label="上傳圖片") | |
| gr.Markdown("#### 試試看範例圖片:") | |
| # 範例功能 (會自動填入上面的 shared_image_input) | |
| gr.Examples( | |
| examples=[ | |
| ["sample_images/cat.jpg"], | |
| ["sample_images/dog.jpg"] | |
| ], | |
| inputs=shared_image_input, | |
| label="點選範例圖片" | |
| ) | |
| # --- (重新設計) 佈局:右側為功能輸出 --- | |
| with gr.Column(scale=3): | |
| # --- 功能一:圖片標註 --- | |
| with gr.Group(): | |
| gr.Markdown("### 2. 功能一:圖片標註 (Image Captioning)") | |
| caption_button = gr.Button("生成圖片描述", variant="primary") | |
| caption_output_text = gr.Textbox( | |
| label="AI 生成的描述", | |
| interactive=False, | |
| elem_id="output-caption" # 綁定 CSS ID | |
| ) | |
| # --- 功能二:視覺問答 (VQA) --- | |
| with gr.Group(): | |
| gr.Markdown("### 3. 功能二:視覺問答 (VQA)") | |
| vqa_input_question = gr.Textbox( | |
| label="你的問題", | |
| placeholder="例如:圖片中有幾個人? (What color is the car?)" | |
| ) | |
| vqa_button = gr.Button("對圖片提出問題", variant="primary") | |
| vqa_output_answer = gr.Textbox( | |
| label="AI 的回答", | |
| interactive=False, | |
| elem_id="output-vqa" # 綁定 CSS ID | |
| ) | |
| # VQA 的範例 (會同時填入圖片 和 問題) | |
| gr.Examples( | |
| examples=[ | |
| ["sample_images/cat.jpg", "What color is the cat?"], | |
| ["sample_images/dog.jpg", "What color is the dog?"] | |
| ], | |
| inputs=[shared_image_input, vqa_input_question], | |
| label="點選範例 (包含圖片與問題)" | |
| ) | |
| # ----------------------------------------------------------------- | |
| # 4. 綁定按鈕和函式 (邏輯不變,只是元件名稱更新) | |
| # ----------------------------------------------------------------- | |
| # 功能一: | |
| caption_button.click( | |
| fn=get_image_caption, | |
| inputs=[shared_image_input], # 輸入來自共用的圖片 | |
| outputs=[caption_output_text] | |
| ) | |
| # 功能二: | |
| vqa_button.click( | |
| fn=answer_visual_question, | |
| inputs=[shared_image_input, vqa_input_question], # 輸入來自共用圖片 + VQA問題 | |
| outputs=[vqa_output_answer] | |
| ) | |
| # ----------------------------------------------------------------- | |
| # 5. 啟動 App (此部分與你的程式碼相同) | |
| # ----------------------------------------------------------------- | |
| if __name__ == "__main__": | |
| demo.launch(debug=True) | |