Z-Image-Turbo二次开发入门:修改源码添加新功能
引言:为什么需要二次开发?
Z-Image-Turbo 是阿里通义实验室推出的高性能 AI 图像生成模型,其 WebUI 版本基于DiffSynth Studio框架构建,支持快速推理与高质量图像输出。虽然官方提供了完整的用户界面和基础功能,但在实际项目中,我们常常需要:
- 添加自定义图像后处理功能(如水印、裁剪)
- 集成企业内部系统(如内容审核、自动归档)
- 扩展提示词模板库或预设风格
- 支持新的输出格式或存储方式
这些需求无法通过配置文件实现,必须进行源码级二次开发。
本文将带你从零开始,基于科哥构建的Z-Image-Turbo WebUI项目,完成一次典型的二次开发实践:在生成图像后自动添加文字水印。整个过程涵盖环境准备、代码结构解析、功能扩展与测试验证,适合有一定 Python 基础的开发者阅读。
开发前准备:环境与项目结构
环境依赖
确保你已成功运行过原始 WebUI,并具备以下环境:
# 推荐使用 conda 管理环境 conda activate torch28 # 核心依赖(已在 requirements.txt 中) pip install pillow gradio diffsynth-studio注意:Pillow 是图像处理库,我们将用它来添加水印。
项目目录结构解析
进入项目根目录后,关键路径如下:
Z-Image-Turbo/ ├── app/ # 主应用逻辑 │ ├── main.py # Gradio 启动入口 │ └── core/ │ ├── generator.py # 核心生成逻辑 │ └── pipeline.py # 模型加载与推理流程 ├── scripts/ # 启动脚本 ├── outputs/ # 图像输出目录 └── config.yaml # 配置文件本次开发主要修改两个文件: 1.app/core/generator.py—— 控制生成后的图像处理 2.app/main.py—— 可选地扩展前端 UI
功能目标:为生成图像自动添加水印
我们要实现的功能是:
在每张生成的图像右下角添加半透明文字水印:“Powered by Z-Image-Turbo”,字体大小适配图像尺寸,不影响主体视觉。
技术方案设计
| 组件 | 实现方式 | |------|----------| | 水印绘制 | 使用 Pillow 的ImageDraw和ImageFont| | 透明度控制 | RGBA 模式叠加图层 | | 字体选择 | 内置默认字体(若无中文字体则 fallback) | | 触发时机 | 图像生成完成后、保存前 |
步骤一:编写水印处理模块
我们在app/core/下新建一个工具模块watermark.py:
# app/core/watermark.py from PIL import Image, ImageDraw, ImageFont import os def add_watermark(image: Image.Image, text: str = "Powered by Z-Image-Turbo", opacity: float = 0.6) -> Image.Image: """ 为图像添加右下角半透明水印 Args: image: 输入图像 (PIL Image) text: 水印文本 opacity: 透明度 (0.0 ~ 1.0) Returns: 添加水印后的图像 """ # 创建透明图层 overlay = Image.new("RGBA", image.size, (0, 0, 0, 0)) draw = ImageDraw.Draw(overlay) # 计算字体大小(按图像宽度比例) font_size = max(24, int(min(image.width, image.height) * 0.03)) try: font = ImageFont.truetype("arial.ttf", font_size) # 尝试加载 Arial except IOError: font = ImageFont.load_default() # fallback 到默认字体 # 获取文本尺寸 bbox = draw.textbbox((0, 0), text, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1] # 设置位置(右下角内边距) padding = 20 position = (image.width - text_width - padding, image.height - text_height - padding) # 设置颜色和透明度 fill_color = (255, 255, 255, int(255 * opacity)) # 白色,带透明度 # 绘制文本 draw.text(position, text, font=font, fill=fill_color) # 合并原图与图层 watermarked = Image.alpha_composite(image.convert("RGBA"), overlay) return watermarked.convert("RGB") # 转回 RGB 保存步骤二:集成到生成器核心逻辑
打开app/core/generator.py,找到generate()方法,在图像保存之前插入水印处理。
修改前代码片段(示例):
# 原始逻辑:生成图像并保存 for i in range(num_images): image = pipeline(prompt, negative_prompt, width, height, num_inference_steps, seed, cfg_scale) output_path = save_image(image, output_dir) output_paths.append(output_path)修改后代码:
# 新增导入 from .watermark import add_watermark import shutil # ... def generate( prompt: str, negative_prompt: str = "", width: int = 1024, height: int = 1024, num_inference_steps: int = 40, seed: int = -1, num_images: int = 1, cfg_scale: float = 7.5, enable_watermark: bool = True # 新增参数 ) -> tuple[list[str], float, dict]: """ 生成图像并可选添加水印 """ from .pipeline import get_pipeline from .utils import save_image pipeline = get_pipeline() output_paths = [] start_time = time.time() for i in range(num_images): # 执行推理 pil_image = pipeline( prompt=prompt, negative_prompt=negative_prompt, width=width, height=height, num_inference_steps=num_inference_steps, guidance_scale=cfg_scale, seed=seed if seed != -1 else None ) # 【新增】如果启用水印,则处理图像 if enable_watermark: pil_image = add_watermark(pil_image, text="AI Generated · 科哥出品", opacity=0.7) # 保存图像 output_path = save_image(pil_image, "./outputs") output_paths.append(output_path) gen_time = time.time() - start_time metadata = {"prompt": prompt, "negative_prompt": negative_prompt} return output_paths, gen_time, metadata✅ 提示:
enable_watermark参数可通过前端传递,实现开关控制。
步骤三:扩展 WebUI 界面(可选)
为了让用户能控制是否添加水印,我们可以修改app/main.py,在界面上增加一个复选框。
修改main.py中的 Gradio 界面定义部分:
with gr.Row(): with gr.Column(): prompt = gr.Textbox(label="正向提示词", lines=3, placeholder="描述你想要的画面...") negative_prompt = gr.Textbox(label="负向提示词", lines=2, placeholder="不希望出现的内容...") # ... 其他参数组件 ... # 【新增】水印开关 enable_watermark = gr.Checkbox(label="✅ 添加水印", value=True) generate_btn = gr.Button("🎨 生成图像", variant="primary")然后将该参数传入generator.generate()调用中:
generate_btn.click( fn=lambda prompt, neg_prompt, w, h, steps, seed, count, cfg, wm: generator.generate( prompt=prompt, negative_prompt=neg_prompt, width=w, height=h, num_inference_steps=steps, seed=seed, num_images=count, cfg_scale=cfg, enable_watermark=wm # ← 传入水印开关 ), inputs=[ prompt, negative_prompt, width, height, steps, seed, count, cfg_scale, enable_watermark # 包含新参数 ], outputs=[gallery, time_cost, metadata_output] )测试验证:启动并查看效果
重新启动服务:
bash scripts/start_app.sh访问http://localhost:7860,操作步骤:
- 输入任意提示词
- 勾选“✅ 添加水印”选项
- 点击“生成图像”
观察输出图像: - 是否在右下角显示了水印? - 水印是否清晰但不过于突兀? - 图像能否正常下载?
同时尝试关闭水印功能,确认行为可切换。
💡技巧:可在
outputs/目录对比开启/关闭水印的 PNG 文件,验证逻辑正确性。
进阶优化建议
1. 自定义水印内容
可通过配置文件读取水印文本:
# config.yaml watermark: enabled: true text: "内部测试版 · 禁止外传" opacity: 0.5在generator.py中加载配置即可统一管理。
2. 支持图片 Logo 水印
使用Image.paste()叠加透明 PNG 格式的 Logo:
logo = Image.open("logo.png").convert("RGBA") image.paste(logo, position, logo) # 第三个参数作为 mask3. 性能优化:缓存字体对象
避免每次生成都重新加载字体,可在模块级别缓存:
_font_cache = {} def get_font(size): if size not in _font_cache: try: _font_cache[size] = ImageFont.truetype("arial.ttf", size) except: _font_cache[size] = ImageFont.load_default() return _font_cache[size]4. 安全增强:防止恶意输入
对水印文本做长度限制和字符过滤,避免注入攻击或异常渲染。
常见问题与解决方案
❌ 问题1:中文乱码或方块字
原因:系统缺少中文字体,truetype加载失败,fallback 到默认字体不支持中文。
解决方法: - 将simhei.ttf或NotoSansCJK-Regular.ttc放入项目目录 - 显式指定路径:
font = ImageFont.truetype("./fonts/simhei.ttf", font_size)❌ 问题2:图像变黑或通道错误
原因:RGBA 与 RGB 混合导致颜色异常。
修复:确保最终返回的是 RGB 模式:
return watermarked.convert("RGB")❌ 问题3:内存泄漏(长时间运行)
原因:Pillow 图像未及时释放。
建议:在循环结束后显式删除中间变量:
del overlay, draw, pil_image或使用上下文管理器包装。
总结:掌握二次开发的核心思路
通过本次实战,我们完成了 Z-Image-Turbo 的一次典型功能扩展。总结关键要点如下:
📌 二次开发三步法: 1.定位入口:明确功能触发点(这里是
generate()函数) 2.解耦实现:将新功能封装为独立模块(watermark.py) 3.平滑集成:通过参数化控制,保持原有接口兼容
你可以举一反三的应用场景:
- 自动生成图像描述(调用 BLIP 模型)
- 输出前调用 NSFW 检测过滤不良内容
- 上传至 OSS/S3 并返回 URL
- 记录生成日志到数据库
- 支持 Base64 输出用于 API 对接
下一步学习建议
如果你想深入 Z-Image-Turbo 的底层机制,推荐研究以下方向:
- 模型结构分析:查看
pipeline.py中如何加载 DiT 架构模型 - 加速技术原理:了解其为何能在 1~40 步内生成高质量图像
- LoRA 微调支持:尝试加载自定义风格 LoRA 模型
- 多模态扩展:结合 Qwen-VL 实现图文互生
项目源码托管于 ModelScope,欢迎 Fork 并贡献你的创意功能!
本文由科哥原创,转载请注明出处。微信交流:312088415