Nodes/ComfyUI-Color_Transfer/Palette Optimal Transport Transfer
ComfyUI Node

Palette Optimal Transport Transfer

Optimal transport, no posterization

By 45uee·Created 2 years ago·Updated 5 months ago· 42
Palette Optimal Transport Transfer
  • image
  • target_colors
  • IMAGE
palette_extension_methodNone
palette_extension_points5
blend_modeOriginal
blend_ratio0.5

Of all the palette nodes in ComfyUI-Color_Transfer, this is the one that sounds most like a math exam and behaves the most like magic. Palette Optimal Transport Transfer doesn't just snap every pixel to the nearest swatch like the plain Palette Transfer does. It moves your image's whole distribution of colors toward the palette's distribution, the way you'd shift a pile of sand so it matches another pile's shape. Same sand, same amount, rearranged to fit a new mold. That's exactly what "optimal transport" means, and it's why the result keeps your image's tonal balance instead of flattening it into bands.

How it works

The pipeline is, step by step:

  1. Summarize the source. It runs MiniBatchKMeans with 1000 clusters on your image's pixels - a compact stand-in for the full color distribution.
  2. Compute a transport plan. Using the POT (Python Optimal Transport) library, it solves a regularized optimal-transport problem (Sinkhorn) between your image's cluster distribution and your palette, with a cost matrix measuring how "expensive" it is to turn each source color into each palette color. The plan moves colors proportionally: if your image is 30% blue, roughly 30% of it gets pushed toward blue-ish palette colors, not all of it to whatever single swatch is closest.
  3. Recolor. Each pixel takes its cluster's transported color, and you can blend that against the original or against a grayscale version.

That proportional behavior is the selling point. Hard nearest-swatch mapping can dump everything into one dominant palette color and leave your other swatches unused; transport actively spends your palette, so you end up with a recolor where all the swatches show up in sensible amounts.

The inputs that matter

  • image, target_colors - same as the rest of the family: any IMAGE plus a COLOR_LIST from ColorPalette.
  • palette_extension_method (None / Dense / Edge, default None) - how much the palette gets pre-expanded before transport. Dense interpolates points between every pair of colors; Edge uses a Delaunay triangulation to find sensible "edges" between colors and interpolates along those. With a small 4-color palette and None, the palette distribution is spiky - extension gives transport smoother intermediate colors to work with.
  • palette_extension_points (2–20, default 5) - how many interpolated points per pair/edge. More points = smoother, heavier.
  • blend_mode (Original / Grayscale) - blend the transport result against your original image, or against a desaturated version. Grayscale + a low blend ratio is the classic "tint it toward a mood without losing the photo's luminance" move.
  • blend_ratio (0–1, default 0.5) - how much transport wins. 0 keeps the source untouched; 1 is full recolor.

Practical notes and gotchas

This is the most expensive node in the pack - a 1000-cluster KMeans plus a Sinkhorn solve on every frame. The source has explicit memory-safety fixes (small batches, no reassignment, forced GC on batches), but on a 4K image it'll still chug noticeably. Fine for stills, worth a thought for video batches.

Also, it's the only node that genuinely needs the POT package. The pack's other nodes are fine if POT is missing, but this one imports ot at the top of the module - if ComfyUI's loader complains, install it:

pip install POT

Install

ComfyUI Manager search "Color_Transfer", or:

cd ComfyUI/custom_nodes
git clone https://github.com/45uee/ComfyUI-Color_Transfer

Then restart. No models, no keys, CPU math. If it's your first node from this pack, also note the README's general fix for import errors: pip install scikit-learn. It's a small solo-dev pack, and this is its heaviest, cleverest node - expect the good results to come with a bit of wait.

CategoryColor Transfer/Palette Transfer

Inputs (6)

NameTypeDefaultDescription
imageIMAGE
target_colorsCOLOR_LIST
palette_extension_methodCOMBONone3 options: Dense, Edge, None
palette_extension_pointsINT52–20
blend_modeCOMBOOriginal2 options: Original, Grayscale
blend_ratioFLOAT0.50–1

Outputs (1)

NameTypeDescription
IMAGEIMAGE