ECHO Paired Surface / 回响·同材质配对取样
The node that tells ECHO which two patches are the same material
- source_sample
- reference_sample
- previous
- paired_surfaces
The node that changes nothing and decides everything
ECHO Paired Surface outputs no image. It doesn't touch a pixel. What it does is hand the rest of the pack a signed statement - "this patch of pavement in my source and this patch of pavement in my reference are the same material" - and that statement is the only thing that lets ECHO Outdoor Match run at all. Forget to wire it up and the outdoor node stops with an error rather than guessing.
This matters because of where the pack sits. Color matching is one of those post-processing primitives people bolt onto the end of a workflow - deterministic and instant, the honest alternative to re-rolling a generation because "the colors are off." But a whole-image average is a blunt instrument. Outdoors, the sky/ground/foliage ratio swings between two shots of the same outfit, so the average moves even when the subject lighting hasn't. ECHO's answer is to stop averaging and start measuring named surfaces you vouch for.
How it works
The node packages two mask tensors into the pack's own list type, ECHO_SURFACES. If you've wired SEGS around in a detector workflow, this is the same idea at a much smaller scale: a typed container you build up one entry at a time and pass along a wire. Each call appends one entry - a region (background or person), a unique name, and the source and reference sample masks converted to 8-bit grayscale - and the optional previous input lets you chain nodes so one Outdoor Match receives the whole batch.
Two things are worth internalising. First, the white in these masks is sample selection, not an edit scope - you're pointing at a small patch of evidence, not masking an area to be changed. Second, the node does no measurement itself; it just transports. The actual fitting happens downstream, in ECHO Outdoor Match, where each pair becomes one anchor and carries equal weight per anchor rather than per pixel area. A tiny sample of shade under a bench gets the same vote as a huge swath of sky, which is exactly why you're asked to spread samples across dark, mid and bright surfaces instead of painting one giant one.
The inputs that matter
source_sample/reference_sample(MASK): two tight patches of the same material, one per image. Same paving stone, same wall, same garment.region:backgroundorperson. Garments, skin and hair all follow thepersontransform.name: a label, unique inside its region. It shows up in the review report, so name it for the material (ground,stone-shadow,garment) rather thansample1.confirm_comparable_surface: must be ticked. Unticked, the node raisesConfirm that the two samples represent a comparable surface. That's the author making you take responsibility for a judgement the code can't make.previous(optional): the chain input, up to 32 pairs.
The only output is paired_surfaces, which goes into paired_surfaces on ECHO Outdoor Match. Nothing else consumes it.
Install
This is the whole pack, so you install the pack - no separate step for this node. Search ECHO in ComfyUI Manager (the pack declares ECHO · 回响, publisher sysyou, in its pyproject.toml), or clone it:
cd ComfyUI/custom_nodes
git clone https://github.com/x9c4gqtpv4-coder/ECHO.git
# use ComfyUI's OWN python, not a system one
python -m pip install -r ECHO/requirements.txt
Then restart and look for ECHO Paired Surface / 回响·同材质配对取样 under ECHO / 回响. One honest note: the repo's docs say a GitHub source update doesn't imply the Registry entry is in sync, so if Manager turns up nothing, clone it. requirements.txt is just numpy and Pillow - no model downloads, no GPU, no API key. The heavier optional extras (mediapipe, pymatting) aren't needed for this path.
Where people get burned
The failure that wastes the most time is the sample itself. Each pair needs at least 64 usable pixels after the match discards near-black and blown-out ones, and a sample that is more than half clipped fails outright with insufficient unclipped evidence. Pointing at a sun-bleached sky patch is the classic version of this. Samples also have to sit inside the confirmed region's core, not straddle the edge of the edit mask.
Then there's geometry. ECHO refuses to silently resize a mask: if your mask isn't the source image's size, or its batch count isn't 1 or the source batch count, you get a hard error rather than a quietly moved selection. Related trap - don't wire the alpha output of a Load Image node straight in; connect a real grayscale selection so white means what it says.
And mind the pairing itself. The node will accept a statement you shouldn't make. Grass and a green jacket are not the same surface, and a warm off-white object is not your neutral reference. The downstream report can flag contradictory samples at the same brightness, but it cannot un-pair a bad judgement call for you.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| source_sample | MASK | — | |
| reference_sample | MASK | — | |
| region | COMBO | 2 options: background, person | |
| name | STRING | same_surface | — |
| confirm_comparable_surface | BOOLEAN | false | — |
| previousopt | ECHO_SURFACES | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| paired_surfaces | ECHO_SURFACES | — |