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.

samples

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
Safetensors
Model size
49.8M params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Dataset used to train azyg0s/pixelart-50m