Filter Tile SEGS
Stop Detailing the Same Face Twice
- segs
- segs
- excluded_segs
Here is the failure nobody models in a diagram. You tile a large image so you can render detail on a small GPU, and you run a detector on the tiles. A face sitting near a seam shows up in two tiles, so you get two SEGS entries describing the same face, each cropped to a different rectangle with a different amount of surrounding context. Feed both into DetailerForEach and the face is re-rendered twice with two different crops, at two different moments, and the second pass composites over the first. The result is the specific mush of double-denoised skin, plus twice the render time.
Filter Tile SEGS is the geometry filter that prevents it. It splits a tile-derived SEGS in two: the entries that own content no other crop contains, and everything else.
How it works
The node builds a coverage map of the whole canvas. For every segment's crop region it adds a rectangle to a 2-D difference array, then integrates it, which leaves each pixel holding a count of how many tile crops cover it. Pixels with a count of exactly 1 are that crop's unique territory - the part of the image only that tile ever sees. Those are the pixels where a detection is unambiguous.
Then, for each segment:
- If its cropped mask is entirely zero, it goes to the excluded pile immediately, in either mode. An empty detection is not a candidate.
- With
modeset to mask, the segment is kept if any nonzero mask pixel falls inside its unique territory. That is the honest test: the thing you detected is at least partly yours alone. - With
modeset to bbox, the segment is kept if its bounding box overlaps any unique-territory pixel. Looser, and appropriate when the SEGS came from a bbox detector that has no meaningful polygon.
Outputs are two SEGS: segs (the survivors) and excluded_segs. The second output is not trash - it is the overlap set, and if you drop it on the floor you have thrown away every detection that lives entirely in the seam.
Why the excluded output is worth wiring
The obvious use is to feed segs into your detail pass. The less obvious one is to hand excluded_segs to a second, cheaper pass, or to route it into the pack's Restore Tile SEGS Gaps node, which exists for the case where filtering leaves a hole: an entry excluded because it only touched shared territory can be exactly the thing that bridges two survivors, and restoring it is the difference between a continuous subject and a visible tile-shaped gap in your detail.
There is nothing image-aware here at all. "Content" in this node means mask pixels and box coordinates - it never looks at a tensor of pixels, so it is instant however big your canvas is, and it works on SEGS you built by hand just as well as on detector output.
Install
Part of ComfyUI-Utility-Suite. ComfyUI Manager → search ComfyUI-Utility-Suite → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite
Restart ComfyUI. You need Impact Pack (or anything that emits SEGS) for this node to have something to chew on - the suite consumes the SEGS structure but does not ship it. No model downloads; the declared dependency is opencv-python-headless, and the pack needs a recent ComfyUI because it is written against the V3 node API.
Traps
Validation is strict about crop regions. Every entry must have a crop_region that sits inside the declared canvas and is non-empty, and in mask mode the cropped mask must match its crop extent exactly. Malformed SEGS from a hand-rolled node will be rejected here by index - useful, and occasionally the reason a third-party SEGS producer will not cooperate.
The filter does not know what a tile is. It infers coverage purely from the crop rectangles in the SEGS you hand it. Assemble those SEGS from one tiled pass, not from mixed sources, or the coverage map will describe a mosaic that never existed.
Filtering removes detections from your detail pass, not from the image. If a face sits mostly in the seam and gets excluded, the tile that should have processed it still will, as long as you kept the complementary SEGS wired. The common mistake is lighting up the survivors and never routing the excluded set anywhere, then wondering why the seam region is flat.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| segs | SEGS | — | |
| mode | COMBO | 2 options: mask, bbox |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| segs | SEGS | — |
| excluded_segs | SEGS | — |