Nodes/PortraitUtils/Paired Image Loader
ComfyUI Node

Paired Image Loader

Load before/after pairs from two folders, in sync

By heyburns·Created 11 months ago·Updated 4 months ago· 1
Paired Image Loader
    • output_image
    • source_image
    • filename
    source_dir
    output_dir
    reversefalse
    strip_trailing_numbersfalse

    A/B comparison workflows live on pairs: here's the source scan, here's what the model did to it. Keeping those two images in lockstep across a whole folder is a chore - they're usually in different directories (originals/ and outputs/), with names that only loosely match, and one side always has more files than the other. PairedImageLoader is built for exactly this: point it at a source folder and an output folder, and each run it hands you the matching before/after pair as two synchronized IMAGE outputs.

    Inputs: source_dir and output_dir (the two folders), reverse (swap which folder is treated as source), and strip_trailing_numbers, whose tooltip says it plainly: Strip trailing " (n)" suffixes before matching. That toggle is the one that saves the day, because image processors love producing photo (1).png, photo (2).png while the originals are photo.png, photo_01.jpg - and by stripping the (n) before matching, the node pairs them on the true base name instead of failing to find a match.

    Outputs are output_image, source_image, and filename. source_image is whatever lives in the source folder, output_image is its partner, and filename is the shared base name. Every run advances to the next pair in natural-sort order, so running the graph repeatedly walks the folder set without you touching anything. It also carries state carefully - the match list is keyed by the two directories and the strip flag, so switching folders doesn't desync the pointer.

    Where this shines is QA loops: feed the pair into a ComparisonGate or a side-by-side preview, eyeball source-vs-result, and iterate. Because both images arrive together with a shared filename, your save node can write photo__restored.png next to photo.png and the pairing survives on disk too.

    Install

    Manager → search "PortraitUtils", or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/heyburns/PortraitUtils
    

    Restart. PIL + pathlib; no extra deps.

    Common issues

    • Pairs don't match up - filenames differ beyond the (n) suffix (e.g. one side has a prefix the other doesn't). The matcher is basename-based; fix the naming on one side or match in a pre-step.
    • "No pairs found" - either folder is empty, or the basenames genuinely don't overlap. Try strip_trailing_numbers on.
    • Source and output look swapped - flip reverse. That's literally what it's for.
    • It loads the same pair twice in a row - the index advances on each execution; if the graph re-executes the loader before the comparison branch finishes, you'll see repeats. That's a graph-timing thing, not a loader bug.

    If you do before/after passes at all - and every photo-restoration pipeline should - this removes the most tedious part of the loop.

    CategoryPortraitUtils/IO

    Inputs (4)

    NameTypeDefaultDescription
    source_dirSTRING
    output_dirSTRING
    reverseBOOLEANfalse
    strip_trailing_numbersBOOLEANfalseStrip trailing " (n)" suffixes before matching.

    Outputs (3)

    NameTypeDescription
    output_imageIMAGE
    source_imageIMAGE
    filenameSTRING