Skip to main content

styletransfer-lite

tests PyPI Python License

Fast neural style transfer for Python. Pick one of 26 built-in painting styles, blend a few of them, or hand it any picture and it will use that as the style. It runs on onnxruntime, so the install is a few megabytes instead of a full TensorFlow or PyTorch, and a 1024 pixel photo takes about half a second on a laptop CPU.

A NASA photo of an astronaut next to three stylized versions

Left to right: the original photo, built-in style 19, Van Gogh's Starry Night used as a style image, and Hokusai's Great Wave used as a style image. Sources for the images are in examples/SOURCES.txt.

Quick start

pip install styletransfer-lite
styletransfer-lite photo.jpg --style 19

Real output from my machine (AMD laptop CPU, no GPU):

$ styletransfer-lite examples/astronaut.jpg --style 19
astronaut.jpg -> examples\astronaut_style19.png  (795x800, 0.337s on cpu)

$ styletransfer-lite examples/astronaut.jpg --style-image examples/starry_night.jpg
astronaut.jpg -> examples\astronaut_stylecustom.png  (795x800, 0.187s on cpu)

$ styletransfer-lite examples/astronaut.jpg --style 40
error: style index must be 0 to 25, got 40

Not sure which of the 26 styles you want? Render all of them on your photo at once:

styletransfer-lite sheet photo.jpg -o sheet.png

All 26 built-in styles applied to the same photo

The numbers under each tile are the style indices you pass to --style. I did not invent names for them, because the model I started from never came with any.

Read this first

  • The 26 built-in styles are fixed. This package runs pretrained networks, it does not train new ones.
  • "Style image" mode works on a 384 pixel version of your photo and scales the result back up, so on large photos it looks softer than the built-in styles.
  • Video is stylized frame by frame. Fine texture can shimmer between frames. --smooth reduces it but does not remove it.
  • The networks are small and quantized in their original form. See Where the models come from for what I checked.

Install

Python 3.8 or newer.

pip install styletransfer-lite             # CLI, Python API, GUI (needs tkinter)
pip install "styletransfer-lite[video]"    # adds OpenCV for video and webcam

The base install pulls in numpy, Pillow and onnxruntime. That is all.

GPU. The default onnxruntime is CPU only. For CUDA, swap it for the GPU build and use --device cuda:

pip uninstall onnxruntime
pip install onnxruntime-gpu

This needs CUDA 12 and cuDNN 9 on your PATH. If onnxruntime cannot load them it quietly falls back to CPU, so the CLI checks and gives you an error with --device cuda instead of pretending. On Windows with DirectML, install onnxruntime-directml and use --device dml (I have not tested this one). --device auto, the default, uses whatever is available.

On Debian or Ubuntu the GUI needs sudo apt install python3-tk.

Usage

Command line

styletransfer-lite photo.jpg --style 7                       # one built-in style
styletransfer-lite photo.jpg --style 3:0.5,12:0.5            # blend two styles
styletransfer-lite photo.jpg --style 7 --strength 0.6        # mix 60% style with the original
styletransfer-lite photo.jpg --style 7 --preserve-color      # stylized brightness, original colours
styletransfer-lite photo.jpg --style-image painting.jpg      # any picture as the style
styletransfer-lite photos/ -o out/ --style 4                 # whole folder
cat photo.jpg | styletransfer-lite - -s 4 -o - > out.png     # stdin to stdout
styletransfer-lite video clip.mp4 -o out.mp4 -s 19 --smooth 0.3
styletransfer-lite webcam -s 19                              # n / p change style, q quits
styletransfer-lite gui
styletransfer-lite info                                      # versions, devices, model files

Add --json to stylize, sheet, video and info for output you can parse:

$ styletransfer-lite examples/astronaut.jpg --style 3:0.5,12:0.5 --strength 0.8 --json
{
  "input": "astronaut.jpg",
  "output": "examples\\astronaut_style3-0.5_12-0.5.png",
  "size": [795, 800],
  "style": "3:0.5,12:0.5",
  "mode": "builtin",
  "strength": 0.8,
  "device": "cpu",
  "seconds": 0.306
}

(I collapsed the size list to one line here. The tool prints it across several.)

Errors go to stderr with exit code 2. A missing OpenCV gives you the exact pip install line.

What --strength means depends on the mode. With a built-in style it blends the result with your photo. With --style-image it moves between the photo's own style and the one you gave, which tends to look better than a plain fade.

Python

from styletransfer_lite import StyleTransfer

st = StyleTransfer()                                  # device="auto", max_size=1024
st.stylize("photo.jpg", style=7).save("out.png")
st.stylize("photo.jpg", style={3: 0.5, 12: 0.5}, strength=0.8)
st.stylize("photo.jpg", style=7, preserve_color=True)
st.stylize_with("photo.jpg", "painting.jpg")          # any picture as the style
st.contact_sheet("photo.jpg").save("sheet.png")

Everything returns a PIL.Image. Inputs can be paths, PIL images or HxWx3 uint8 arrays. Bad input raises StyleTransferError. Importing the package loads no models and opens no windows; models load on first use.

Desktop window

styletransfer-lite gui opens a small tkinter window: open a photo, choose a style index or a style image, move the strength slider, press Stylize.

The desktop window with an astronaut photo and a stylized copy

Speed

Measured with benchmarks/latency.py, median of 10 warm runs, on a Windows 11 laptop with an AMD CPU and an RTX 4060 Laptop GPU (8 GB). The "first call" column includes loading the model.

built-in style CPU CUDA
256 x 256 18 ms 7 ms
512 x 512 106 ms 20 ms
800 x 800 251 ms 53 ms
1024 x 1024 584 ms 84 ms

Style image mode (384 pixel network) is about 100 ms on either, and rendering the full 26 style contact sheet takes 0.76 s on CPU and 0.54 s on CUDA. The first CUDA call in a process took 2.2 s to start up. Full tables are in benchmarks/. A 320 x 320 test video ran at about 25 frames per second on CPU with the 26-style network.

The GPU gap is small below 512 pixels, so for single photos CPU is fine.

Where the models come from

I did not train anything. Three pretrained networks ship inside the wheel (about 3.8 MB in total):

  • multistyle26.onnx: the 26 style network (conditional instance normalization, Dumoulin et al.). I started from a quantized stylize_quantized.pb that, as far as I can tell, comes from the TensorFlow Android stylize demo. That file needs TensorFlow to run, so tools/convert_pb_to_onnx.py dequantizes its 8-bit weights, rebuilds the network in PyTorch and exports it to ONNX.
  • arbitrary_predict.onnx and arbitrary_transform.onnx: Magenta's arbitrary image stylization models (Ghiasi et al., 2017), the int8 TFLite versions from TF Hub, converted to ONNX with tf2onnx.

What I checked after converting, and what I did not:

  • 26 style network vs the original quantized TensorFlow graph, same input image: mean absolute pixel difference 0.008, 0.011 and 0.020 (on a 0 to 1 scale) for styles 0, 7 and 19. That is on one synthetic test image and three styles, not a full evaluation. The differences come from the original being 8-bit quantized and mine being float.
  • Style image network vs the TFLite originals: mean absolute difference 0.013 on one photo and one style.
  • There is no accuracy benchmark, because "good style transfer" has no ground truth. If you need a number, the speed table is the only one I can stand behind.

If you find a style that looks wrong compared with the original TensorFlow model, please open an issue with the input image.

Limitations

  • Style transfer changes a lot of an image. Faces and text can warp, especially at high strength.
  • Built-in styles are tuned to look right at roughly 500 to 1000 pixels. At 256 pixels the strokes look huge, as in the contact sheet above.
  • Images smaller than 32 pixels on a side are rejected.
  • Video output has no audio, and I only tested it on a short synthetic clip. The webcam command is implemented but I have not run it against a camera.
  • The dml device and macOS are untested. CI covers Linux, Windows and macOS on the CPU path.

Development

git clone https://github.com/Ekaghni/styletransfer-lite
cd styletransfer-lite
pip install -e ".[dev]"
pytest

The original scripts this project grew out of are kept in legacy/ for reference. One of them, pytorch_model.py, exported an untrained random network to style_transfer.pt, so do not use that file for anything.

Credits and licenses

Code: MIT, see LICENSE. Model weights are Apache-2.0 from the TensorFlow and Magenta projects. Example images: see examples/SOURCES.txt.

  • Dumoulin, Shlens, Kudlur. A Learned Representation for Artistic Style. 2017.
  • Ghiasi, Lee, Kudlur, Dumoulin, Shlens. Exploring the Structure of a Real-time, Arbitrary Neural Artistic Stylization Network. 2017.

Metadata

Release files for styletransfer-lite 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for styletransfer-lite 0.1.0
File Size Uploaded
styletransfer_lite-0.1.0.tar.gz 2.9 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for styletransfer-lite 0.1.0
File Interpreter ABI Platform
styletransfer_lite-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 5.8 MB

Release files / styletransfer_lite-0.1.0.tar.gz

Download URL styletransfer_lite-0.1.0.tar.gz
Size 2.9 MB
Tags Source
SHA-256 checksum
How to use checksums
db5dd09955aace7eff5af937cb4e22697d55154c0b6103d72834e85bafdd10c2
BLAKE2b-256 checksum
How to use checksums
a4d8571c0681095d32224f376967a24aaeb2e3162566b6f2fd80704e544642ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.6

Release files / styletransfer_lite-0.1.0-py3-none-any.whl

Download URL styletransfer_lite-0.1.0-py3-none-any.whl
Size 2.9 MB
Tags Python 3
SHA-256 checksum
How to use checksums
f4ddd424e6a637097155bd47293c1423b13345b9b84d983079009b93f2f0775b
BLAKE2b-256 checksum
How to use checksums
8d1a3afe3b83e4607f0e5b5452021ffa1a9cf980849bd7a7b331cb3fe5e4751a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.10.6

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page