Nodes/ComfyUI-Pixel-Forge/Image Similarity (Sequential CLIP)
ComfyUI Node

Image Similarity (Sequential CLIP)

Match a Stack of Reference Images Against Your Crops — One-to-One, No Repeats

By ThunderBolt4931·Created 12 months ago·Updated 9 months ago· 6
Image Similarity (Sequential CLIP)
  • image_ref
  • image_batch
  • batch_masks
  • batch_blank_masks
  • bounding_boxes
  • matched_images
  • matched_masks
  • matched_blank_masks
  • matched_bounding_boxes
  • clip_similarities
  • lpips_distances
threshold0.80

"Image Similarity (Sequential CLIP)" is the brain of Pixel-Forge: a node that takes a batch of reference images, a batch of candidates, and pairs them up by visual similarity - every reference gets its best match, no candidate used twice. If you've ever wanted to sort a pile of crops against a set of "known good" examples, this is the node you've been hand-rolling a mess of Python for.

The inputs - it expects the full pipeline

  • image_ref (IMAGE) - your reference images, in a batch
  • image_batch (IMAGE) - the candidates. In the intended flow this is the cropped_images output of Crop Disjoint Mask Regions.
  • batch_masks, batch_blank_masks (MASK) and bounding_boxes (BOX) - the travel companions that node also emits. They all must match the candidate batch size; the node will throw a ValueError otherwise. You can't skip them, so the node is really "match my crops against my references," not a general image comparator.
  • threshold (FLOAT, default 0.8) - the CLIP cosine-similarity bar. Higher = stricter.

How it works

Every image is embedded with OpenAI's CLIP ViT-B-32 (via open_clip). Then comes the "Sequential" part, which is the interesting bit: it processes references one at a time, in order, and for each one picks the best remaining candidate by cosine similarity. Once a candidate is matched it's removed from the pool - so with 5 references and 20 crops, you get 5 distinct pairings, not 5 all pointing at the same best crop. This greedy-without-replacement behavior is what makes it actually useful for assignment problems (pairing product shots to crops, matching frames to references) rather than just ranking.

After each match it computes an LPIPS distance (AlexNet) as a second opinion - a perceptual "how different are these really" number. If the CLIP score clears the threshold, the candidate's image, mask, blank mask and box flow through to the outputs; if not, you get a black image and zeroed mask/box in that slot, keeping the batch aligned.

Outputs: matched_images, matched_masks, matched_blank_masks, matched_bounding_boxes (in reference order), plus clip_similarities and lpips_distances as comma-separated score strings. It's flagged as an output node, so the matched batch shows up in the UI for a quick eyeball.

Setting the threshold

0.8 is a genuinely strict bar for CLIP cosine similarity - a "same subject, same angle" match scores high, but a same-subject-different-lighting crop can dip below. If you're getting all black output, you're not broken, you're below threshold: drop it to 0.7 or 0.65 and watch what comes through. If everything matches when it shouldn't, raise it.

The load cost

The node downloads open_clip's ViT-B-32 (OpenAI weights) and the LPIPS AlexNet on first use. A few hundred MB and a wait the first time - after that they're cached. The pack's open_clip_torch and lpips requirements install with the pack.

Install

ComfyUI Manager → search "ComfyUI-Pixel-Forge" → install → restart, or:

cd ComfyUI/custom_nodes
git clone https://github.com/ThunderBolt4931/comfyui_pixel_forge

restart, under Pixel-Forge/Utils. New-pack caveat applies - December 2025, no community footprint, README documents nothing. On a workflow that matters, sanity-check a few of its pairings by eye; the scores in the strings are your audit trail.

CategoryPixel-Forge/Utils

Inputs (6)

NameTypeDefaultDescription
image_refIMAGE
image_batchIMAGE
batch_masksMASK
batch_blank_masksMASK
bounding_boxesBOX
thresholdFLOAT0.800–1

Outputs (6)

NameTypeDescription
matched_imagesIMAGE
matched_masksMASK
matched_blank_masksMASK
matched_bounding_boxesBOX
clip_similaritiesSTRING
lpips_distancesSTRING