See-through β the libwaifu package
See-through (SIGGRAPH 2026), converted to the
package format libwaifu reads. It takes an anime
illustration apart into the layers it was drawn in β up to twenty-four of them: hair, face, eyes,
clothing, what is held β with what each one hides drawn in, and stacks them by depth into a
Photoshop document. In libwaifu the task is img2layers.
These weights are subject to the Open RAIL licences of the models they come from, copied unchanged here as
LICENSE-layerdiff3dandLICENSE-marigold. The use-based restrictions in paragraph 5 and Attachment A of those licences apply to every use of these files, and anyone who redistributes them or hosts them as a service must pass those restrictions on. Commercial use is permitted.This is a modified copy β see
NOTICEfor what was changed β and it is not an official See-through release and is not endorsed by its authors. The original weights are at layerdifforg/seethroughv0.0.2_layerdiff3d and layerdifforg/seethroughv0.0.1_marigold.
What is here
see-through.yaml and its six parts, 11.4 GB, carry both of See-through's models:
| what | dtype | |
|---|---|---|
| the layers model | LayerDiff 3D: an Animagine XL 4.0 U-Net that draws every layer at once, SDXL's VAE, and LayerDiffuse's alpha decoder | U-Net and alpha decoder float16, VAE float32 |
| the depth model | Marigold on Stable Diffusion 2, fine-tuned to order the layers | U-Net float16, VAE float32 |
There are no text encoders. Neither model reads a prompt anyone writes: the layers model is conditioned on the name of each layer and the depth model on the empty prompt, so what the encoders make of those is computed once and carried in the package instead.
Using it
From Rust:
let manifest = Manifest::open("see-through.yaml")?;
let model = SeeThrough::from_manifest(Device::Cuda, u64::MAX, &manifest)?;
let layers = model.decompose(&picture, &SeeThroughOptions::default(), &mut |_| ControlFlow::Continue(()))?;
std::fs::write("layers.psd", layers.to_psd())?;
std::fs::write("depth.psd", layers.to_depth_psd())?;
or from C, through waifu_engine_layers_async in waifu.h. See
docs/see_through.md for how a
picture is taken apart.
How close it is to the original
Upstream runs in bfloat16. Measured against upstream's own pipelines in float32, on inputs taken
off a real run of test_image.png, libwaifu is closer to float32 than upstream's bfloat16 is β
which is the bar its tests hold it to:
| libwaifu vs float32 | upstream bfloat16 vs float32 | |
|---|---|---|
| layers U-Net, one step | 0.035 % | 0.26 % |
| depth U-Net, one step | 0.041 % | 0.25 % |
| VAE decode | 0.0004 % | 2.4 % |
| VAE + alpha decoder | 0.058 % | 0.54 % |
The reference tensors are see-through_test.safetensors in
ling0322/libwaifu_test_data.
Speed and memory
One 928 Γ 1232 illustration at the defaults (1280, 30 steps; depth at 768, 4 steps) on an RTX 5060 Ti 16 GB takes 472 s with FlashAttention, against upstream's 398 s. Both models are read onto the device at once; at 1280 a 16 GB card holds all but about 2.4 GB of the weights.
Citation
@inproceedings{lin2026seethrough,
title = {See-through: Single-image Layer Decomposition for Anime Characters},
author = {Lin, Jian and Li, Chengze and Qin, Haoyun and Chan, Kwun Wang and Jin, Yanghua and
Liu, Hanyuan and Choy, Stephen Chun Wang and Liu, Xueting},
booktitle = {SIGGRAPH Conference Papers '26},
year = {2026},
publisher = {ACM},
doi = {10.1145/3799902.3811209}
}
Model tree for ling0322/libwaifu-see-through
Base model
prs-eth/marigold-depth-v1-1