一、SD 图生图底层原理(潜空间 Img2Img)
SD 的图生图本质,不是直接在像素图片上修改,而是在 VAE 压缩后的 4× 下采样潜空间(Latent Space)做可控去噪。完整链路:
- 输入 RGB 原图 → 归一化、通道对齐、尺寸对齐;
- VAEEncode 编码器:把像素图压缩为
[B,4,H/4,W/4]的潜张量,保留构图、姿态、物体位置、光影轮廓,丢弃高频像素细节; - 向潜张量混入高斯噪声,混入比例由
denoising_strength(重绘幅度)控制; - CLIP 文本编码器将正负提示词转为文本条件 Embedding 向量,作为采样引导信号;
- KSampler 在潜空间迭代去噪:从带噪潜数据,按照提示词条件逐步还原潜图像;
- VAEDecode 解码器:将去噪完成的潜张量还原回 RGB 像素图像输出。
核心变量 denoising_strength 是整套工作流的控制核心,区间划分对应生产场景:
- 0.1 ~ 0.3:低重绘,几乎锁定原图结构;适合瑕疵修复、光影微调、质感润色,短剧画面微调、人脸修复;
- 0.4 ~ 0.6:黄金生产区间;保留构图、人物位置,替换画风、色调、服饰,是漫剧迭代最常用区间;
- 0.6 ~ 0.8:高改写;原图仅保留基础构图,大幅度更换场景、画风;
- 0.8 ~ 0.95:强参考;构图大概率变动,提示词权重更高;
- 1.0:等价文生图,原图仅用来锁定分辨率,丢失全部原图信息。
很多新手误区:降噪强度不等于画质,降噪强度只控制 “给原图潜数据加多少噪声”;采样步数、CFG、采样器才控制画面精细度。
二、网盘配套工作流节点链路拆解
网盘内 JSON 为 ComfyUI 标准可视化工作流格式(带节点坐标布局,拖拽进 ComfyUI 即可加载),节点连接顺序如下:
CheckpointLoaderSimple(加载SD大模型,输出 MODEL / CLIP / VAE) ├─ CLIPTextEncode(正向提示词,CLIP输入 → CONDITION) ├─ CLIPTextEncode(反向提示词,CLIP输入 → CONDITION) └─ VAE → VAEEncode 的 vae输入槽 LoadImage(上传参考原图,image输出) └─ VAEEncode(image输入,vae来自Checkpoint;输出 latent_image 给KSampler) KSampler ├─ model:Checkpoint MODEL ├─ positive:正向CLIP条件 ├─ negative:反向CLIP条件 ├─ latent_image:VAEEncode输出潜图 ├─ seed、steps、cfg、sampler_name、scheduler、denoising_strength 参数组 └─ latent输出 → VAEDecode VAEDecode ├─ samples:KSampler潜输出 ├─ vae:Checkpoint VAE └─ image输出 → SaveImage 保存节点
依赖清单(导入报错优先检查)
这套是原生基础节点,不需要额外自定义节点,仅依赖基础 SD 模型:
- SD1.5 / SDXL 基础 Checkpoint(
.safetensors)放入models/checkpoints - VAE:优先使用模型自带 VAE,或者单独 vae 文件放入
models/vae
如果后续扩展 ControlNet、IP-Adapter,再安装对应自定义节点(ComfyUI Manager 一键安装)
三、API 格式工作流 JSON(可直接用于接口提交)
注意区分:网盘里是【可视化工作流 JSON(带布局坐标)】,下面是【API 导出 JSON】,没有布局信息,适合代码调用;在 ComfyUI 菜单:文件 → 导出工作流 (API) 得到同格式文件ComfyUI。
{ "3": { "class_type": "KSampler", "inputs": { "seed": 12345, "steps": 25, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoising_strength": 0.5, "model": ["4", 0], "positive": ["6", 0], "negative": ["7", 0], "latent_image": ["10", 0] } }, "4": { "class_type": "CheckpointLoaderSimple", "inputs": { "ckpt_name": "v1-5-pruned-emaonly.safetensors" } }, "6": { "class_type": "CLIPTextEncode", "inputs": { "text": "masterpiece, best quality, anime style, beautiful girl, soft lighting", "clip": ["4", 1] } }, "7": { "class_type": "CLIPTextEncode", "inputs": { "text": "worst quality, low quality, blurry, deformed, extra limbs, watermark", "clip": ["4", 1] } }, "10": { "class_type": "VAEEncode", "inputs": { "pixels": ["11", 0], "vae": ["4", 2] } }, "11": { "class_type": "LoadImage", "inputs": { "image": "input_ref.png" } }, "12": { "class_type": "VAEDecode", "inputs": { "samples": ["3", 0], "vae": ["4", 2] } }, "13": { "class_type": "SaveImage", "inputs": { "images": ["12", 0], "filename_prefix": "img2img_out" } } }
四、Python 自动化批量图生图脚本(生产可用)
功能说明:
- 遍历
./input文件夹下所有 png/jpg 参考图; - 动态替换工作流内 LoadImage、提示词、denoise 参数;
- 提交 ComfyUI 本地 API(默认地址
http://127.0.0.1:8188); - 轮询任务状态,生成完成后读取图片二进制,保存到
./output; - 单图失败自动跳过,打印日志,适合漫剧、短剧批量迭代画面。
前置依赖安装:
pip install requests pillow
完整代码:
import requests import json import os import time from PIL import Image from io import BytesIO COMFY_API_URL = "http://127.0.0.1:8188" INPUT_DIR = "./input" OUTPUT_DIR = "./output" os.makedirs(INPUT_DIR, exist_ok=True) os.makedirs(OUTPUT_DIR, exist_ok=True) # 基础工作流模板,和上面API JSON对应 BASE_WORKFLOW = { "3": { "class_type": "KSampler", "inputs": { "seed": 12345, "steps": 25, "cfg": 7.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoising_strength": 0.5, "model": ["4", 0], "positive": ["6", 0], "negative": ["7", 0], "latent_image": ["10", 0] } }, "4": { "class_type": "CheckpointLoaderSimple", "inputs": { "ckpt_name": "v1-5-pruned-emaonly.safetensors" } }, "6": { "class_type": "CLIPTextEncode", "inputs": { "text": "masterpiece, best quality, anime, soft color, detailed face", "clip": ["4", 1] } }, "7": { "class_type": "CLIPTextEncode", "inputs": { "text": "worst quality, lowres, blurry, bad anatomy, ugly, watermark", "clip": ["4", 1] } }, "10": { "class_type": "VAEEncode", "inputs": { "pixels": ["11", 0], "vae": ["4", 2] } }, "11": { "class_type": "LoadImage", "inputs": { "image": "" } }, "12": { "class_type": "VAEDecode", "inputs": { "samples": ["3", 0], "vae": ["4", 2] } }, "13": { "class_type": "SaveImage", "inputs": { "images": ["12", 0], "filename_prefix": "img2img_batch" } } } def upload_image(file_path): """上传本地图片到ComfyUI服务端,返回服务端内文件名""" with open(file_path, "rb") as f: res = requests.post(f"{COMFY_API_URL}/upload/image", files={"image": f}) return res.json()["name"] def submit_workflow(workflow): payload = {"prompt": workflow} r = requests.post(f"{COMFY_API_URL}/prompt", json=payload) return r.json()["prompt_id"] def wait_for_result(prompt_id): while True: history = requests.get(f"{COMFY_API_URL}/history").json() if prompt_id in history: return history[prompt_id] time.sleep(0.5) def save_output(history_data, out_name): outputs = history_data["outputs"] for node_id, node_out in outputs.items(): if "images" in node_out: for img_info in node_out["images"]: img_data = requests.get(f"{COMFY_API_URL}/view", params=img_info).content with open(os.path.join(OUTPUT_DIR, out_name), "wb") as f: f.write(img_data) print(f"✅ 已保存:{out_name}") def batch_run(denoise=0.5): img_list = [f for f in os.listdir(INPUT_DIR) if f.lower().endswith(("png","jpg","jpeg"))] for fname in img_list: full_path = os.path.join(INPUT_DIR, fname) print(f"\n🚀 处理图片:{fname}") try: server_img_name = upload_image(full_path) wf = json.loads(json.dumps(BASE_WORKFLOW)) wf["3"]["inputs"]["denoising_strength"] = denoise wf["11"]["inputs"]["image"] = server_img_name pid = submit_workflow(wf) res_data = wait_for_result(pid) save_output(res_data, f"out_{fname}") except Exception as e: print(f"❌ {fname} 处理失败:{str(e)}") if __name__ == "__main__": # 修改denoise参数适配你的业务 batch_run(denoise=0.5)
使用说明
- 启动 ComfyUI 本地服务;
- 在项目新建
input文件夹,放入你的参考原图; - 修改脚本内
ckpt_name、正负提示词、denoise; - 运行脚本,成品自动输出到
output。
五、生产调优踩坑指南(短剧漫剧高频问题)
- 人物面部崩坏:denoise 高于 0.6 容易出现;方案:降低 denoise 到 0.4 以内,搭配 FaceDetailer 后置人脸修复节点;
- 画面饱和度异常、偏色:优先使用模型原生 VAE,不要混用不匹配 VAE;SDXL 和 SD1.5 的 VAE 不可互通;
- 构图乱跑、物体移位:denoise 过高是主因;如果需要高改写同时锁构图,在 VAEEncode 之后接入 ControlNet-Canny/OpenPose;
- 同提示词每次出图不一样:固定 seed 可以锁定结果;批量生产测试时固定 seed,上线批量生成再随机 seed;
- 网盘工作流导入后节点红色报错:90% 是 Checkpoint 名称不一致,打开 CheckpointLoaderSimple 节点,下拉选择你本地已有的模型名称。
六、扩展升级方向(基于本底层工作流)
这套原生 Img2Img 是基座,可以直接链式叠加:
- 增加 ControlNet:Canny 线稿锁轮廓、OpenPose 锁人物姿态、Depth 锁空间;
- 增加 IP-Adapter:风格图参考,不改变构图前提下统一画风;
- 增加 Tile 分块高清修复:低分辨率原图输入,输出 2K 大图;
- 接入 Flux、SDXL 模型:替换 Checkpoint 即可,潜空间 Img2Img 链路逻辑不变;
- 封装成漫剧流水线:配合字幕节点、批量角色 Lora,实现连续镜头统一角色。