HairDeck: Hair Cards and Spring Bones From One Character Image
HairDeck generates stylized hair cards as a set from a single image, adds the spring-bone chains that animate them, and exports GLB or VRM avatars.
Hair is the part of a 3D character that image-to-3D pipelines get wrong most often. Strand reconstruction gives a realistic groom that is heavy to render, and mesh reconstruction gives one fused blob that an artist cannot re-comb, restyle or animate. Card hairstyles are what stylized production actually ships, and they are made by hand, one ribbon at a time.
HairDeck treats the hairstyle as what it is to an artist: an unordered set of primitives. Each hair card is a single token, and a set diffusion transformer denoises all cards together, so the model never has to decide what order the hair comes in. The result keeps individual cards with per-card UVs, plus the spring-bone chains that make them move.
The pipeline: hair-card tokens, image or point-cloud conditioned set diffusion, and generated cards with spring-bone chains.
Cards as a set
The only prior generator of stylized hair cards, CHARM, decodes a hairstyle autoregressively as one long sequence of control points. That makes the order of the sequence matter, and a mistake early in the sequence propagates through the rest of the hair.
HairDeck inverts it. A card VAE encodes each card into a token, the set transformer looks at all of them at once, and the card VAE decodes each token back into geometry with its own UV coordinates. Cards are conditioned on an image by default, or on a point cloud through a fourth released model.
Spring bones come with the hair
Geometry alone is not an asset. A card hairstyle in a game engine or a VRM avatar only looks alive because spring bones pull each card with a little physics, and those chains are normally hand-built and weight-painted after the mesh is done.
A chain diffusion model generates them directly, conditioned on the card tokens, so the export carries skinning as well as geometry. One image goes in, and what comes out is a hairstyle that swings.
A frame from the project's demo: generated cards on the supplied avatar body.
The project's demo video: one input image, four generated variations, and the VRM head-turn preview.
What ships
| Model | Role | Checkpoint |
|---|---|---|
| Image DiT | Generates card tokens conditioned on an image | ckpt/image_model/model.safetensors |
| Card VAE | Decodes a card token's latent into card geometry | ckpt/card_vae/model.safetensors |
| Chain DiT | Generates spring-bone chains conditioned on card tokens | ckpt/chain_model/model.safetensors |
| Point-cloud DiT | Generates card tokens conditioned on a point cloud | ckpt/pointcloud_model/model.safetensors |
The image path runs Image DiT, Card VAE and Chain DiT. The point-cloud model is used by the point-cloud generation and evaluation path. The repository also ships the normalization statistics, the canonical head frame, a VRoid Studio template avatar for VRM export, and 100 test cases with their original card geometry, so the evaluation can be reproduced without the training set.
Inference needs Linux x86-64, Python 3.12 and one NVIDIA CUDA GPU, tested with PyTorch 2.8 and CUDA 12.8. The preprocessing stack is heavier than the models: SAM 3 and DINOv3 ViT-L/16 are gated downloads that require accepting their licences, BiRefNet-matting handles the cutout, and the VRM export drives Blender 4.2 LTS with the VRM add-on, which the setup script can fetch on its own. The VRM path is still a Python and Blender pipeline, not a ComfyUI custom node.
A single command generates one to four variations, and --no-chains drops the spring-bone model when only the cards are wanted:
python scripts/image_to_hair.py character.png --out results/my_character --n 4
python -m hairdeck.vrm.export results/my_character/character 0Numbers from the paper
On CHARM's own test set, HairDeck reports 44% lower Chamfer distance and more than half the card-orientation error, while running 33 times faster. From single images the authors report it beating CHARM, image-to-3D pipelines and strand-based methods, which is the comparison that matters for anyone feeding it a generated character rather than a rendered one.
Availability
- hyz317/HairDeck on Hugging Face: four checkpoints, supporting data, 100 test cases, Apache-2.0
- hyz317/HairDeck on GitHub: inference, local demo, evaluation and training code, currently the only supported path
- A hosted Space demo that generates hair and exports VRM from the browser
- There is no first-party ComfyUI integration. A very new community pack, FengLairh/ComfyUI-HairDeck, wraps the same checkpoints into three nodes (load, generate, save) that run inside ComfyUI's own Python process and prepare a portable Blender for VRM export; it appeared on November 1 and has not been validated here
Comments
Sign in with GitHub to join the discussion.