ArtificialGuyBR

Home / Blog / Fixing things

Create an Inpainting Checkpoint from Any Model

Merge SD checkpoints into inpainting variants with Add Difference. Why inpaint weights differ and how to control seed and noise for repeatable edits.

8 sources cited Fixing things

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

TL;DR


Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Why Convert a Checkpoint Instead of Downloading One?

Dedicated inpainting checkpoints exist for SD 1.5 and SDXL, but they're tied to the base model they were trained from. If you've fine-tuned a model on a specific style, character, or domain, the official inpainting weights won't carry those adaptations. The Add Difference merge (A + (B - C)) grafts the inpainting capability onto your checkpoint while preserving its learned concepts.

This technique works because the inpainting delta — the weights that changed when the base model was fine-tuned for inpainting — is isolated by subtracting the base (C) from the inpainting base (A). Applying that delta to your fine-tune (B) transfers only the inpainting-specific adaptation.


Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

The Architecture Difference: 9 Channels vs. 4

A standard Stable Diffusion UNet expects 4-channel latents from the VAE encoder. An inpainting UNet expects 9 channels:

Channel groupCountPurpose
Noisy latent4Standard diffusion input
Masked-image latent4VAE encoding of the image with masked regions zeroed
Mask1Downsampled binary mask (white = regenerate, black = preserve)

The 5 additional channels are zero-initialized when inpainting training begins, so the model learns to condition on the masked region and mask from scratch. This is why a regular checkpoint simply fails at inpainting — its UNet has no weights for those extra inputs.

Source: The SD 1.5 inpainting model card states: "For inpainting, the UNet has 5 additional input channels (4 for the encoded masked-image and 1 for the mask itself) whose weights were zero-initialized after restoring the non-inpainting checkpoint."

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

SD 1.5 Merge Recipe

SlotModelSource
Model Astable-diffusion-v1-5-inpainting (official)HuggingFace
Model BYour fine-tuned checkpoint
Model Cstable-diffusion-v1-5 (base)HuggingFace
ModeAdd Difference
MultiplierIgnored for this mode
Formatsafetensors

The output file appears as <YourModelName>.inpainting.safetensors in your models folder.

Note: The benjamin-paine repository mirrors the official CompVis/Stability weights. Use the official model card as the canonical source.

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

SDXL Merge Recipe

SlotModelSource
Model Asd_xl_base_1.0_inpainting_0.1.safetensorsbenjamin-paine/sd-xl-alternative-bases
Model BYour SDXL fine-tune
Model Csd_xl_base_1.0_fp16_vae.safetensorsSame repo
ModeAdd Difference
MultiplierIgnored
Formatsafetensors

Critical: Model C must be the FP16 VAE version. The Diffusers team trained XL Inpainting with the FP16 VAE fused in; using a different base (fp32 VAE or no VAE) applies a mismatched delta and yields a broken VAE.

Source: Benjamin Paine's model card: "You must specifically use the two files present in this repository... using a different XL base will result in an incorrect delta being applied to the inpainting checkpoint, and the resulting VAE will be nonsensical."

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

How Add Difference Works (The Mechanism)

The formula theta_A + (theta_B - theta_C) computes:

  1. theta_A - theta_C = the inpainting delta (weights added/changed when the base model was fine-tuned for inpainting)
  2. theta_B + delta = your fine-tune with the inpainting adaptation grafted on

Because A and C share the same architecture (and for SDXL, the same VAE), the subtraction cancels out the shared base weights, leaving only the inpainting-specific changes: the 9-channel input projection, attention modifications, and any VAE statistics baked into the delta.

Source: A1111 merge_models.py implements add_difference as theta_0 + (theta_1 - theta_2) with no multiplier scaling.

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Common Error: BigLust v1.0 Metadata Crash

SymptomCauseFix
TypeError: argument 'metadata': 'dict' object cannot be converted to 'PyString' during mergeCheckpoint contains metadata in an incompatible format (dict vs. PyString)In Checkpoint Merger → Metadata section: uncheck "save metadata", click "read metadata from selected checkpoints", then Merge
Source: Civitai article 833 workaround.

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Controlling Seed and Noise for Repeatable Edits

Three levers determine determinism in the StableDiffusionInpaintPipeline:

LeverParameterEffect
Seeded generatorgenerator=torch.Generator(device).manual_seed(seed)Makes sampling deterministic if the pipeline generates its own noise
Explicit latentslatents=your_tensorBypasses random noise entirely — pipeline uses your tensor as the starting latent
Strengthstrength=0.3–1.0At 1.0, masked region becomes pure noise; at <1.0, original latent signal is partially preserved

For exact reproducibility across runs, supply both a seeded generator and explicit latents.

Source: diffusers StableDiffusionInpaintPipeline.__call__ signature documents generator ("make generation deterministic") and latents ("Pre-generated noisy latents to be used as inputs").

Denoising Strength vs. Mask Interaction

The strength parameter controls how much noise is added to the input image before denoising the masked region:

Source: Pipeline docs: "A value of 1 essentially ignores image." Community workflow (Civitai 4451) recommends 0.7 for first pass, 0.3 for detail refinement.

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Workflow: From Sketch to Inpaint-Ready Result

  1. Prepare the inpainting checkpoint using the merge recipe above.
  2. Open an img2img/inpaint interface (A1111, ComfyUI, or Krita AI Diffusion).
  3. Draw a crude mask over the region to regenerate; set strength ≈ 0.7.
  4. Prompt the desired content for the masked area.
  5. Iterate: lower strength to 0.3–0.4, refine mask/prompt, re-run.
  6. For exact reproducibility: capture the latents tensor from a good run, then re-use it with the same seed.
Tooling: Krita AI Diffusion (ComfyUI) provides a fast sketch → inpaint loop. ControlNet's "inpaint only" processor handles outpainting. ADetailer automates face/body touch-ups.

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Quick Reference: SD 1.5 vs. SDXL Merge Settings

SettingSD 1.5SDXL
Model A (inpainting base)stable-diffusion-v1-5-inpaintingsd_xl_base_1.0_inpainting_0.1.safetensors
Model B (your fine-tune)Your .safetensorsYour .safetensors
Model C (base)stable-diffusion-v1-5sd_xl_base_1.0_fp16_vae.safetensors
ModeAdd DifferenceAdd Difference
MultiplierIgnoredIgnored
Output name&lt;name&gt;.inpainting.safetensors&lt;name&gt;.inpainting.safetensors

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

FAQ

Can I use a regular checkpoint for inpainting without merging?

No. The UNet lacks the 5 additional input channels (4 masked-image latent + 1 mask). It will either error or produce garbage.

Does the Multiplier setting matter for Add Difference?

No. The A1111 implementation ignores multiplier for this mode; the formula is fixed as A + (B - C).

Why must SDXL use the FP16 VAE as Model C?

The XL inpainting model was trained with the FP16 VAE fused in. The delta A - C contains VAE-specific statistics. A mismatched base applies the wrong delta and breaks the VAE.

How do I get the exact same inpaint result twice?

Pass the same seeded torch.Generator and the same latents tensor to the pipeline. strength must also match.

What does strength=0.5 actually do?

It adds noise halfway to pure noise. At 0.5, the masked region is noised halfway toward pure noise; the denoiser preserves more structure while still allowing prompt-guided changes.

Can I merge a LoRA into the inpainting checkpoint instead?

Yes — load the merged inpainting checkpoint, then apply LoRAs at inference time. The merge recipe only handles the base checkpoint architecture.

Where do I find the official SD 1.5 inpainting weights?

stable-diffusion-v1-5/stable-diffusion-inpainting on HuggingFace (CompVis/Stability). The benjamin-paine repo is a mirror.


Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial

Sources

#SourceWhat it contributed
1SD 1.5 Inpainting model card9-channel architecture, 440k training steps, zero-init weights
2SDXL Alternative BasesAdd Difference formula, FP16 VAE requirement, filenames
3diffusers InpaintPipeline docsgenerator, latents, strength, mask_image semantics
4A1111 merge_models.pyadd_difference implementation, multiplier ignored
5Civitai 833SD 1.5/SDXL merge recipes, BigLust metadata fix
6Civitai 4451Denoising strength heuristics (0.7 / 0.3), img2img workflow
7Civitai 482ControlNet inpaint-only outpainting, Krita AI Diffusion, ADetailer
8Civitai 8261Civitai on-site generator localStorage hack (reference only)

Related reads: Stable Diffusion checkpoint training guide · ControlNet inpainting and outpainting · ComfyUI inpainting workflow tutorial