
如何读懂图像修复提速插件源码ComfyUI-Inpaint-CropAndStitch 裁剪与拼接机制全解析【免费下载链接】ComfyUI-Inpaint-CropAndStitchComfyUI nodes to crop before sampling and stitch back after sampling that speed up inpainting项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Inpaint-CropAndStitch高分辨率图像的局部修复为什么非要让模型把整张图重新采样一遍ComfyUI-Inpaint-CropAndStitch 用先裁剪、后拼接的思路给出了答案只把掩码周围的最小必要区域交给采样器再将结果无缝回贴图像修复因此提速数倍到数十倍。本文沿着痛点→架构→机制→实战的线索拆解这个插件最核心的设计决策与代码落地。一个真实的痛点修复 5% 的面积却付出 100% 的算力假设我们拿到一张 4K 人像只想修掉脸上的一颗痘痘。传统工作流会把整张 4K 图送入 VAE 编码、整图采样、再解码——显存瞬间告急单次迭代动辄几十秒而真正需要模型操心的只有那一小片掩码区域。更麻烦的是修复区域在画面中占比越小模型越要花大量计算去保持那些根本不该被改动的背景。这个项目的核心思路可以浓缩成一句话采样前把图像裁剪到恰好够用采样后再把结果精确拼回去。裁剪决定了模型能看到多少上下文拼接决定了最终图像能否天衣无缝。接下来我们看这两件事在代码里是怎么落地的。架构总览两个节点、一个抽象处理器打开inpaint_cropandstitch.py整体结构非常清晰InpaintCropImproved负责裁InpaintStitchImproved负责拼二者通过自定义类型STITCHER传递元数据底层的图像算子则被抽象成一个策略接口由 CPU 与 GPU 两套实现分别提供。# inpaint_cropandstitch.py · ProcessorLogic 抽象基类节选 class ProcessorLogic(ABC): abstractmethod def rescale_i(self, samples, width, height, algorithm: str): ... # 图像缩放 abstractmethod def rescale_m(self, samples, width, height, algorithm: str): ... # 掩码缩放 abstractmethod def expand_m(self, samples, pixels): ... # 掩码膨胀 abstractmethod def blur_m(self, samples, pixels): ... # 掩码模糊 abstractmethod def crop_magic_im(self, image, mask, x, y, w, h, ...): ... # 智能裁剪 abstractmethod def stitch_magic_im(self, canvas_image, inpainted_image, mask, ...): ...CPUProcessorLogic基于 PIL scipy.ndimage 实现兼容性最好GPUProcessorLogic基于 torch 实现官方实测可带来 30~100 倍提速。节点在运行时根据device_mode选择实现上层业务逻辑完全无感知——这正是策略模式的价值算法可以替换流程不用改。值得注意的设计是stitcher这个字典它把画布图像、裁剪框相对画布的坐标cropped_to_canvas_*、画布相对原图的坐标canvas_to_orig_*、用于融合的掩码以及缩放算法全部打包。采样环节被断开后无论你接的是普通 KSampler、ControlNet 还是 HiRes 放大链路只要最后把inpainted_image喂回 Stitch 节点它就能凭这些坐标把结果放回原位。关键机制一裁剪框是怎么长出来的那么问题来了这个裁剪区域到底怎么计算直接框住掩码显然不够——模型需要周围背景作为语义上下文。crop_magic_im的核心逻辑分三步先找到掩码包围盒 → 按目标宽高比拉伸 → 越界时扩展画布。# inpaint_cropandstitch.py · CPUProcessorLogic.crop_magic_im节选 target_aspect_ratio target_w / target_h context_aspect_ratio w / h if context_aspect_ratio target_aspect_ratio: # 上下文太瘦加宽到目标比例 new_w int(h * target_aspect_ratio) new_h h new_x x - (new_w - w) // 2 new_y y # 越界优先整体平移放不下再居中溢出 if new_x 0: shift -new_x new_x new_x shift if new_x new_w shift image_w else -((new_w - image_w) // 2) elif new_x new_w image_w: overflow new_x new_w - image_w new_x new_x - overflow if new_x - overflow 0 else -((new_w - image_w) // 2) else: # 上下文太扁加高到目标比例new_y 的校正逻辑对称 new_w w new_h int(w / target_aspect_ratio) new_x x new_y y - (new_h - h) // 2这段代码解释了几个关键设计决策为什么按比例拉伸而不是直接缩放裁剪区域必须保持模型输入的目标宽高比比如 SDXL 的 1024×1024否则采样器会二次缩放导致内容变形。代码以掩码中心为锚点向两侧均匀扩展保证掩码始终居中。越界校正为什么要先平移、后溢出理想情况下裁剪框应完全落在图像内只有掩码本身贴着图像边缘、实在无法满足比例时才允许裁剪框部分伸出画布。这一策略避免了旧版本围绕掩码居中、动不动就越界的算力浪费。伸出画布的部分怎么处理后续步骤会把画布按需扩展新区域用边缘像素复制edge-replicate填充而非镜像。镜像会让边界出现语义上不可能存在的内容容易误导模型。关键机制二掩码管道参数这样设计的原因在计算裁剪框之前掩码还要经过一条完整的处理管道顺序是preresize → fill_holes → expand → invert → blend(expandblur) → hipass → extend_for_outpainting。这条顺序本身就是设计参数作用设计意图mask_fill_holes填充掩码内部闭合空洞蒙版画笔常留下漏涂的灰色缝隙mask_expand_pixels按像素膨胀掩码让修复区域覆盖到掩码边缘的过渡带mask_invert反转掩码一键切换擦除/保留两种用法mask_blend_pixels膨胀并模糊融合掩码生成渐变过渡回贴时无接缝mask_hipass_filter忽略低于阈值的掩码值过滤近乎纯黑如 0.01的误涂像素这里最容易踩坑的是mask_hipass_filter人的肉眼分辨不出 0.01 和 0 的区别但算法会把任何非零值都当成掩码。默认值 0.1 的意义就是把看起来没涂的噪点直接归零。另一个容易被低估的是mask_blend_pixels它在裁剪阶段先用expand_m放大掩码、再用blur_m模糊产生一个带软边的融合掩码存入 stitcher——拼接阶段的无缝正是靠它实现的。关键机制三拼接——掩码线性混合的艺术拼接发生在stitch_magic_im里代码短小但值得逐行读# inpaint_cropandstitch.py · CPUProcessorLogic.stitch_magic_im节选 # 1) 修复结果先缩放回上下文区域的实际尺寸 if ctc_w w or ctc_h h: resized_image self.rescale_i(inpainted_image, ctc_w, ctc_h, upscale_algorithm) resized_mask self.rescale_m(mask, ctc_w, ctc_h, upscale_algorithm) else: resized_image self.rescale_i(inpainted_image, ctc_w, ctc_h, downscale_algorithm) resized_mask self.rescale_m(mask, ctc_w, ctc_h, downscale_algorithm) resized_mask resized_mask.clamp(0, 1).unsqueeze(-1) # [B,H,W] - [B,H,W,1] canvas_crop canvas_image[:, ctc_y:ctc_yctc_h, ctc_x:ctc_xctc_w] # 2) 线性混合掩码内取修复图掩码外保留原画布 blended resized_mask * resized_image (1.0 - resized_mask) * canvas_crop # 3) 回贴画布再按 canvas_to_orig 坐标裁出原图区域 canvas_image[:, ctc_y:ctc_yctc_h, ctc_x:ctc_xctc_w] blended output_image canvas_image[:, cto_y:cto_ycto_h, cto_x:cto_xcto_w]三个设计点值得品味缩放方向决定算法放大用upscale_algorithm默认 bicubic缩小用downscale_algorithm默认 bilinear。因为修复图可能经过 HiRes 放大尺寸与裁剪框不一致这里必须做一次逆向缩放。混合公式天然保护未掩码区当掩码值为 0 时结果完全等于画布原像素也就是说未掩码区域根本不会被改动甚至不需要经过 VAE 编码解码。这正是它能避免整图重采样的根本原因。坐标精度即拼接精度旧版本曾因坐标换算误差出现 1 像素位移。现在裁剪阶段就把cto画布→原图与ctc裁剪→画布两套坐标一次性算好、随 stitcher 传递拼接时直接取用从源头消除了二次换算的漂移。关键机制四GPU 处理器的性能密码既然 CPU 实现已经能工作为什么还要单独写一套 GPU 实现答案藏在两个算子里。以掩码膨胀为例CPU 版用 scipy 的grey_dilation逐张处理GPU 版则用一个数学技巧最大池化等价于方形核膨胀。# inpaint_cropandstitch.py · GPUProcessorLogic.expand_m sigma pixels / 4 kernel_size math.ceil(sigma * 1.5 1) if kernel_size % 2 0: kernel_size 1 padding kernel_size // 2 mask_in mask.unsqueeze(1) # [B,H,W] - [B,1,H,W] mask_padded TF.pad(mask_in, (padding,)*4, modereflect) dilated TF.max_pool2d(mask_padded, kernel_size, stride1, padding0)同样高斯模糊在 GPU 版里退化为一次conv2d与预计算高斯核的卷积查找掩码包围盒也改成了torch.max/where/min/max的向量化写法整批图像一次算完。不过开发者并没有盲目全上 GPU缩放仍回落到 PIL源码注释明确写了 CPU 效果更好孔洞填充仍用 scipy——只有真正受益于并行计算的算子才上 GPU这种务实取舍值得借鉴。最小可运行示例从零搭一条裁剪-采样-拼接链路动手验证是最好的理解方式。首先安装插件放到 ComfyUI 的custom_nodes/目录下git clone https://gitcode.com/gh_mirrors/co/ComfyUI-Inpaint-CropAndStitch然后按以下步骤搭最小工作流Load Image载入测试图用蒙版工具涂出待修复区域接入Inpaint Crop节点mask连蒙版SD1.5 场景建议开启output_resize_to_target_size并设 512×512SDXL/Flux 设 1024×1024output_padding保持 32把cropped_image送进InpaintModelConditioning后接标准采样链路——采样器拿到的是一个远小于原图的分辨率速度提升立竿见影 ⚡将采样输出接到Inpaint Stitch节点的inpainted_imagestitcher接口直接连 Crop 节点的同名输出最终输出的就是修复完成的整图。仓库自带的inpaint_hires.png展示了完整的高分辨率修复工作流可直接对照搭建。如果你用的是 Stable Diffusion 1.5仓库中的inpaint_sd15.png是更贴近入门配置的参考。常见疑问与避坑指南Q为什么这里要用 GPU 模式什么情况下该切回 CPUGPU 模式下裁剪、拼接的算子全部跑在 CUDA 上官方实测比 CPU 快 30~100 倍视频逐帧修复这类场景几乎是刚需。但 GPU 要求整批输入能装进显存且部分算子仍需回退到 CPU 执行如果你在无 GPU 的环境运行默认的cpu (compatible)模式永远可用。Qcontext_from_mask_extend_factor调不好会怎样它决定模型能看到多少上下文设成 1 意味着只裁掩码本身模型缺乏语义线索修复结果容易跑偏设得过大比如 5裁剪区域接近整张图提速收益就没了。默认 1.2 在多数场景是平衡点人物面部修复建议提高到 1.5 左右。Q为什么修复后还能隐约看到原图几乎可以肯定是掩码不够不透明。算法只把掩码值接近 1 的区域视为必须重绘若蒙版是 0.8 的灰混合后原图就会透出来。请确认掩码边缘像素为纯白255必要时开启mask_fill_holes补掉内部灰缝。Q批量处理时报 shape mismatch 错误裁剪节点要求批量输入时开启output_resize_to_target_size因为同批次输出必须同尺寸。另外代码对一张图配多张掩码多张图配一张掩码都做了自动复制扩展但前提是掩码与图像的空间尺寸一致。延伸方向这套设计还能怎么用读懂这个插件后你会发现它的思想可以迁移到更多场景stitcher这种坐标元数据随流程传递的模式完全可以复用在局部放大、局部重绘、区域超分等任务上策略模式的双处理器骨架也适合给其他图像算子做 CPU/GPU 双实现。接下来你可以尝试给crop_magic_im增加更智能的构图约束如人脸居中、把 GPU 版包围盒查找进一步向量化、或者为视频修复场景写一个逐帧复用的缓存层。想参与项目可以直接克隆仓库阅读源码、跑通示例工作流遇到问题提 issue或者提交 PR 贡献新特性。【免费下载链接】ComfyUI-Inpaint-CropAndStitchComfyUI nodes to crop before sampling and stitch back after sampling that speed up inpainting项目地址: https://gitcode.com/gh_mirrors/co/ComfyUI-Inpaint-CropAndStitch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考