【深度学习】Fooocus Outpaint 原理
编辑
2025-06-03
深度学习
00

目录

Fooocus Outpaint 完整处理流程
1. Canvas Expansion & Mask Creation 画布扩展和遮罩创建
2. Content-Aware Filling 内容感知填充
3. VAE Inpaint Encoding VAE修复编码
4. Inpaint Head Injection 修复头部注入
5. Diffusion Sampling (Add Noise + Denoise) 扩散采样(加噪+去噪)
6. Post-processing 后处理
总结流程:

Fooocus Outpaint 完整处理流程

1. Canvas Expansion & Mask Creation 画布扩展和遮罩创建

12:15:modules/async_worker.py
展开代码
def apply_outpaint(async_task, inpaint_image, inpaint_mask): if len(async_task.outpaint_selections) > 0: H, W, C = inpaint_image.shape if 'top' in async_task.outpaint_selections: inpaint_image = np.pad(inpaint_image, [[int(H * 0.3), 0], [0, 0], [0, 0]], mode='edge') inpaint_mask = np.pad(inpaint_mask, [[int(H * 0.3), 0], [0, 0]], mode='constant', constant_values=255)
  • 根据用户选择的方向(top/bottom/left/right)扩展画布30%
  • 使用edge模式复制边缘像素填充新区域
  • 新区域的mask值设为255(完全需要重绘)

2. Content-Aware Filling 内容感知填充

158:170:modules/inpaint_worker.py
展开代码
# compute filling if use_fill: self.interested_fill = fooocus_fill(self.interested_image, self.interested_mask)

fooocus_fill函数中:

136:147:modules/inpaint_worker.py
展开代码
def fooocus_fill(image, mask): height, width, _ = image.shape mask = mask[:, :, 0] raw_image = image.copy() raw_mask = mask.copy() # 多尺度模糊填充算法 for r in [11, 7, 5, 3]: kernel = np.ones((r, r), dtype=np.uint8) dilated_mask = cv2.dilate(mask, kernel, iterations=1) blurred_image = box_blur(image, r) image = np.where(dilated_mask[..., None] > 128, blurred_image, image) mask = dilated_mask

3. VAE Inpaint Encoding VAE修复编码

177:189:modules/core.py
展开代码
def encode_vae_inpaint(vae, pixels, mask): # 预处理mask w = mask.round()[..., None] pixels = pixels * (1 - w) + 0.5 * w # 用0.5替换masked区域 # VAE编码 latent = vae.encode(pixels) B, C, H, W = latent.shape # 处理latent mask latent_mask = mask[:, None, :, :] latent_mask = torch.nn.functional.interpolate(latent_mask, size=(H * 8, W * 8), mode="bilinear").round() latent_mask = torch.nn.functional.max_pool2d(latent_mask, (8, 8)).round().to(latent)

4. Inpaint Head Injection 修复头部注入

194:218:modules/inpaint_worker.py
展开代码
def patch(self, inpaint_head_model_path, inpaint_latent, inpaint_latent_mask, model): # 加载inpaint head模型 if inpaint_head_model is None: inpaint_head_model = InpaintHead() sd = torch.load(inpaint_head_model_path, map_location='cpu', weights_only=True) inpaint_head_model.load_state_dict(sd) # 特征拼接和处理 feed = torch.cat([ inpaint_latent_mask, model.model.process_latent_in(inpaint_latent) ], dim=1) inpaint_head_feature = inpaint_head_model(feed)

5. Diffusion Sampling (Add Noise + Denoise) 扩散采样(加噪+去噪)

280:342:modules/core.py
展开代码
def ksampler(model, positive, negative, latent, seed=None, steps=30, cfg=7.0, sampler_name='dpmpp_2m_sde_gpu', scheduler='karras', denoise=1.0, ...): latent_image = latent["samples"] # 准备噪声(加噪过程) if disable_noise: noise = torch.zeros(latent_image.size(), ...) else: noise = ldm_patched.modules.sample.prepare_noise(latent_image, seed, batch_inds) # 扩散采样过程(去噪过程) samples = ldm_patched.modules.sample.sample(model, noise, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, ...)

6. Post-processing 后处理

254:261:modules/inpaint_worker.py
展开代码
def post_process(self, img): a, b, c, d = self.interested_area content = resample_image(img, d - c, b - a) result = self.image.copy() result[a:b, c:d] = content result = self.color_correction(result) return result

总结流程:

  1. 扩展画布 → 创建新区域和mask
  2. 填充mask → 使用content-aware filling算法
  3. VAE编码 → 将图像和mask编码到潜在空间
  4. 加噪 → 准备噪声张量
  5. 去噪 → 通过扩散采样生成新内容
  6. 后处理 → 调整尺寸和颜色校正
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!