使用Stable Diffusion WebUI API执行img2img时图像尺寸意外缩小
问题:ControlNet Canny映射图像尺寸自动缩小,与原始尺寸不符
原始图像尺寸为(719, 899),通过SD Forge的API生成Canny映射后,返回图像尺寸变为(712, 896),即使在payload中指定了原始width和height也无效。试过调整resize_mode、移除ControlNet配置,问题依然存在。
原因分析
这是Stable Diffusion(包括Forge分支)的默认行为:SD的潜在空间基于8倍下采样的VAE模型,因此所有输入输出的图像尺寸必须是8的整数倍。你的原始尺寸719、899都不是8的倍数,API会自动向下取整到最近的8的倍数:
- 719 ÷ 8 = 89.875 → 取89×8=712
- 899 ÷ 8 = 112.375 → 取112×8=896
这就是返回图像尺寸缩小的根本原因,和ControlNet无关——即使去掉ControlNet,img2img接口依然会强制对齐尺寸到8的倍数。
解决方案
方案1:提前将原始图像调整为8的倍数
在编码为base64前,先把图像尺寸调整为8的整数倍,这样API返回的结果就会和调整后的尺寸一致:
image = Image.open(image_path) # 计算最近的8的倍数尺寸 target_width = ((image.width + 7) // 8) * 8 target_height = ((image.height + 7) // 8) * 8 # 调整图像尺寸(用LANCZOS插值保证画质) image = image.resize((target_width, target_height), Image.Resampling.LANCZOS) with io.BytesIO() as img_bytes: image.save(img_bytes, format='PNG') img_b64 = base64.b64encode(img_bytes.getvalue()).decode() # 后续payload中的width和height用调整后的尺寸 payload = { # ... 其他参数不变 "width": target_width, "height": target_height, # ... }
方案2:生成后将图像resize回原始尺寸
如果必须严格保留原始尺寸,可以在获取返回图像后,再resize回原始大小:
map_image = Image.open(io.BytesIO(base64.b64decode(r['images'][1].split(",", 1)[0]))) # resize回原始图像的尺寸 map_image = map_image.resize((image.width, image.height), Image.Resampling.LANCZOS) root, ext = os.path.splitext(image_path) basename = os.path.basename(root) save_path = os.path.join(tools_dir, "canny_dst", basename+ext) map_image.save(save_path)
额外提示
- 如果你使用的是其他SD衍生版本,倍数可能是4或16,但Forge和主流SD版本默认都是8倍。
- 尽量优先用方案1,因为提前调整尺寸比生成后再resize,画质损失更小。
内容的提问来源于stack exchange,提问作者きのこしたたけ
相关产品推荐
相关产品推荐

