Stable Diffusion+Pyqt5: 实现图像生成与管理界面(带保存 + 历史记录 + 删除功能)——我的实验记录(结尾附系统效果图)

目录

🧠 前言

🧾 我的需求

🔧 实现过程(按功能一步步来)

🚶‍♂️ Step 1:基本图像生成界面

🗃️ Step 2:保存图片并显示历史记录

📏 Step 3:优化长提示词显示和添加删除功能

🧹 Step 4:解决新生成图片删除失败

⚠️ 遇到的问题总结

✅ 最终效果展示

🧩 总结 & 收获


🧠 前言

本科课设做过一个人脸面部表情识别系统,当时是用Pyqt5库实现的图形可视化界面,最近我尝试结合 PyQt5 和 Stable Diffusion 模型开发一个图像生成工具,目标是实现一个带有图形界面的系统,能够输入提示词生成图像、自动保存并按序命名查看历史记录并支持删除功能。在开发过程中,我逐步实现了功能,也遇到了一些问题,最终在优化下达到了预期效果。本文将记录我的需求、实现过程、遇到的问题以及最终成果。
这一篇是在先前部署Stable Diffusion V1.5的基础上,加入了图形界面显示优化,部署可看从零搭建这篇,搭建完即可链接本篇:
深度学习项目记录·Stable Diffusion从零搭建、复现笔记-CSDN博客
从全灰到清晰图像:我的 Stable Diffusion 多尺度优化学习记录-CSDN博客
这里初始图像生成迭代步数我设置为30步,img2img优化迭代步数设置为50步



可能不好理解为什么实际运行生成图片过程中是15步?其实大概知道是微调受strength参数影响,50*0.3=15,这里我查了仔细解释,如下:
在 img2img(图像到图像)模式中,实际执行的迭代步数通常会受到 strength 参数的影响,而不是直接等于 num_inference_steps。
 

第一,strength 参数的作用

  • strength(这里是0.3)控制从初始图像 init_image 到生成新图像的“变化程度”。
  • 它的取值范围是0到1:
    • strength=0:完全保留初始图像,不做任何改变。
    • strength=1:完全忽略初始图像,等同于从头生成(text-to-image)。
    • strength=0.3:表示保留70%的初始图像特征,只对30%的内容进行调整。
       

第二,为什么是15步而不是50步?

  • 在 img2img 模式中,初始图像 init_image 已经提供了大部分结构,模型不需要从完全随机的噪声开始生成。因此,strength=0.3 表示只需要对图像进行轻微调整,实际迭代步数被缩减为 50 * 0.3 = 15。
  • 这是一个优化机制,避免浪费计算资源。
     

 第三,总结

  • 第一行(30/30):对应 pipe(prompt, ..., num_inference_steps=30),完整的30步生成。
  • 第二行(15/15):对应 img2img_pipe(..., num_inference_steps=50, strength=0.3),实际步数被 strength=0.3 缩减为15步。
  • 原因:img2img 模式的 strength 参数调整了实际迭代步数,以适配从已有图像开始的优化过程。

正文开始:

🧾 我的需求

  1. 生成逻辑

    • 输入提示词 → 点击生成 → 得到一张图像并保存,文件名按序递增(如 image_001.png, image_002.png)

    • 生成完成后暂停,等待下一次手动点击“开始生成”。

  2. 交互界面

    • 提供“清空提示词”按钮,方便输入新提示词。

    • 历史记录列表显示生成的图像,格式为:

      image_001.png  
      描述: A beautiful sunset
      
  3. 历史管理

    • 长提示词能完整显示,不被截断。

    • 每张图片支持删除功能,点击图片名称后可删除对应文件。


🔧 实现过程(按功能一步步来)


🚶‍♂️ Step 1:基本图像生成界面

目标:实现一个简单的 PyQt5 界面,能够输入提示词并生成图像,仅显示在界面上,不保存。

主要通过导入PyQt5库实现:

实现要点

  • 使用 StableDiffusionPipeline 和 StableDiffusionImg2ImgPipeline 生成图像。

  • 创建 PyQt5 界面,包含 QLineEdit(输入提示词)、QPushButton(开始生成)、QLabel(显示图像)

  • 将生成过程放入 QThread,通过信号机制 pyqtSignal将生成的图像传回主线程显示。(生成图像是个耗时操作,用 QThread 异步处理)

    用到的 Python 原理和技术

  • 多线程(QThread):避免生成图像时阻塞主界面,使用 pyqtSignal 传递结果。
  • GUI 布局(QVBoxLayout, QHBoxLayout):组织界面元素。
  • 图像处理(PIL 到 QPixmap):将生成的 PIL 图像转换为 PyQt5 可显示的格式。
class ImageGenerationThread(QThread):
    finished = pyqtSignal(object)
    def run(self):
        image = self.pipe(self.prompt).images[0]
        self.finished.emit(image)

def generate_image(self):
    self.thread = ImageGenerationThread(prompt, save_path)
    self.thread.finished.connect(self.show_image)
    self.thread.start()

def show_image(self, image):
    image.save("temp.png")
    pixmap = QPixmap("temp.png")
    self.image_label.setPixmap(pixmap)

🗃️ Step 2:保存图片并显示历史记录

目标:在生成图像后自动保存,并用列表显示图片名称和提示词,支持点击查看。

实现要点

  • 添加保存路径和文件名生成逻辑(image_001.png 等)。
  • 使用 QListWidget 显示历史记录,每张图片占两行:文件名和描述。
  • 实现点击列表项显示对应图像的功能。
     

    用到的 Python 原理和技术

  • 文件操作(os.path, os.makedirs):创建目录并保存图像。
  • 列表控件(QListWidget):存储和显示图片名及描述,使用 addItem 添加条目。
  • 字典(dict):用 self.history_data 存储文件名和提示词的映射,便于查看时获取描述。
  • 事件处理(itemClicked):绑定点击事件,加载并显示选中的图像。
def generate_image(self):
    filename = f"image_{self.count:03d}.png"
    save_path = os.path.join(self.save_dir, filename)
    self.thread = ImageGenerationThread(prompt, save_path)
    self.thread.finished.connect(self.on_generation_finished)

def on_generation_finished(self, image, save_path, prompt):
    pixmap = QPixmap(save_path)
    self.image_label.setPixmap(pixmap)
    filename = os.path.basename(save_path)
    self.history_list.addItem(filename)
    self.history_list.addItem(f"描述: {prompt}")
    self.history_data[filename] = prompt
    self.count += 1

📏 Step 3:优化长提示词显示和添加删除功能

目标:解决长提示词截断问题,并为每张图片添加删除按钮。

实现要点

  • 设置 QListWidget 宽度、开启自动换行;

  • 新增“删除图像”按钮,绑定删除逻辑;

  • 删除时移除对应列表项,弹确认框防误删。
     

    用到的 Python 原理和技术

  • 控件属性调整(setMaximumWidth, setWordWrap):增加宽度并启用自动换行。
  • 文件删除(os.remove):删除磁盘上的图片文件。
  • 列表操作(takeItem):从 QListWidget 中移除条目。
  • 对话框(QMessageBox):提供删除确认提示。
self.history_list.setMaximumWidth(400)
self.history_list.setWordWrap(True)

def delete_selected_image(self):
    filename = self.history_list.selectedItems()[0].text()
    image_path = os.path.join(self.save_dir, filename)
    os.remove(image_path)
    row = self.history_list.row(selected_item)
    self.history_list.takeItem(row + 1)  # 描述
    self.history_list.takeItem(row)      # 文件名

🧹 Step 4:解决新生成图片删除失败

现象:已有图片可以删,但刚生成的删不了,会报错 [WinError 2]

原因:生成线程或图像显示时还占着这个文件的资源,没释放。

解决办法

  • 生成完成后手动释放图像对象;

  • 删除前清空当前显示的图像;

  • 加一波 gc.collect() 触发垃圾回收。
     

    用到的 Python 原理和技术

  • 垃圾回收(gc.collect):强制释放内存中的图像对象。
  • 资源管理(del, clear):显式删除图像对象并清除 QLabel 显示。
  • 异常处理(try-except):捕获删除时的错误并显示。
def on_generation_finished(self, image, save_path, prompt):
    # 显示图像 & 加入历史列表 ...
    del image
    gc.collect()
    self.image_label.clear()

def delete_selected_image(self):
    if self.image_label.pixmap():
        self.image_label.clear()
    os.remove(image_path)

⚠️ 遇到的问题总结

问题描述解决方法
❌ 无法保存图像最初没写保存逻辑手动加保存路径 + 文件名管理
❌ 提示词显示不完整长提示词在历史列表中只显示一行增加宽度 + 开启 setWordWrap(True)
❌ 新图片删不掉报错 [WinError 2] 文件被占用显式释放图像资源 + 清空 QLabel + 垃圾回收

最终效果展示

  1. 生成 + 保存

    • 输入提示词,点击“开始生成”,生成一张图像并保存(如 image_001.png),完成后暂停。
    • 清空提示词后输入新提示词,点击生成,保存为 image_002.png,文件名依次递增。
  2. 历史记录显示

    • 历史列表中,文件名和提示词分两行显示,长提示词自动换行,例如:

      image_001.png  
      描述: A beautiful sunset over the mountains with a long description that wraps
      image_002.png  
      描述: A cute kitten playing with a ball
      
  3. 删除功能完善

    • 选中历史中的图片文件名,点“删除”按钮,会弹窗确认;

    • 删除后界面实时刷新,文件从磁盘也会消失;删除后:

    • 新生成的图片也能正常删了!删除001.png

      下方显示已删除图像+图像名
      生成测试:This guy is wearing a short-sleeve T-shirt with pure color patterns. The T-shirt is with cotton fabric and its neckline is v-shape. The pants this guy wears is of long length. The pants are with cotton fabric and solid color patterns
      这位男士穿着一件纯色图案的短袖 T 恤。T恤为棉质面料,领口呈 V 形。这位男士穿着一条长裤。裤子为纯棉面料,纯色图案。
      效果一般,测试2:A little girl is sitting in front of a large painted rainbow .

      测试3:White dog playing with a red ball on the shore near the water .



      关闭系统界面,图像已保存到本地


🧩 总结 & 收获

这个小项目让我逐步实践了以下内容:

  • PyQt5 界面搭建;

  • 多线程 + 信号机制避免卡顿;

  • 图像处理、自动保存、文件管理;

  • 资源释放与垃圾回收(真香);

  • 控件交互与用户体验优化。

最关键的是,从一开始的功能设想到实际落地、再到解决 bug 完善体验,完整走了一遍闭环,非常适合练手或当项目展示。


如果你也想做个图像生成小工具类似系统,可以直接参考我这套逻辑(Pyqt5+生成模型)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值