Nodes/ComfyUI_pixel_snapping/Pixel Snapping (SIFT)
ComfyUI Node

Pixel Snapping (SIFT)

Line up two images without hand-placing a single point

By flywhale-666·Created 8 months ago·Updated 7 months ago· 58
Pixel Snapping (SIFT)
  • reference_image
  • target_image
  • target_mask
  • stitched_image
  • mask
  • corrected_target
max_features5000
match_ratio0.75
ransac_threshold5.0
invert_input_maskfalse
mask_grow0
mask_blur0.0
invert_output_maskfalse

You've got two photos of the same scene that overlap, or a re-rendered crop that has to sit back on its original, and the thought of dragging one image pixel-by-pixel into place makes you want to quit. That's the job this node exists for. It doesn't generate anything and calls no API - it finds matching texture in both images, works out the transform between them, and stitches them together. No model download, no seed, usually under a second.

Pixel Snapping (SIFT) is one of five nodes in the ComfyUI_pixel_snapping pack, and it's the one doing the cleverest work. Where most alignment tools assume a simple translate-and-scale, this one estimates a full affine transform - rotation, skew, and even non-uniform scaling - which is exactly the case you hit when a scan, a phone photo, or an AI-generated crop is slightly warped relative to your base image.

How it works

The mechanism is classic computer vision, and the node is refreshingly honest about it. It converts both images to grayscale and runs SIFT to detect distinctive keypoints (up to max_features, default 5000). Those keypoints get matched with FLANN, and Lowe's ratio test uses match_ratio (0.75) to keep only unambiguous matches. Then RANSAC - with ransac_threshold in pixels, default 5 - fits an affine matrix to the good matches, and there's a refinement pass that drops the worst 20% of inliers by reprojection error and refits with a more robust estimator.

The interesting bit: if the width scale and height scale differ by more than 0.6%, it decides your target has non-uniform scaling distortion, stretches it, and re-runs the whole match. It'll retry up to ten times before giving up, and it needs at least 80 solid matches to be happy. All of this chatter lands in the console - you'll see a small essay per attempt, which is great for debugging and overwhelming otherwise.

The inputs that matter

  • reference_image - your base image (what the target gets aligned to).
  • target_image - the image that gets warped.
  • max_features, match_ratio, ransac_threshold - the three knobs you'll actually touch when it fails. More features and a looser ratio help when the images share little texture.
  • target_mask (optional) - limits the output mask to a region of the target, so you control exactly where the overlap counts.
  • mask_grow, mask_blur, invert_input_mask, invert_output_mask - post-process the mask the node emits. Blur is the one worth setting for a soft seam.

Outputs

  • stitched_image - a canvas holding both images with the overlap included once. Wire this to a preview or save.
  • mask - where the target sits, in original-image coordinates, after any grow/blur/invert. Feed it to a composite if you want to do your own blending.
  • corrected_target - the target after its distortion was corrected (before warping), useful if you want the aligned result without the panorama.

Install

The pack installs like any custom node. Via ComfyUI Manager, search for "Pixel Snapping". Or:

cd ComfyUI/custom_nodes
git clone https://github.com/flywhale-666/ComfyUI_pixel_snapping
cd ComfyUI_pixel_snapping
pip install -r requirements.txt

Then restart ComfyUI completely - the README is explicit that a page refresh isn't enough after this pack changes its node ports. The one dependency to know about is opencv-contrib-python: SIFT lives in the contrib build of OpenCV, so if a node complains about cv2.SIFT_create missing, that's what's wrong.

Troubleshooting

  • "Feature points insufficient" - the images share too little texture, or one is blurry. Raise max_features (say 8000–10000), loosen match_ratio toward 0.85, and bump ransac_threshold. If two images genuinely have nothing in common, no parameter saves them.
  • It only processes the first image of a batch, silently. If you feed it a video frame stack expecting per-frame alignment, you get one output.
  • A huge mismatch in exposure can sink SIFT before it gets to color - matching the exposure first, or running this pack's Powerful Color Alignment afterwards, fixes the two problems in sequence.

It's a quiet, no-drama utility node, the kind that earns its keep in an automated batch rather than a showcase. Pair it with the mask crop/restore pair in the same pack when your "re-crop and re-render" loop drifts out of alignment.

Categoryimage/transform

Inputs (10)

NameTypeDefaultDescription
reference_imageIMAGE
target_imageIMAGE
max_featuresINT5000100–20000
match_ratioFLOAT0.750.1–1
ransac_thresholdFLOAT5.01–50
invert_input_maskBOOLEANfalse
mask_growINT0-50–50
mask_blurFLOAT0.00–50
invert_output_maskBOOLEANfalse
target_maskoptMASK

Outputs (3)

NameTypeDescription
stitched_imageIMAGE
maskMASK
corrected_targetIMAGE