用完整图片A替换图片B局部:为什么AI总会重绘,以及可行做法
把一张图里完整的物体原样搬到另一张图的指定位置,SD 局部重绘却总会把物体重画一遍。本文解释扩散模型为何保不住原始像素,给出「抠图合成 + 只在接缝低强度重绘 + 统一光影色调」的可操作流程,并说明 prompt 控制材质颜色与保留原始像素之间的取舍。
把一张图里完整的物体(记作图片 A)原样搬到另一张图(图片 B)的指定位置,不允许模型重画——这个需求在电商换模特、商品换背景、海报拼素材的场景里非常普遍。听起来像是「局部重绘」的活,但真拿 Stable Diffusion 的 inpaint 去跑,结果往往是:位置对了,东西还是被重新画了一遍,纹理、边缘、细节全都变了。
问题的根源不在参数没调好,而在于把两类完全不同的任务混为一谈:你想要的是一次合成(复制像素),模型提供的是生成(重新采样像素)。下面先说清楚为什么,再给出一条能真正保住图片 A 的流程。
为什么扩散模型留不住原始像素
1. 潜空间往返本身就有损
SD 系模型不是直接操作像素,而是先把图编码到潜空间(通常是原分辨率的 1/8),处理完再解码回来。这意味着:哪怕 denoise 设成 0,图片 A 只要进过一次模型,出来就已经不是原来那张了,高频细节会明显糊掉。所以「把 A 丢进去让模型别动它」这条路从一开始就走不通。
2. 扩散模型没有「复制」这条通路
文字大模型能精确把「张三」换成「李四」而不动其他字,是因为文本是离散 token,输出词表里就存在「李四」这个词,模型可以直接照抄。图像是连续的像素或潜变量,每一步去噪都是在重新采样,不存在「把这块像素原封不动搬过来」的机制。
所以「文字模型能做到,图像模型应该也能做到」这个类比并不成立。目前主流的多模态生图能力基本是「看懂内容 → 重新画一遍」,没有像素级复制通道;各家能力迭代很快,具体以官方最新说明为准。
3. ControlNet 是条件,不是约束
线稿、Canny、深度图这些控制手段,作用是告诉模型「大概长成这个形状」,它影响的是生成方向,并不锁定像素值。用 ControlNet 的结果通常是结构相似、细节全新——恰好是需求里最不想要的那种。
可行路线:先合成,再让 AI 只处理接缝
思路很直接:把「搬运」交给确定性的图像处理,把「融合」交给模型。模型只在一圈很窄的接缝上工作,就没有机会改掉图片 A 的主体。
第 1 步:把目标从图片 A 里干净地抠出来
- 主体清晰时用
rembg、SAM 一类的分割/抠图工具,或者 Photoshop 的主体选择。 - 输出带 alpha 通道的 PNG,边缘保留 1–2px 的半透明过渡,别做二值化硬切。
- 这一阶段保持原分辨率,不要反复缩放。
# 去背景,得到带 alpha 的抠图
rembg i object_a.png a_cut.png
第 2 步:几何对齐后贴到图片 B 上
先想清楚 A 与 B 目标区域的关系:只是位置不同(平移即可),还是有缩放、旋转、透视差异。差异越大,后面穿帮越难救。
# 缩放到目标尺寸,再按坐标贴到 B 上
magick b.png \( a_cut.png -resize 320x320 \) -geometry +480+260 -composite composited.png
from PIL import Image
b = Image.open("b.png").convert("RGBA")
a = Image.open("a_cut.png").convert("RGBA").resize((320, 320), Image.LANCZOS)
b.alpha_composite(a, (480, 260))
b.save("composited.png")
要点:一次插值完成所有变换(缩放 + 旋转 + 透视合成到同一个仿射/透视矩阵里),分多次缩放会让 A 越来越糊。
第 3 步:只在接缝环带上做低强度重绘
关键技巧是别用对象本身的蒙版,而是用「膨胀后的蒙版减去原蒙版」得到一圈环带,让重绘只发生在边界处。
import cv2, numpy as np
mask = cv2.imread("mask.png", 0) # 对象所在区域,白底黑背
kernel = np.ones((15, 15), np.uint8)
ring = cv2.dilate(mask, kernel) - mask # 只有边界环带为白
cv2.imwrite("ring_mask.png", ring)
然后把 composited.png 和 ring_mask.png 送进 inpaint:
- denoise 控制在 0.2–0.35,再高就会开始吃掉 A 的边缘。
- prompt 描述的是图片 B 的环境(光线方向、色温、材质氛围),不要描述 A 本身。
- 蒙版羽化 2–4px,避免出现一圈生硬的色边。
第 4 步:统一色调、光影和接触阴影
融合感主要来自这一步,而不是生成模型:
- 颜色匹配:Photoshop 的「图像 → 调整 → 匹配颜色」,或代码里做直方图/均值方差对齐。
- 光照方向:观察 B 的主光从哪来,给 A 补对应的高光或压暗背光面;需要改光照方向可以用重打光类工具,但同样要接受它会重绘 A。
- 接触阴影:物体落在台面/地面上的那一小块暗部和地面反射,是最容易被忽略、也最影响真实感的细节。
prompt 加材质、颜色要求,能用但要付代价
可以,但要想清楚代价:文字指令生效的前提是模型重绘,而重绘就意味着 A 的原始像素保不住,这两件事互斥。
几种折中:
- 只改局部子区域:比如只给衣服换材质,对衣服区域单独跑一次 0.4–0.5 的重绘,其余部分保持合成结果不动。
- 先合成再低强度重绘:denoise 压得很低时,prompt 对材质颜色的影响会很弱,只能做微调。
- 接受「参考而非复制」:如果其实只是要求「长得像同一个东西」,可以用参考图/主体保持类方案,让模型重新生成,但细节漂移是必然的。
几种做法怎么选
| 做法 | 能否保留 A 的原始像素 | 适用场景 | 主要代价 |
|---|---|---|---|
| 纯 inpaint 局部重绘 | 否 | 只要「差不多是那个东西」 | 细节全变 |
| img2img + ControlNet | 否 | 需要姿态、结构可控 | 仍会重绘 |
| 参考图/主体保持方案 | 否(近似) | 保持风格与主体观感 | 细节漂移 |
| 抠图 + 几何合成 + 接缝重绘 | 是 | 要求 A 原样出现 | 需要手工对齐 |
| 纯手工合成 | 是 | 数量少、要求高 | 依赖人工 |
容易翻车的细节
- 不要让 A 走一遍 img2img 往返,哪怕 denoise 为 0,VAE 编解码也会让它变糊。
- 透视角度差异过大就别硬合,A 的拍摄角度和 B 差太多时,任何融合都救不回来。
- 分辨率别倒挂,A 的清晰度显著低于目标区域大小,放大后一眼假。
- 色彩空间统一到 sRGB 再比对颜色,否则匹配结果会偏。
- 阴影方向必须和 B 一致,这是比抠图精度更影响观感的因素。
- 边缘过渡宁可多花 2px 羽化,也不要留硬边。
如果要做几十上百张的批量替换,本地机器算力吃紧或者需要长时间挂着跑,可以把这个流程放到一台长期在线的远程机器上执行(例如整台放在机房的独享 Mac,按月租用、远程连接),本地不用一直开机,具体生成速度取决于所用模型规模,需要自行实测。
小结
「用完整图片 A 替换图片 B 的局部」本质是图像合成问题,不是生成问题。只要坚持让模型远离 A 的主体、只在接缝和色调上动手,就能得到既保留原始细节、又看不出拼接痕迹的结果。反过来,如果你愿意接受模型重新生成,那就干脆放弃「原始像素」这个前提,直接用 prompt 和参考图去描述你想要的效果——两头都想要,才是这类需求最常见的失败原因。