Stable-Diffusion-v1-5-archive WebUI 定制化:CSDN平台界面主题与快捷按钮扩展

你是不是觉得 Stable Diffusion WebUI 的默认界面有点千篇一律?每次生成图片都要重复输入一堆参数,或者来回切换标签页,效率有点低?

今天,我们就来聊聊如何为部署在 CSDN 星图平台上的 Stable-Diffusion-v1-5-archive 镜像,进行一番“精装修”。我们将从界面主题美化入手,再到添加快捷按钮、优化工作流,让你的人机交互体验直线上升,创作效率翻倍。

1. 为什么需要定制化 WebUI?

在深入动手之前,我们先明确一下目标。对 WebUI 进行定制化,绝不仅仅是为了“好看”,它背后有非常实际的工程价值:

  • 提升操作效率:将高频操作(如固定种子、切换常用分辨率)变成一键点击,省去重复输入和查找的时间。
  • 降低使用门槛:通过预设和快捷方式,让新用户更快上手,专注于创意本身而非参数调试。
  • 个性化工作流:每个创作者的习惯不同,定制化的界面能更好地贴合个人或团队的特定创作流程。
  • 视觉舒适度:长时间面对一个界面,一个符合审美的主题能有效缓解视觉疲劳。

本次我们改造的对象,是基于 Gradio 框架构建的 Stable Diffusion WebUI。Gradio 的优点是快速构建,但默认样式比较基础,这正好给了我们充足的发挥空间。

2. 环境准备与项目结构分析

我们的改造将在 CSDN 星图平台提供的 Stable-Diffusion-v1-5-archive 镜像环境中进行。这个镜像已经预置了模型和 Web 服务,开箱即用。

首先,通过终端连接到你的 GPU 实例。

2.1 定位 WebUI 应用目录

服务运行后,WebUI 的应用文件通常位于工作空间内。我们可以先查看服务状态,并找到其主程序文件。

# 查看当前运行的WebUI服务状态
supervisorctl status sd15-archive-web

# 通常,应用主文件在这个路径下,我们进入工作空间查看
cd /root/workspace
ls -la

你可能会看到一个名为 app.pywebui.py 的文件,这就是 Gradio 应用的入口。我们的所有定制化修改,都将围绕这个文件及其相关资源(如 CSS 文件)展开。

2.2 理解基础界面构成

在修改前,先快速浏览一下默认的 app.py,了解其结构:

# 这是一个简化的示例结构,实际文件可能更复杂
import gradio as gr

def generate_image(prompt, negative_prompt, steps, guidance_scale, width, height, seed):
    # 这里是调用SD模型生成图像的逻辑
    # ...
    return image, parameters_json

# 使用Gradio创建界面
with gr.Blocks() as demo:
    gr.Markdown("## Stable Diffusion v1.5 Archive 文生图")
    with gr.Row():
        with gr.Column():
            prompt = gr.Textbox(label="Prompt")
            negative_prompt = gr.Textbox(label="Negative Prompt")
            # ... 其他参数控件
            generate_btn = gr.Button("生成图片")
        with gr.Column():
            output_image = gr.Image(label="输出图像")
            output_json = gr.JSON(label="推理参数")

    generate_btn.click(fn=generate_image,
                       inputs=[prompt, negative_prompt, steps, guidance_scale, width, height, seed],
                       outputs=[output_image, output_json])

demo.launch(server_name="0.0.0.0", server_port=7860)

可以看到,界面由 gr.Blocks() 构建,里面包含了文本输入框、滑块、按钮等组件。我们的定制化,就是在这个框架上“添砖加瓦”。

3. 实战一:自定义界面主题与样式

Gradio 支持通过 CSS 来深度定制界面外观。我们将创建一个自定义的 CSS 文件,并注入到应用中。

3.1 创建自定义 CSS 文件

在工作空间内,创建一个新的 CSS 文件,例如 custom_theme.css

cd /root/workspace
touch custom_theme.css

然后,用你喜欢的文本编辑器(如 vimnano)打开这个文件,添加以下样式代码。这里提供了一个偏向深色科技感的主题示例:

/* custom_theme.css - 深色科技主题 */
.gradio-container {
    background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%) !important;
    color: #e2e8f0 !important;
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}

/* 标题和标签样式 */
h1, h2, h3, h4, .gr-markdown, label {
    color: #f8fafc !important;
    font-weight: 600;
}
.gr-markdown {
    background-color: rgba(30, 41, 59, 0.7) !important;
    padding: 1rem !important;
    border-radius: 0.75rem !important;
    border-left: 4px solid #3b82f6 !important;
}

/* 输入框、文本框样式 */
input[type="text"], textarea, .gr-box {
    background-color: #334155 !important;
    border: 1px solid #475569 !important;
    color: #f1f5f9 !important;
    border-radius: 0.5rem !important;
    padding: 0.75rem !important;
}
input[type="text"]:focus, textarea:focus {
    border-color: #60a5fa !important;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2) !important;
    outline: none;
}

/* 滑块样式 */
.gr-slider .gr-slider-track, .gr-slider .gr-slider-fill {
    background: #3b82f6 !important;
}
.gr-slider .gr-slider-handle {
    background: #ffffff !important;
    border: 2px solid #3b82f6 !important;
}

/* 按钮样式 - 主要生成按钮 */
button.gr-button.primary {
    background: linear-gradient(90deg, #3b82f6, #1d4ed8) !important;
    color: white !important;
    font-weight: bold;
    border: none;
    border-radius: 0.5rem;
    padding: 0.75rem 1.5rem;
    transition: all 0.2s ease;
}
button.gr-button.primary:hover {
    background: linear-gradient(90deg, #2563eb, #1e40af) !important;
    transform: translateY(-2px);
    box-shadow: 0 10px 25px -5px rgba(37, 99, 235, 0.5);
}

/* 按钮样式 - 次要快捷按钮 */
button.gr-button.secondary {
    background-color: #475569 !important;
    color: #cbd5e1 !important;
    border: 1px solid #64748b !important;
    border-radius: 0.375rem;
    padding: 0.5rem 1rem;
    margin: 0.25rem;
    font-size: 0.875rem;
}
button.gr-button.secondary:hover {
    background-color: #64748b !important;
    color: #f1f5f9 !important;
}

/* 输出图像区域 */
.gr-image-preview, .gr-image {
    border: 2px solid #475569 !important;
    border-radius: 0.75rem !important;
    background-color: #1e293b !important;
}

/* JSON输出框 */
.gr-json {
    background-color: #1e293b !important;
    border: 1px solid #475569 !important;
    border-radius: 0.5rem !important;
    font-family: 'Monaco', 'Menlo', monospace !important;
    font-size: 0.9em;
}

这个 CSS 做了以下几件事:

  1. 将背景改为深色渐变,减少长时间使用的眼睛疲劳。
  2. 美化了输入框、按钮、滑块的样式,使其更具现代感。
  3. 为主要的“生成”按钮添加了渐变和悬停效果,使其更醒目。
  4. 为我们将要添加的快捷按钮定义了样式。

3.2 在 Gradio 应用中加载 CSS

接下来,我们需要修改 app.py,在创建 gr.Blocks() 时加载我们的 CSS。

app.py 文件的开头或 demo.launch 之前,添加以下代码:

# 在 app.py 中,创建 demo 之前或之后添加
import os

# 读取自定义CSS文件
css_file_path = os.path.join(os.path.dirname(__file__), "custom_theme.css")
custom_css = ""
if os.path.exists(css_file_path):
    with open(css_file_path, "r", encoding="utf-8") as f:
        custom_css = f.read()
    print("自定义CSS主题加载成功。")
else:
    print(f"未找到CSS文件: {css_file_path}")

# 修改 gr.Blocks 的创建,注入CSS
with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: # 可以保留一个基础主题
    # ... 你原有的界面构建代码 ...

修改完成后,保存文件,并重启 WebUI 服务。

supervisorctl restart sd15-archive-web

等待几秒钟后,刷新你的 WebUI 页面(地址为 https://gpu-{你的实例ID}-7860.web.gpu.csdn.net/),应该就能看到焕然一新的深色主题界面了。

4. 实战二:添加快捷按钮与预设功能

界面好看了,接下来我们提升效率。我们将添加一排快捷按钮,用于快速填充常用参数和提示词。

4.1 添加快捷参数按钮

我们计划在参数设置区域上方,添加一行按钮,实现以下功能:

  1. 固定种子:点击后,将 Seed 设置为一个特定值(如 12345),便于复现。
  2. 常用分辨率:一键设置 512x512768x768 等常用出图尺寸。
  3. 质量预设:一键设置 Steps=25, Guidance Scale=7.5 这样的常用高质量参数组合。

修改 app.py 中界面构建的部分:

with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo:
    gr.Markdown("## 🎨 Stable Diffusion v1.5 Archive - 定制增强版")

    with gr.Row():
        with gr.Column(scale=2):
            # ========== 快捷按钮区域 ==========
            with gr.Row():
                gr.Markdown("**⚡ 快捷操作**")
            with gr.Row():
                fix_seed_btn = gr.Button("固定种子 (12345)", elem_classes="secondary")
                res_512_btn = gr.Button("分辨率 512x512", elem_classes="secondary")
                res_768_btn = gr.Button("分辨率 768x768", elem_classes="secondary")
                quality_high_btn = gr.Button("高质量预设", elem_classes="secondary")
            gr.Markdown("---") # 分隔线

            # ========== 原有的参数输入区域 ==========
            prompt = gr.Textbox(label="📝 正向提示词 (建议使用英文)", placeholder="例如:a beautiful landscape, sunset, digital art, highly detailed", lines=3)
            negative_prompt = gr.Textbox(label="🚫 负向提示词", value="lowres, blurry, bad anatomy, extra fingers", lines=2)
            with gr.Row():
                steps = gr.Slider(minimum=1, maximum=50, step=1, value=20, label="采样步数 (Steps)")
                guidance_scale = gr.Slider(minimum=1, maximum=20, step=0.5, value=7.5, label="引导强度 (Guidance Scale)")
            with gr.Row():
                width = gr.Slider(minimum=256, maximum=1024, step=64, value=512, label="宽度")
                height = gr.Slider(minimum=256, maximum=1024, step=64, value=512, label="高度")
            seed = gr.Number(label="随机种子 (Seed)", value=-1, precision=0)
            generate_btn = gr.Button("🚀 生成图片", variant="primary")

        with gr.Column(scale=3):
            output_image = gr.Image(label="生成的图像", type="pil")
            output_json = gr.JSON(label="本次生成参数")

    # ========== 快捷按钮的点击事件 ==========
    def set_seed_to_fixed():
        return 12345
    def set_res_512():
        return 512, 512
    def set_res_768():
        return 768, 768
    def set_quality_high():
        return 25, 7.5 # steps, guidance_scale

    # 绑定按钮事件
    fix_seed_btn.click(fn=set_seed_to_fixed, outputs=seed)
    res_512_btn.click(fn=set_res_512, outputs=[width, height])
    res_768_btn.click(fn=set_res_768, outputs=[width, height])
    quality_high_btn.click(fn=set_quality_high, outputs=[steps, guidance_scale])

    # 原有的生成按钮事件
    generate_btn.click(fn=generate_image,
                       inputs=[prompt, negative_prompt, steps, guidance_scale, width, height, seed],
                       outputs=[output_image, output_json])

代码解释

  • 我们新增了一行 gr.Row() 来放置快捷按钮,并给按钮添加了 elem_classes="secondary" 以应用之前 CSS 中定义的次要按钮样式。
  • 为每个快捷按钮定义了一个简单的函数(如 set_seed_to_fixed),这个函数返回想要设置的值。
  • 使用 gr.Button.click() 方法将按钮与函数绑定,并指定函数的输出(outputs)更新哪个界面组件(如 seed, width 等)。

4.2 添加快捷提示词按钮

除了参数,提示词也可以预设。我们可以添加一些针对常用风格的快捷提示词按钮。

在刚才的快捷按钮区域下方,继续添加:

            # ... 上面是参数快捷按钮 ...
            gr.Markdown("---")
            # ========== 快捷提示词按钮 ==========
            with gr.Row():
                gr.Markdown("**🎨 风格预设**")
            with gr.Row():
                style_btn_photo = gr.Button("真实照片", elem_classes="secondary")
                style_btn_anime = gr.Button("二次元动漫", elem_classes="secondary")
                style_btn_painting = gr.Button("油画艺术", elem_classes="secondary")
                style_btn_cyber = gr.Button("赛博朋克", elem_classes="secondary")

    # ... 其他代码 ...

    # ========== 快捷提示词按钮事件 ==========
    def apply_photo_style():
        base_prompt = "masterpiece, best quality, photorealistic, 8k, ultra detailed, sharp focus"
        base_negative = "cartoon, painting, illustration, 3d, render, anime, blurry"
        return base_prompt, base_negative

    def apply_anime_style():
        base_prompt = "masterpiece, best quality, 1girl, anime style, vibrant colors, detailed eyes"
        base_negative = "photorealistic, realistic, 3d, render, ugly, deformed"
        return base_prompt, base_negative

    # ... 为其他风格按钮定义类似的函数 ...

    # 绑定提示词按钮事件
    style_btn_photo.click(fn=apply_photo_style, outputs=[prompt, negative_prompt])
    style_btn_anime.click(fn=apply_anime_style, outputs=[prompt, negative_prompt])
    # ... 绑定其他风格按钮 ...

现在,你的界面上方应该有两排快捷按钮。点击“真实照片”,正向和负向提示词框会自动填入对应的风格关键词;点击“分辨率 768x768”,宽高滑块会自动跳转。这大大减少了手动输入和调整的时间。

5. 进阶优化:历史记录与参数快照

对于创作者来说,回溯和复用之前的成功参数组合非常有价值。我们可以实现一个简单的“参数快照”功能。

5.1 添加快照记录区域

在输出图像旁边,添加一个用于显示和选择历史快照的区域。

        with gr.Column(scale=3):
            output_image = gr.Image(label="生成的图像", type="pil")
            output_json = gr.JSON(label="本次生成参数")
            gr.Markdown("---")
            with gr.Row():
                with gr.Column(scale=1):
                    save_snapshot_btn = gr.Button("💾 保存当前参数为快照", variant="secondary")
                    snapshot_dropdown = gr.Dropdown(label="加载历史快照", choices=[], interactive=True)
                    load_snapshot_btn = gr.Button("📂 加载选中快照", variant="secondary")
                with gr.Column(scale=2):
                    snapshot_info = gr.Textbox(label="快照描述(可选)", placeholder="例如:金色麦田风景测试", lines=2)
                    snapshot_list_display = gr.Textbox(label="已有快照", interactive=False, lines=5)

5.2 实现快照的保存与加载逻辑

我们需要在 Python 后端维护一个快照列表。为了简单起见,我们将其保存在内存中(服务重启会丢失)。在生产环境中,你可能需要将其保存到文件或数据库中。

app.py 顶部定义全局变量和函数:

import json
from datetime import datetime

# 用于存储快照的列表
parameter_snapshots = []

def save_current_snapshot(prompt, neg_prompt, steps, scale, width, height, seed, info):
    """保存当前参数为快照"""
    snapshot = {
        "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "info": info,
        "parameters": {
            "prompt": prompt,
            "negative_prompt": neg_prompt,
            "steps": steps,
            "guidance_scale": scale,
            "width": width,
            "height": height,
            "seed": seed
        }
    }
    parameter_snapshots.append(snapshot)
    # 更新下拉菜单选项
    choices = [f"{s['timestamp']} - {s['info']}" for s in parameter_snapshots]
    # 返回更新后的下拉菜单和清空的描述框
    return gr.Dropdown.update(choices=choices), "", "\n".join(choices)

def load_selected_snapshot(selected_snapshot_str):
    """加载选中的快照参数"""
    if not selected_snapshot_str:
        return "", "", 20, 7.5, 512, 512, -1 # 返回默认值
    # 从字符串中找到对应的快照索引
    for idx, snap in enumerate(parameter_snapshots):
        if f"{snap['timestamp']} - {snap['info']}" == selected_snapshot_str:
            params = snap['parameters']
            return (params['prompt'], params['negative_prompt'],
                    params['steps'], params['guidance_scale'],
                    params['width'], params['height'],
                    params['seed'])
    return "", "", 20, 7.5, 512, 512, -1 # 未找到则返回默认值

然后,在界面构建代码的底部,绑定按钮事件:

    # ... 绑定其他按钮事件 ...

    # 绑定快照功能事件
    save_snapshot_btn.click(fn=save_current_snapshot,
                            inputs=[prompt, negative_prompt, steps, guidance_scale, width, height, seed, snapshot_info],
                            outputs=[snapshot_dropdown, snapshot_info, snapshot_list_display])
    load_snapshot_btn.click(fn=load_selected_snapshot,
                            inputs=snapshot_dropdown,
                            outputs=[prompt, negative_prompt, steps, guidance_scale, width, height, seed])

现在,当你生成一张满意的图片后,可以在“快照描述”里写个备注,点击“保存当前参数为快照”。之后,你就可以从下拉菜单中选择它,并点击“加载选中快照”,所有参数都会自动填充回去,方便你进行微调或复现。

6. 总结与部署

通过以上步骤,我们完成了一个从视觉到功能都得到显著增强的 Stable Diffusion WebUI。让我们回顾一下核心成果:

  1. 个性化主题:通过注入自定义 CSS,我们将默认界面改造为更护眼、更具科技感的深色主题,提升了长时间使用的舒适度。
  2. 效率快捷按钮:我们添加了两类快捷按钮。参数快捷按钮(固定种子、分辨率、质量预设)让常用设置触手可及;风格提示词按钮则提供了快速启动不同创作风格的入口,极大提升了操作流暢度。
  3. 参数快照功能:实现了一个简单的历史参数管理功能,允许用户保存和加载成功的参数组合,便于回溯、复现和迭代创作。

完成所有修改后,别忘了重启服务以使更改生效:

supervisorctl restart sd15-archive-web

一些进一步的思考

  • 主题分享:你可以将 custom_theme.css 文件分享给其他用户,他们只需放入自己的 workspace 并修改 app.py 加载路径即可使用。
  • 功能扩展:本文实现的“快照”功能是内存式的。你可以尝试将其改为基于文件(如 JSON 文件)的存储,这样数据在服务重启后也不会丢失。
  • 更多快捷方式:根据你的创作习惯,可以继续添加更多快捷按钮,例如“清除所有输入”、“填充上次参数”、“批量生成预设”等。
  • 布局优化:Gradio 的 gr.Row()gr.Column() 非常灵活,你可以尝试将图像输出区放大,或将参数区折叠进一个可伸缩的标签页(gr.Tab()),以创造更极致的创作画布。

定制化你的 AI 创作工具,让它完全适应你的工作流,这本身就是一种充满乐趣的创作。希望这篇指南能帮助你打造出独一无二、高效顺手的 Stable Diffusion 创作环境。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐