Pixel-art icon model (49.8M)
A small text-to-image model that draws 32×32 RGBA pixel-art game icons with transparent backgrounds. It is a flow-matching (rectified flow) UNet with 49.8M parameters, conditioned on a frozen CLIP ViT-B/32 text encoder. It was trained from scratch on 175,544 sprites: the 172,330 in azyg0s/pixelart-172k plus 3,214 CC0 sprites from OpenGameArt and a CC0 synthetic set, which are not redistributed there. It runs on a CPU, though slowly; a GPU or Apple Silicon (MPS) is much faster.
Seed 0, 30 steps, CFG 4. Rows: red armchair · potted cactus in a blue pot · golden crown with rubies · green slime
monster · dcss style brown potion · steaming bowl of ramen.
Usage
pip install -r requirements.txt
python generate.py "red armchair" "potted cactus in a blue pot" -n 4
The script writes native 32×32 PNGs and an upscaled contact sheet to outputs/. On first run it downloads the text
encoder openai/clip-vit-base-patch32 (MIT) from the Hub.
| flag | default | |
|---|---|---|
-n |
4 | images per prompt |
--steps |
30 | Heun sampler steps |
--cfg |
4.0 | classifier-free guidance scale |
--cfg-interval |
0.0,0.75 |
apply CFG only for t in this range (t=1 is noise) |
--seed |
0 |
Prompts describe a single object: "striped lavender shield", "neon cyberpunk peach scroll bundle". They are
wrapped as pixel art icon of a <prompt> internally. A <source> style prefix switches to the look of one of the
CC0 sources in the training data: dcss, 7soul1, idylwild, krea16 (e.g. "dcss style iron helmet").
Post-processing: alpha is thresholded to 0/255 and opaque pixels are quantised to at most 16 colours, so the output is clean pixel art.
Files
model.safetensors |
EMA weights (fp32) at step 124k, the best mean validation loss |
config.json |
architecture, text encoder, sampler defaults, training hyper-parameters |
pixelart/ |
model, text encoder wrapper, sampler and post-processing (about 300 lines of PyTorch) |
generate.py |
command-line generator |
Model
- UNet, base 64 channels, multipliers (1, 2, 4, 5), cross-attention to the text tokens at 16, 8 and 4 px; time + pooled-text embedding as scale/shift in every ResBlock. Input/output: 4 channels (RGBA) at 32×32, scaled to [-1, 1].
- Text: frozen CLIP ViT-B/32 text encoder, 24 tokens; token states are used for cross-attention and the pooled state for the global embedding.
- Objective: rectified flow, velocity prediction; 10% caption dropout for classifier-free guidance.
Training
150k steps, batch 128, AdamW lr 2e-4 (1k warmup), bf16, EMA 0.9999, on one NVIDIA L4 (Colab).
Sources were sampled with weights sheet=1.5, lora=1.0, cc0=0.5. For 50% of samples with an alternative caption,
the alternative was used. The released weights are the EMA at step 124k.
| validation loss (lower is better) | val | patterns | r6 | binding | unseen |
|---|---|---|---|---|---|
| step 124k | 0.0695 | 0.0713 | 0.0813 | 0.0639 | 0.0867 |
unseen holds 458 prompts about 115 subjects that do not occur in training. The validation sets are part of the
dataset.
Limitations
- 32×32 only, single centred objects. It does not draw scenes, tiles or characters in poses reliably.
- Attribute binding is weak: "polka dot grandfather clock" often comes out plain, and ambiguous words take the wrong sense ("haunted scale mail" can become a weighing scale). Multi-part objects (pianos, vehicles with attachments) are often messy.
- English prompts only.
- About 98% of the training images are synthetic (see the dataset card), so the model inherits the biases and mistakes of those image generators.
License
Weights and code: MIT. The text encoder openai/clip-vit-base-patch32 is MIT-licensed and downloaded
separately.
- Downloads last month
- 71