最近在修一批 Midjourney 出图时,遇到一个很典型的问题:人物整体构图、光影、氛围都很好,但放大到 100% 之后,手指关节错位、发丝断裂、衣服边缘出现马赛克状的破碎感,甚至脸部五官出现轻微扭曲。一开始我习惯回到 Midjourney 里继续改提示词,或者让机器人“Vary(Subtle)”一遍,但效果并不稳定,改提示词改得越多,画面越容易跑偏,尤其是只想修复局部瑕疵的时候。
后来我把整个修复流程搬到了 ComfyUI 里,用一套几乎不依赖提示词的工作流,直接在本地对图片做低强度重绘和放大修复,大部分破碎细节都能被补回来。这篇文章会把我从原理到实际搭建踩过的坑完整整理出来,包含核心原理拆解、完整工作流搭建、参数调优和常见问题排查。无论你是刚接触 ComfyUI 的新手,还是已经会用 Midjourney 做图但苦于后期修复的老用户,这篇文章都能给你一套可以直接落地的方案。
1. 背景与核心概念
1.1 什么是 Midjourney 生成的“破碎细节”
所谓的“破碎细节”,并不是指某一种固定的报错或异常,而是 AI 生成图片中常见的一类质量缺陷。它通常表现为:
- 手指数量不对、关节弯曲方向不合理、手指之间粘连。
- 头发丝从中间断掉,或者大面积糊成一团。
- 衣服边缘、帽子边缘出现锯齿状破边。
- 人脸五官比例轻微错位,眼睛、嘴巴细节“融化”。
- 远处背景中的建筑、树叶变成一团不可识别的噪点。
- 图片放大后边缘出现明显的颗粒感或马赛克感。
在 Midjourney 中,这类问题出现的原因通常和生成步数、分辨率、CFG Scale、模型本身的能力边界都有关系。简单来说,扩散模型在去噪阶段可能没有足够多的“步数”去精修高频细节,或者模型在低分辨率下对某些结构的理解本身就不稳定,导致最终生成结果出现细节断裂。
1.2 为什么“提示词修复”并不总是有效
遇到破碎细节,很多人的第一反应是回到 Midjourney 修改提示词,比如加上“detailed hands”、“perfect fingers”之类的描述,然后再重新生成或重 roll。但实际操作中你会发现:
- 提示词修改后,整个画面构图可能会发生较大变化,原本满意的内容反而变了。
- Midjourney 对“手指”“细节”这类词的理解并不稳定,加词未必有正反馈。
- 有些破碎细节出现在小区域,你并不希望整张图重新生成,但提示词方式很难做到“只改局部”。
- 频繁重 roll 会浪费算力,而且不一定能复现原来的构图和风格。
所以核心痛点在于:我们希望尽量保持原图的构图、色彩、人物特征不变,只把破碎的局部细节补全或修整。这种情况下,纯提示词方案并不是最优解,更好的方式是在本地图生图工具里做“低程度重绘”。
1.3 免提示词修复的整体思路
“免提示词”并不是说完全不需要任何文本信息,而是指在修复阶段我们不再依赖自然语言描述画面内容。具体思路是:
- 使用 ComfyUI 加载同一个或相近风格的底模型。
- 将 Midjourney 生成的图片作为输入图,通过 VAE 编码到潜在空间。
- 使用 KSampler 对潜在空间表示做一次低强度重绘。
- 通过设置较低的 denoise 强度,让模型在保留原图整体结构的前提下,重新“润色”细节。
- 最后通过放大模型进一步增强清晰度,修复破碎感。
在这个流程中,提示词甚至可以留空,因为图片本身已经包含了足够的语义信息。模型只需要参考原图的颜色、结构、光影,对局部高频细节进行补全即可。
2. 免提示词修复的原理拆解
2.1 扩散模型与图生图重绘
扩散模型生成图片的过程,本质上是从一个随机噪声图开始,一步步去噪,最终还原出符合文字描述的画面。在训练时,模型学会的是“如何把带噪声的图像还原成清晰图像”。
当我们使用图生图功能时,输入图片先被编码到潜在空间,再加上一定程度的噪声,然后由模型执行去噪过程。这一步去噪的强度,决定了最终结果是更接近原图,还是更接近一次全新生成。
这就是为什么“低 denoise 值”可以修复细节:模型并没有重新设计整张图,它只是在原有信息基础上,对模糊、破损、不合理的部分做了重新推断和补全。
2.2 为什么空文本也能完成修复
在图生图修复场景中,提示词的作用是引导模型“画什么”。但当我们已经提供了一张完整图片时,模型可以从图片本身的潜在表示中获取足够的语义信息。此时即使 CLIP Text Encode 的文本为空字符串,模型的注意力依然会被原图的色彩、轮廓和构图吸引。
从原理上看,图片经过 VAE 编码后得到的 latent,已经包含了丰富的内容信息。低 denoise 重绘时,模型接收到的 latent 与原始图高度相似,它会在这个近似分布上做小幅度修正,而不是从零开始生成。所以“免提示词”是可行的,它依赖的是图像本身的条件约束。
2.3 关键参数:denoise、CFG、steps
在 ComfyUI 的 KSampler 节点中,有三个参数对修复效果影响最大:
| 参数 | 作用 | 修复建议 |
|---|---|---|
| denoise | 重绘强度,0 表示完全不变,1 表示完全重新生成 | 0.45 - 0.65 |
| CFG | 提示词引导强度,越高越接近 prompt | 4 - 8 |
| steps | 采样步数,越高细节越充分,但速度越慢 | 20 - 35 |
denoise 是整个修复工作的灵魂参数。它越高,模型对原图的改动越大;它越低,原图保留得越完整,但修复能力也会变弱。日常修复破碎细节,建议先从 0.55 开始尝试。若原图破损严重,可以提高到 0.65 左右;若只是轻微模糊,可以降到 0.4 左右。
CFG 建议不要设置太高,过高会导致颜色过饱和、细节锐化过度,反而加重“塑料感”和破碎感。CFG 在 5-7 之间是比较安全的区间。
3. 环境准备:从零搭建 ComfyUI
3.1 ComfyUI 安装方式
ComfyUI 是一个基于节点的 Stable Diffusion 工作流工具,它以流程图的方式组织模型加载、采样、解码、保存等过程。安装主要有两种方式,你可以根据自己的基础选择。
方式一:使用秋叶一键整合包
这种方式适合新手。整合包通常已经预装好了 Python 环境、依赖、常用插件和模型管理器,下载解压后即可运行。你只需要运行启动脚本,等待浏览器自动打开 ComfyUI 页面。需要注意,整合包版本更新较快,安装后建议先确认内置的 ComfyUI 版本和自定义节点版本,再继续后面的操作。
方式二:使用官方源码安装
适合有一定基础、希望自己控制环境依赖的开发者。基本步骤如下:
- 克隆 ComfyUI 官方仓库到本地。
- 创建 Python 虚拟环境并安装 PyTorch 等依赖。
- 启动 ComfyUI 主程序。
- 在浏览器访问
http://127.0.0.1:8188。
无论采用哪种方式,最终运行起来的界面都是一个节点式工作台。
3.2 模型与插件准备
要做“免提示词修复”,你需要先准备以下资源:
- 底模型:建议下载一个写实类或通用类大模型,例如 DreamShaper、Realistic Vision、majicMIX realistic 等。修复 Midjourney 人像图时,选一个偏写实的模型效果更自然。
- VAE:大多数底模型已经内置了 VAE,如果单独下载了 VAE,也需要放到 models/vae 目录。
- 放大模型:为了修复细节纹理,可以准备 RealESRGAN_x4plus、4x-UltraSharp 等放大模型,放在 models/upscale_models 目录。
- ControlNet(进阶可选):如果你希望结构保持更强,可以下载 ControlNet Tile 模型,例如
control_v11f1e_sd15_tile.pth,放在 models/controlnet 目录。SDXL 用户则可以使用对应的 tile_xl 模型。
3.3 硬件与版本建议
ComfyUI 对硬件有一定要求,建议 NVIDIA 显卡,显存不低于 8GB。如果你的显卡显存较小,可以降低输入图片分辨率,或者开启 tiled VAE 来避免显存溢出。
ComfyUI 版本迭代很快,不同版本的节点名称、参数细节可能有差异。本文中的示例以常见版本为例,重点演示配置思路。如果你导入工作流时提示缺少节点或参数不匹配,请根据实际版本进行微调。
4. 完整实战:搭建免提示词修复工作流
4.1 工作流整体流程
下面用文字流程图来说明工作流的主要逻辑:
Midjourney 原图 ↓ Load Image 加载图片 ↓ VAE Encode 编码到潜空间 ↓ KSampler 低强度重绘(denoise≈0.55) ↓ VAE Decode 解码回像素空间 ↓ Upscale 放大增强细节 ↓ Save Image 保存结果其中,CLIP Text Encode 两个节点的文本都留空,作为 positive 和 negative 条件传入 KSampler,这是“免提示词”的关键实现方式。
4.2 手动搭建工作流核心步骤
第一次使用时,不建议直接导入别人的工作流,手动搭一遍能帮你理解每个节点的作用,后面调参时会更有手感。
第一步:删除默认节点
打开 ComfyUI 后,按Ctrl + A全选当前画布中的节点,按Delete删除,得到一个空白画布。
第二步:添加 CheckpointLoaderSimple
在画布空白处双击,弹出节点搜索框,输入CheckpointLoaderSimple,回车添加。这个节点负责加载底模型。在节点的下拉框中,选择你已经放入models/checkpoints目录的模型文件。
这个节点会输出三路信息:MODEL、CLIP、VAE。MODEL 是采样用的模型本体,CLIP 用于文本编码,VAE 用于图像和潜在空间互转。
第三步:添加 LoadImage
搜索并添加LoadImage节点。点击节点上的“choose file to upload”,选择 Midjourney 生成的原图。节点会输出 IMAGE 数据,同时你可以在图片预览中看到原始画面。
第四步:添加 VAEEncode
搜索并添加VAEEncode节点。将 LoadImage 的 IMAGE 输出连接到 VAEEncode 的 pixels 输入;将 CheckpointLoaderSimple 的 VAE 输出连接到 VAEEncode 的 vae 输入。这个节点会把像素空间的图片编码到潜在空间,供 KSampler 处理。
第五步:添加两个空文本 CLIPTextEncode
搜索并添加两个CLIPTextEncode节点,分别作为 positive 和 negative 条件。将 CheckpointLoaderSimple 的 CLIP 输出连接到两个节点的 clip 输入。两个节点的 text 输入框都设为空字符串。
注意:不要删除这两个节点,虽然提示词为空,但 KSampler 需要接收条件数据。
第六步:添加 KSampler
搜索并添加KSampler节点,然后完成下述连接:
- model 输入接 CheckpointLoaderSimple 的 MODEL 输出。
- positive 接第一个 CLIPTextEncode 的 CONDITIONING 输出。
- negative 接第二个 CLIPTextEncode 的 CONDITIONING 输出。
- latent_image 接 VAEEncode 的 LATENT 输出。
参数可以按下表设置:
| 参数名 | 建议值 | 说明 |
|---|---|---|
| seed | 42 | 随机种子,可随意 |
| control_after_generate | randomize | 每次运行随机种子 |
| steps | 25 | 采样步数 |
| cfg | 6.0 | 提示词引导强度 |
| sampler_name | dpmpp_2m | 采样器 |
| scheduler | karras | 调度器 |
| denoise | 0.55 | 重绘强度 |
第七步:添加 VAEDecode
搜索并添加VAEDecode节点。将 KSampler 的 LATENT 输出连接到 VAEDecode 的 samples 输入,将 CheckpointLoaderSimple 的 VAE 输出连接到 VAEDecode 的 vae 输入。VAEDecode 会把修复后的潜在表示重新解码为图片。
第八步:添加 SaveImage
搜索并添加SaveImage节点。将 VAEDecode 的 IMAGE 输出连接到 SaveImage 的 images 输入。SaveImage 的 filename_prefix 可以改成fix_detail,运行后图片会保存到ComfyUI/output目录。
到这里,一个最基础的“免提示词修复工作流”已经搭好。
4.3 可复用的工作流 JSON 模板
如果你希望跳过手动搭建,也可以通过 ComfyUI 的 API 接口直接提交工作流。下面是一个最小可运行的 API 格式 JSON 模板,逻辑与手动搭建一致。
{ "1": { "class_type": "CheckpointLoaderSimple", "inputs": { "ckpt_name": "dreamshaper_8.safetensors" } }, "2": { "class_type": "LoadImage", "inputs": { "image": "broken_face.png" } }, "3": { "class_type": "VAEEncode", "inputs": { "pixels": ["2", 0], "vae": ["1", 2] } }, "4": { "class_type": "CLIPTextEncode", "inputs": { "text": "", "clip": ["1", 1] } }, "5": { "class_type": "CLIPTextEncode", "inputs": { "text": "", "clip": ["1", 1] } }, "6": { "class_type": "KSampler", "inputs": { "model": ["1", 0], "positive": ["4", 0], "negative": ["5", 0], "latent_image": ["3", 0], "seed": 42, "steps": 25, "cfg": 6.0, "sampler_name": "dpmpp_2m", "scheduler": "karras", "denoise": 0.55 } }, "7": { "class_type": "VAEDecode", "inputs": { "samples": ["6", 0], "vae": ["1", 2] } }, "8": { "class_type": "SaveImage", "inputs": { "images": ["7", 0], "filename_prefix": "fix_detail" } } }使用前需要修改两处:ckpt_name改成你本机 checkpoints 目录下实际存在的模型文件名;image改成你放进ComfyUI/input目录的图片文件名。保存为fix_workflow_api.json后,可以通过以下命令提交给本地 ComfyUI:
curl -X POST http://127.0.0.1:8188/prompt \ -H "Content-Type: application/json" \ -d @fix_workflow_api.json如果你习惯在界面上操作,也可以把工作流通过界面菜单保存为.json文件,下次直接拖入浏览器即可加载。
4.4 运行与参数验证
在 ComfyUI 界面中点击右上角的Queue Prompt,任务开始运行。运行完成后,SaveImage 节点会显示输出图片,同时ComfyUI/output目录下会生成带前缀fix_detail的图片文件。
第一轮运行后,建议先对比原图与修复图,重点观察:
- 手指是否更加自然。
- 发丝是否变得连贯。
- 边缘破碎感是否减少。
- 整体构图、色彩是否被保留。
如果修复力度不足,也就是图片几乎没有变化,请逐步调高 denoise,每次增加 0.05,直到细节有明显改善。如果图片已经完全偏离原图,则说明 denoise 过高,请回调到 0.5 以下,或者降低 CFG。
5. 进阶:局部重绘、放大与 ControlNet 组合修复
5.1 使用遮罩进行局部修复
很多时候,我们并不需要整张图重绘,只需要修复脸部或手部这些局部区域。此时可以使用遮罩局部修复。
思路是把“整图低强度重绘”改成“只在遮罩区域重绘”:
- 使用 LoadImage 节点加载原图。
- 在 LoadImage 节点上打开 mask 编辑器,用画笔涂抹需要修复的区域。
- 添加 VAEEncode 将图片编码为 latent。
- 添加
Set Latent Noise Mask节点,把 VAEEncode 的 LATENT 和 LoadImage 的 MASK 输入进去。 - 将 Set Latent Noise Mask 的输出连接到 KSampler 的 latent_image。
在这种模式下,denoise 可以适当调高到 0.6-0.75,因为模型只会在遮罩区域内生成新内容,不会破坏遮罩外的画面。局部修复的优点是非常精准,适合只修手部、脸部等局部破碎。
5.2 加入 ControlNet Tile 增强结构保持
ControlNet Tile 模型的作用是“参考原图结构,生成细节”,非常适合修复破碎纹理。它会把原图分成多个小块,作为结构参考传给模型,让模型在生成时保持原有的空间布局,同时补全高频细节。
添加 ControlNet 的流程大致如下:
- 安装 ComfyUI 的 ControlNet 相关插件。
- 将 Tile 模型放入
models/controlnet目录。 - 添加
ControlNetLoader节点,选择control_v11f1e_sd15_tile.pth。 - 添加
ControlNetApplyAdvanced节点。 - 将原图 IMAGE 连接到 ControlNetApplyAdvanced 的 image 输入。
- 将 positive 和 negative 条件连接到对应输入。
- 将 ControlNetApplyAdvanced 的 positive 和 negative 输出连接到 KSampler。
- KSampler 的 latent_image 仍然连接 VAEEncode 的 latent。
加入 ControlNet 后,即使 denoise 稍微调高,画面结构也不容易跑偏,修复纹理的能力会明显增强。适合处理复杂的建筑背景、密集纹理衣物、大幅度破碎区域。
5.3 多阶段修复生产流
在实际项目中,单次修复往往很难一步到位。更推荐的做法是分阶段处理:
- 第一阶段:整体低 denoise 重绘,修复大部分破碎边缘。
- 第二阶段:对脸部、手部做局部遮罩修复,强化细节。
- 第三阶段:使用 Upscale 放大模型提升分辨率,让纹理更清晰。
三个阶段可以组合成一张更大的工作流画布,也可以分开保存成三个模板。批量处理时,前三阶段都使用相同的输入图,最后统一输出,能有效提高出图质量。
6. 常见问题与排查思路
在实际使用 ComfyUI 时,新手经常会遇到一些环境或节点层面的问题。下面是我整理的高频问题排查表:
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| 导入工作流提示缺少自定义节点 | 工作流使用了你未安装的插件 | 根据提示信息安装对应自定义节点,或改为手动搭建基础工作流 |
| 提示“请安装缺失的包以使用此工作流” | Python 依赖缺失 | 在 ComfyUI 所在 Python 环境中运行提示中给出的 pip 安装命令 |
| 生成结果几乎没变化 | denoise 过低或节点连接错误 | 检查 denoise 是否在 0.45 以上,检查 latent 链路是否打通 |
| 生成结果完全变成另一张图 | denoise 过高或 CFG 过高 | 将 denoise 降到 0.5 附近,CFG 降到 5-7 |
| 颜色与原图严重不一致 | VAE 不匹配或 denoise 过高 | 确认 VAE 与底模型匹配,优先使用单一底模型自带 VAE |
| 显存不足 OOM | 分辨率过大、模型过大 | 降低输入分辨率,开启 tiled VAE,或使用 FP16 加载 |
| 运行速度极慢 | steps 过高、模型过大 | 降低 steps 到 25 左右,使用 xformers 等优化加速 |
| 脸部五官依然扭曲 | 局部区域信息不足 | 对脸部使用局部遮罩重绘,并考虑使用 ControlNet 约束 |
| 修复后画面太糊 | 没有加放大模型 | 在输出前增加 Upscale 放大节点,或先放大再重绘 |
如果你遇到了表格中没有列出的问题,建议先查看 ComfyUI 的控制台日志,日志中通常会直接提示是哪个节点、哪个文件或哪个依赖出了问题。
7. 最佳实践与工程建议
7.1 输入图尽量高分辨率
Midjourney 输出图的分辨率如果较低,细节信息本身就不足,修复空间有限。建议在 Midjourney 阶段先使用 Upscale 功能或放大参数,导出更高分辨率的原图,再进入 ComfyUI 修复。低分辨率图直接修复,容易越修越糊。
7.2 建立自己的参数调整起点
每次修复不要同时调整多个参数,建议固定一个变量,只调一项。例如先固定 CFG=6、steps=25,只调整 denoise,观察不同强度下的效果。等确定 denoise 之后,再微调 CFG 和 steps。这样能快速找到适合某类图片的参数组合。
7.3 做好工作流模板管理
ComfyUI 的工作流文件本质上是 JSON,非常方便版本管理。建议把常用的修复流程保存为独立模板,并按照用途命名,例如:
fix_detail_whole_v1.jsonfix_detail_face_mask_v1.jsonfix_detail_tile_controlnet_v1.json
后续如果 ComfyUI 升级导致节点变化,也方便对照旧模板查找差异。
7.4 注意显存和批处理效率
批量修复多张图时,建议使用较小的分辨率跑第一轮筛选,最终满意的图片再做高分辨率放大修复。不要一上来就对全部图片跑高分辨率,否则显存和时间成本都会比较高。此外,批量处理时文件名前缀尽量带上批次信息,避免输出目录中文件名覆盖。
7.5 合法合规使用生成内容
无论是 Midjourney 还是 ComfyUI 修复流程,都应遵守模型的使用协议和平台规则。不要在未经授权的情况下处理他人作品,也不要将修复结果用于侵权、诈骗等非法用途。
8. 总结
修复 Midjourney 破碎细节的关键,不是去背一套固定的参数,而是理解 denoise、CFG、ControlNet 三者之间的关系。denoise 控制修复强度,CFG 控制语义引导强度,ControlNet 控制结构保持程度。三者配合得当,才能真正实现“只修细节、不动构图”。
我建议你先按本文第四节的基础工作流跑通一次,手动搭建一遍,理解每个节点的作用。然后再根据自己的实际图片,尝试局部遮罩修复和 ControlNet Tile 修复。等你把这条链路走熟之后,以后遇到 Midjourney 出图细节崩坏,就能直接在 ComfyUI 里精准修复,不用再靠反复修改提示词碰运气了。