使用Gradio构建交互式Web应用-P2

Gradio界面设计与交互组件

Posts
Gradio
APP
Deep learning
Author

于峻川

Published

July 27, 2024

使用Gradio构建交互式Web应用



这是一个关于如何使用 Gradio 构建 Web 应用程序的开源系列教程。你将从设置 Python 环境开始,学习文本、图像等各类输入组件,自定义界面,设计复杂的交互等。本课程还将涵盖使用 Gradio 和 GDAL 处理遥感数据,用于图像增强、地理坐标转换、坡度分析等任务;学习如何使用 Gradio 和 Foliumap 创建交互式地图,实现动态地理空间数据可视化;如何集成机器学习模型并在 Hugging Face Spaces 上发布 web 应用程序。本教程包括实例、演示和作业。完成本教程后,你将能够高效地构建、部署和共享交互式 Web 应用程序。



课程相关资源链接GITHUB

Part2 :Gradio界面设计与交互组件



DEMO 2-1: Gradio的多种交互组件



在学习 Gradio 时,关键在于理解和掌握inputs、outputs以及 fn 这三个核心要素。

  • fn 是围绕用户界面包装的函数,它接受输入并产生输出,定义了整个交互的核心逻辑。

  • outputs 决定了最终呈现给用户的结果形式和内容。

  • inputs 是用户与应用进行交互的起点,学习各类交互组件是掌握数据接口的关键。Gradio 提供了多种交互组件,如文本框(gr.Textbox)、数字输入框(gr.Number)、滑块(gr.Slider)、下拉菜单(gr.Dropdown)、单选按钮(gr.Radio)和图像上传组件(gr.Image)等。本案例将想你展示这些输入组件,请通过与各个组件的互动,掌握不同类型数据输入的技巧。



import gradio as gr

# 定义处理函数
def process_inputs(text_input, number_input, number_slider, dropdown_selection, radio_options, image_input):
    
    processed_text = f"You entered: {text_input}" 
    processed_number = f"You entered: {number_input}" 
    processed_slider = f"Number selected from slider: {number_slider}" 
    processed_dropdown = f"You selected from dropdown: {dropdown_selection}" 
    processed_radio = f"You selected from radio buttons: {radio_options}" 
    
    if image_input is not None:
        imageshape = f"The shape of the selected image is: {image_input.shape}"
        return processed_text, processed_number, processed_slider, processed_dropdown, processed_radio, imageshape
    else:
        return processed_text, processed_number, processed_slider, processed_dropdown, processed_radio, None

# 创建一个复杂的界面
demo = gr.Interface(
    fn=process_inputs,  # 处理函数
    inputs=[
        gr.Textbox(label="Text Input"),  # 文本输入的文本框
        gr.Number(minimum=5, maximum=100, step=10, label="Number"),  # 具有范围的数字输入
        gr.Slider(minimum=0, maximum=100, step=1, label="Number Slider"),  # 用于数字选择的滑块
        gr.Dropdown(choices=["Option 1", "Option 2", "Option 3"], label="Dropdown Selection"),  # 用于选择的下拉菜单
        gr.Radio(choices=["Radio 1", "Radio 2", "Radio 3"], label="Radio Options"),  # 用于选择的单选按钮
        gr.Image(label="Upload Image", type="numpy"),  # 图像上传组件
    ],
    outputs=[
        gr.Text(label="Processed Text"), 
        gr.Text(label="Processed Number"), 
        gr.Text(label="Processed Slider"), 
        gr.Text(label="Processed Dropdown"),  
        gr.Text(label="Processed Radio"),  
        gr.Text(label="Processed Image")  
    ],
    title="Complex Gradio Interface with Multiple Components",  # 具有多个组件的复杂 Gradio 界面的标题
    description="This interface demonstrates the use of various input components such as textbox, slider, dropdown, radio, and image upload."  # 此界面演示了诸如文本框、滑块、下拉菜单、单选按钮和图像上传等各种输入组件的使用。
)

demo.launch(debug=True)

DEMO 2-2: 复杂界面设计与文件的交互



学习使用 Gradio 构建复杂界面,你需要掌握这些技巧

  • gr.Blocks 对于简单的应用场景我们以如上一个案例一样使用 gr.Interface。但对于需要使用多个 function 的复杂应用,我们需要使用 gr.Blocks,它提供了更高的灵活性和定制性,能满足复杂界面的多样需求。实际上我们在后续的案例中将一直使用它。

  • 复杂界面设计 Gradio 为我们提供了非常灵活的界面构建方法,你可以通过gr.Row, gr.Column 构建横向或竖向的组件,并将它们进行任意的组合,通过 gr.Tab 构建多页面的应用,可以通过 gr.Accordion 和 gr.Markdown 来丰富界面的信息。这种自由布局的特性让我们能够根据具体的业务逻辑和用户体验需求,更合理地组织和展示界面元素。

  • Event Listeners 我认为 Gradio 的输入监听机制是使其区别于其他 app builder 的关键,当用户为一些组件设置 listeners 交互时(如 click,change,select),可以触发预定义的函数或操作,从而增强应用的交互性和动态性。

  • 文件机制 了解文件形式的交互规则也是必不可少的。通过 gr.File, gr.FileExplore 以及 gr.DownloadButton 等可以完成文件的上传、浏览、下载等操作。在Gradio中你可以通过app读写授权文件夹下的文件,但需要注意的是当你想将app处理后的结果以文件形式下载到本地时,app 会通过生成临时文件来响应。

本案例中,只是对以上的技巧做初步的运用,请在后续课程中留意它们的使用,熟练掌握这些技巧,将有助于你构建出功能强大 Gradio 应用。

import gradio as gr
import pandas as pd
from PIL import Image
from pathlib import Path

# 函数用于对输入数字进行平方
def change_number(x):
    return x**2 

# 函数用于下载图片
def download_image(x):
    img = x['composite'][:, :, :3]  # 提取RGB通道
    print(img.shape)
    rgb_image = Image.fromarray(img)  # 将数组转换为图像
    tempdir = './mydraw.jpg'  # 定义临时文件路径
    rgb_image.save(tempdir)  # 保存图像
    print(tempdir, Path(tempdir).stem)  # 打印文件路径和文件名
    return gr.DownloadButton(label=f"Download {Path(tempdir).stem}", value=tempdir, visible=True)  # 创建下载按钮

# 函数用于获取文件路径并绘制CSV文件中的数据
def getfilepath(x):
    path = x[0]  # 获取文件路径
    df_read = pd.read_csv(path)  # 读取CSV文件
    plot = gr.LinePlot(  # 创建折线图
        df_read,
        x="band",
        y="Reflectance",
        color="Symbol",
        color_legend_position="bottom",
        title="Spectra of Different Materials",  # 图表标题
        tooltip=["band", "Reflectance", "Symbol"],  # 提示信息
        height=250,
        width=500,
        container=False,
    )
    return plot

# 函数用于绘制用户上传的CSV文件中的数据
def getpath(x):
    path = x.name  # 获取上传的文件路径
    df_read = pd.read_csv(path)  # 读取CSV文件

    plot = gr.LinePlot(  # 创建折线图
        df_read,
        x="band",
        y="Reflectance",
        color="Symbol",
        color_legend_position="bottom",
        title="Spectra of Different Materials",
        tooltip=["band", "Reflectance", "Symbol"],
        height=250,
        width=500,
        container=False,
    )
    return plot

# 创建使用"soft"主题的Gradio界面
with gr.Blocks(theme="soft") as demo:
    gr.Markdown("# Web app interface design")  # Markdown标题
    csvfile = gr.update(value='')  # 更新组件的值

    with gr.Tab("Get numbers"):  # 第一个子应用标签页
        with gr.Accordion("Readme", open=False):  # 可折叠的"阅读我"部分
            gr.Markdown(" Square of the input number")  # Markdown内容
        with gr.Row():  # 行容器
            with gr.Column():  # 列容器
                temp_slider = gr.Slider(minimum=0.0, maximum=10, step=1, interactive=True, label="Slide me")  # 滑块组件
            with gr.Column():
                out_slider = gr.Textbox()  # 文本框组件

    with gr.Tab("Draw a picture"):  # 第二个子应用标签页
        image_input = gr.ImageEditor(type="numpy", show_download_button=False, label="Draw a Picture")  # 图像编辑器组件
        image_button = gr.DownloadButton("Download", visible=True, variant='primary')  # 下载按钮

    with gr.Tab("Plot a figure"):  # 第三个子应用标签页
        with gr.Row():  # 行容器
            with gr.Column():  # 列容器
                file_explore = gr.FileExplorer(root_dir="./data")  # 文件浏览器组件
            with gr.Column():
                file = gr.File(file_count="single", scale=1, label="Upload the csv file")  # 文件上传组件

        with gr.Row():
            plot = gr.LinePlot()  # 折线图组件

    # 将滑块的变化事件链接到change_number函数
    temp_slider.change(change_number, inputs=temp_slider, outputs=out_slider)
    # 将图像编辑器的变化事件链接到download_image函数
    image_input.change(download_image, inputs=[image_input], outputs=image_button)
    # 将文件浏览器的变化事件链接到getfilepath函数
    file_explore.change(getfilepath, inputs=file_explore, outputs=plot)
    # 将文件上传组件的变化事件链接到getpath函数
    file.change(getpath, inputs=file, outputs=plot)

if __name__ == "__main__":
    demo.launch()  # 启动应用

请关注微信公众号【45度科研人】回复“@gradio”获取该教程配套数据,欢迎后台留言!

为了促进沟通与交流,我们建立了「养生科研」学术交流群。这个平台不仅能够让大家迅速获取本公众号的资源,还为各位提供了一个共同探讨问题、交流思想的空间。有意向加入交流群的朋友们,可以通过添加小编的微信来获得入群邀请。请注意,在添加时请按照“加群-单位-研究方向-姓名”的格式备注您的信息,否则您的申请可能无法通过。