# 【vMaker Edge AI專欄 #24】 如何使用 Gradio 快速搭建人工智慧應用圖形化人機界面
作者:Jack OmniXRI, 2024/12/15
![vMaker_EdgeAI_24_Fig00](https://hackmd.io/_uploads/By1_KFMNJg.jpg)
相信很多朋友都是使用 Python 及 Jupyter Notebook 環境在開發人工智慧應用程式,不論是影像辨識、分類,還是大語言模型、影音生成應用。當只能使用命令列(Command Line)模式操作而沒有圖形化人機界面(Gaphical User Interface, GUI),那麼使用上就會變得非常不直覺且不方便。
傳統上要開發 Python GUI 大概會想到使用 Tkinter, PySide, PyQT 等工具,但這些工具比較適合開發桌機或手機版的應用,並不容易和 Jupyter Notebook 這類網頁版程式整合,包含 Google Colab, Intel OpenVINO Notebooks, Hugging Face 等。所以這裡要幫大家介紹另一項常見的 GUI 開源工具「**Gradio**」。[1]
Gradio 提供了很便捷的網頁型式的各種輸入和輸出模組,如下所示。[2]
* 應用界面:Interface(簡單應用)、Blocks(客製化應用)
* 輸出輸入:文字框(Textbox)、資料框(DataFrame)、影像(Image)、下拉盒(Dropdown)、數字(Number)、文字說明(Markdown)、檔案(File)
* 控制元件:按鍵(Button)
* 版面佈局:標籤頁(Tab)、列佈局(Row)、行佈局(Column)
以上內容除了可直接顯示在 Jupyter Notebook 欄位上,還可透過獨立網頁顯示,包括裝置端(本地端)網址(http://localhost:7860),或公開(雲端)網址(https://xxxx.gradio.live),方便分享結果給其它人使用。
接下來就依序介紹幾個常用模組的使用方式給大家參考。完整範例可點擊下列連結直接於 Google Colab 上啟動。
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/OmniXRI/Hello_World_Gradio/blob/main/Hello_World_Gradio.ipynb)
建議開啟後,先點擊選單「檔案」─「在雲端硬碟中儲存複本」,方便之後可以修改及測試程式。接著點擊選單「執行階段」─「全部執行」可一口氣把所有範例都執行一遍。
![vMaker_EdgeAI_24_Fig01](https://hackmd.io/_uploads/ByzUGcGEkx.jpg)
Fig. 1 Google Colab 工作及執行畫面。(OmniXRI整理製作, 2024/12/15)
## 1. 安裝 Gradio 及必要函式庫
在 Colab 中通常已預安裝好很多 Python 常用套件,如TensorFlow, PyTorch, OpenCV等,這裡只需安裝最重要的 gradio 即可,另外由於後面會下載一些配套檔案,所以另外多安裝一些必要的函式庫,如 requests, numpy 等。
```python=
!pip install -q gradio
!pip install requests
!pip install numpy
#!pip install opencv-pytho # Colab 預設已安裝,本地端可依需要開啟安裝
import gradio as gr # 導入 gradio 函式庫並令別名為 gr
import numpy as np # 導入 numpy 函式庫並令別名為 np
#import cv2 # 導入 opencv 函式庫
```
## 2. 基本文字/數字輸出入
### 2.1. 簡單應用界面一(簡單型)
Gradio 使用上非常簡單,只需定義一個處理函式 fn,接著就可呼叫界面 Interface() 函式 ,指定輸出入格式後,再呼叫執行函式 launch() 函式即可秀出一個漂亮的輸出入界面。
以下範例運行後,左半邊為文字輸入,左半邊為輸出結果。當輸入一個「名字」(字串),按下「Submit」即可在右半邊顯示「Hello 名字!!」,而其內容就是經過 greet1() 組合出來的。當按下「Clear」時可清除輸出入內容。
運行後,除了在 Jupyter Notebook 欄位中出現界面,另外會提供一個公開網址,點擊後會出現一個新網頁,顯示一樣的內容。這個網址就可分享給其它人,享受你設計出的應用。
**註:共享連結只保留72小時,如需免費永久托管,需在終端機模式運行「gradio deploy」部署到 Hugging Face Spaces。**
```python=
#import gradio as gr # 導入 gradio 函式庫並令別名為 gr
# 定義 Gradio 輸出入處理函式 greet1()
# 輸入文字: name(字串)
# 輸出結果: "Hello name!!"(字串)
def greet1(name):
return "Hello " + name + "!!"
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱, inputs: 輸人格式, outputs: 輸出格式
demo = gr.Interface(fn=greet1, inputs="text", outputs="text")
# 執行顯示界面
demo.launch()
```
![vMaker_EdgeAI_24_Fig02](https://hackmd.io/_uploads/SkP5YFGN1l.jpg)
Fig. 2 簡單文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15)
### 2.2. 簡單應用界面二(自定義型)
上一個範例,只有簡單的顯示界面。在這個範例可指定較複雜的設定,具有多個輸入和輸出,同時也自定義了輸出入的標籤,方便使用者辨識用途。
當在 name 欄位輸入「名字」,點選或解除「是早上」複選盒,拉動滑桿或直接輸入華氏溫度數值並按下「Submit」鍵,就會產生處理函式的輸出文字內容及溫度。當按下「Clear」鍵可清除輸入及輸出結果。
在處理函式 greet2() 引入三個變數,分別為 name(字串), is_morning(布林值)及temperature(數值),而回返值為二組字串 greeting 及四捨五入取小數點二位的攝氏溫度值。
在界面函式 Interface(), 分別使用 inputs, outputs 來定義每個輸出入值的更進一步外觀。如果想了解更多各元件用法可參考 [2]。
```python=
#import gradio as gr # 導入 gradio 函式庫並令別名為 gr
# 定義 Gradio 輸出入處理函式 greet2()
# 輸入: name(字串)、is_morning(布林值)、temperature(數值)
# 輸出: "Good morning name, It is xx.x ℉ today"(字串)、攝氏溫度(數值)
def greet2(name, is_morning, temperature):
salutation = "Good morning" if is_morning else "Good evening" # 若複選盒有勾選則輸出 "Good morning", 否則輸出 "Good evening"
greeting = f"{salutation} {name}. It is {temperature} ℉ today" # 組合輸出用字串
celsius = (temperature - 32) * 5 / 9 # 將華氏溫度轉成攝氏
return greeting, round(celsius, 2)
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱
# inputs: 輸人格式, 名字(標籤:名字)、是早上(複選盒)、華氏溫度(標籤:華氏(℉),滑桿,最小值0,最大值100,預設值50)
# outputs: 輸出格式,結果字串(標籤:輸出)、結果溫度(標籤:攝氏(℃))
demo = gr.Interface(
fn=greet2,
inputs=[gr.Textbox(placeholder="請輸入姓名", label="姓名"),
"checkbox",
gr.Slider(0, 100, value=50, label="華氏(℉)") ],
outputs=[gr.Textbox(label="輸出"),
gr.Textbox(label="攝氏(℃)") ],
)
# 執行顯示界面
demo.launch()
```
![vMaker_EdgeAI_24_Fig03](https://hackmd.io/_uploads/Skj9YKfVJx.jpg)
Fig. 3 自定義文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15)
### 2.3. 執行預設計 GUI (*.py)
對於常用的網頁表單格式,在不托管情況下也可以把相關內容預編成一個 Python 模組 (*.py)。
假設想要把上一步驟的 GUI 變成可引用之函式,可將後半段程式變成名為 launch_demo 的函式,再將程式儲存成 gradio_test.py 的程式,放在同一路徑下即可,如 Fig. 4所示。
```python=
# gradio_test.py
import gradio as gr # 導入 Gradio 函式庫並令別名為 gr
# 定義 Gradio 輸出入處理函式 greet2()
# 輸入: name(字串)、is_morning(布林值)、temperature(數值)
# 輸出: "Good morning name, It is xx.x ℉ today"(字串)、攝氏溫度(數值)
def greet2(name, is_morning, temperature):
salutation = "Good morning" if is_morning else "Good evening" # 若複選盒有勾選則輸出 "Good morning", 否則輸出 "Good evening"
greeting = f"{salutation} {name}. It is {temperature} ℉ today" # 組合輸出用字串
celsius = (temperature - 32) * 5 / 9 # 將華氏溫度轉成攝氏
return greeting, round(celsius, 2)
def launch_demo():
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱
# inputs: 輸人格式, 名字(字串)、是早上(複選盒)、華氏溫度(滑桿,最小值0,最大值100,預設值50)
# outputs: 輸出格式,結果字串(標籤 Reslut)、結果溫度(標籤 攝氏(℃))
demo = gr.Interface(
fn=greet2,
inputs=[gr.Textbox(placeholder="請輸入姓名", label="姓名"), "checkbox", gr.Slider(0, 100, value=50, label="華氏(℉)")],
outputs=[gr.Textbox(label="輸出"), gr.Textbox(label="攝氏(℃)")],
)
# 執行顯示界面
demo.launch()
```
若想在 Colab 上運行上述模組時,需先自行下載到 Colab 提供的臨時雲端硬碟,預設使用者根目錄路徑為 content。亦可自行手動上傳。
由於執行路徑並不包含此路徑,所以還需使用 sys.path.append() 將路徑加入才能正確引用。若在本地端執行則不用增加該目錄。
```python=
import requests
from pathlib import Path
import sys
# 從 Github 下載 gradio_test.py 並存於使用者根目錄
r = requests.get(
url="https://raw.githubusercontent.com/OmniXRI/Hello_World_Gradio/main/gradio_test.py",
)
open("gradio_test.py", "w").write(r.text)
sys.path.append('./') # 在 Colab 使用者根目錄 ./ 預設在 /content,將其加入方便開啟下載之檔案
from gradio_test import launch_demo
launch_demo() # 執行預設 GUI
```
![vMaker_EdgeAI_24_Fig04](https://hackmd.io/_uploads/H15BJ9fNyg.jpg)
Fig. 4 以 Python 模組方式引用,完成文字輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15)
## 3. 基本影像輸出入
### 3.1. 使用 numpy 格式影像
當執行後,可支持三種影像輸入方式,直接上傳(支持從電腦檔案夾點擊或直接拖拉置放)、從網路攝影機直接拍照取像及貼上已剪貼簿中的影像。
上傳影像後,按下「Submit」鍵,即可呼叫影像處理函式 sepia(),這裡會令原始影像變成棕色影像顯示在輸出。
```python=
#import gradio as gr # 導入 Gradio 函式庫並令別名為 gr
#import numpy as np # 導入 numpy 函式庫並令別名為 np
# 定義影像處理函式 sepia()
# 輸入: imput_image(影像)
# 輸出: sepia_img(影像)
def sepia(input_img):
sepia_filter = np.array([
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
])
sepia_img = input_img.dot(sepia_filter.T) # 將影像點乘使其變成棕色
sepia_img /= sepia_img.max() # 進行影像正規化
return sepia_img
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像
demo = gr.Interface(sepia, gr.Image(), "image")
# 執行顯示界面
demo.launch()
```
![vMaker_EdgeAI_24_Fig05](https://hackmd.io/_uploads/ByIqsiM4ye.jpg)
Fig. 5 影像輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15)
### 3.2. 使用 OpenCV 格式影像
如果想要使用 OpenCV 影像格式進行影像處理,在界面函式輸人部份需加上 type="filepath" ,而處理函式部份則需加上 input_img = cv2.imread(input_img) 才能順利工作。
```python=
#import gradio as gr # 導入 Gradio 函式庫並令別名為 gr
#import numpy as np # 導入 numpy 函式庫並令別名為 np
import cv2 # Colab 預設已安裝 opencv-python
# 定義影像處理函式 sepia()
# 輸入: imput_image(影像)
# 輸出: sepia_img(影像)
def sepia(input_img):
input_img = cv2.imread(input_img) # 從使用者根目錄讀取影像
sepia_filter = np.array([
[0.393, 0.769, 0.189],
[0.349, 0.686, 0.168],
[0.272, 0.534, 0.131]
])
sepia_img = input_img.dot(sepia_filter.T) # 將影像點乘使其變成棕色
sepia_img /= sepia_img.max() # 進行影像正規化
return sepia_img
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像
demo = gr.Interface(sepia, gr.Image(type="filepath"), "image")
# 執行顯示界面
demo.launch()
```
![vMaker_EdgeAI_24_Fig06](https://hackmd.io/_uploads/HklPk9MNkg.jpg)
Fig. 6 使用 numpy 和 OpenCV 影像格式程式比較。(OmniXRI整理製作, 2024/12/15)
## 4. 基本影音輸出入
為方便測試,會先下載兩個影音檔「Jack_OmniXRI.mp4」、「good_weather.wav」作為 Examples 。
另外為豐富人機界面另外加上四個項目:
* title = 標題
* description = 描述
* examples = [ [樣本1影片, 樣本1聲音], [樣本2影片, 樣本2聲音] ]
* article = 表單最後註腳,可使用 Markdown 語法
當按下 Examples 中文字時會自動載入影音檔到輸入欄位,若不想使用範例影音,亦可自行拖拉影音檔到輸入區。
這裡的影音處理函式 av_identity 為空的,直接輸出原影音檔,若有需要可在此處增加所需程式。
當按下「Submit」鍵後,會把輸入區之影音複製一份到輸出區。
```python=
#import requests
#from pathlib import Path
#import sys
# 從 Github 下載測試用影音檔並存於使用者根目錄
r = requests.get(
url="https://github.com/OmniXRI/Hello_World_Gradio/raw/refs/heads/main/Jack_OmniXRI.mp4",
)
with open("Jack_OmniXRI.mp4", "wb") as f:
f.write(r.content)
r = requests.get(
url="https://github.com/OmniXRI/Hello_World_Gradio/raw/refs/heads/main/good_weather_ZH.wav",
)
with open("good_weather_ZH.wav", "wb") as f:
f.write(r.content)
#sys.path.append('./') # 在 Colab 使用者根目錄 ./ 預設在 /content,將其加入方便開啟下載之檔案
#import gradio as gr # 導入 Gradio 函式庫並令別名為 gr
# 定義影音處理函式(空處理)
# 輸入: video(影片)、audio(聲音)
# 輸出: video(影片)、audio(聲音)
def av_identity(video, audio):
return video, audio
# 建立輸人及輸出簡單應用界面
# fn: 界面函數名稱, inputs: 輸人影像格式, outputs: 輸出影像
demo = gr.Interface(
fn = av_identity,
inputs = [gr.Video(),
gr.Audio()],
outputs = ["video",
"audio"],
title = "影音測試",
description = "操作說明:上傳影音檔或點擊 Examples 取得影音檔,再點擊 Submit 即可",
examples = [["Jack_OmniXRI.mp4", "good_weather_ZH.wav"]],
article = "更多資訊可參考 [OmniXRI Github](https://github.com/OmniXRI/Hello_World_Gradio)"
)
# 執行顯示界面
demo.launch()
```
![vMaker_EdgeAI_24_Fig07](https://hackmd.io/_uploads/rkrP1qzVkx.jpg)
Fig. 7 自定義影音輸出入界面運行結果。(OmniXRI整理製作, 2024/12/15)
## 小結
透過以上的介紹,相信大家已經對 Gradio 有了一些基本認識,只要透過更複雜的排列組合,就能讓大家更容易創建出屬於自己需求的應用。目前已有很多 AI 相關應用都是使用這項工具,包括大型語言模型對話,影音生成等,在 Hugging Face 上也有許多範例,後續有機會再為大家介紹更進階的應用。
## 參考文獻
[1] Gradio, Home Page & Github
https://www.gradio.app/
https://github.com/gradio-app/gradio
[2] Gradio, Documentation - interface
https://www.gradio.app/docs/gradio/interface
## 延伸閱讀
[A] Hugging Face, Gradio 塊簡介(NLP Coures)
https://huggingface.co/learn/nlp-course/zh-TW/chapter9/7
**本文同步發表在[【台灣自造者 vMaker】](https://vmaker.tw/archives/category/%e5%b0%88%e6%ac%84/jack-omnixri)**
---
OmniXRI 整理製作,歡迎點贊、收藏、訂閱、留言、分享
###### tags: `vMaker` `Edge AI`