ComfyUI Node

NMS

How your detector stops drawing fifty boxes on one dog

By Cynthia-lxx·Created 2 months ago·Updated 2 days ago· 6
NMS
  • boxes
  • scores
  • keep_indices
iou_threshold0.50

Every real object detector fires way more boxes than it needs - a dozen overlapping rectangles all pointing at the same dog, each with a confidence score. Non-Maximum Suppression is the thing that collapses them into one clean box, and CdlNms is ComfyDL's textbook-clean implementation of it. If you've built a detection pipeline in this pack (anchor boxes in, class probabilities out), this is the node that makes the output actually presentable.

This is a direct port of the nms function from Dive into Deep Learning, the textbook the whole pack is built on. It's a great way to finally internalize what NMS does, because you can watch it happen on a real image step by step.

How it works

The algorithm is refreshingly simple, and the source makes it visible:

  1. Sort all boxes by score, best first.
  2. Take the top box, keep it.
  3. Compute IoU between it and every remaining box; drop any that overlaps it more than iou_threshold.
  4. Repeat with the next-best surviving box.

That's it. Greedy, fast, and surprisingly effective. The node returns the indices of the boxes that survived - not the boxes themselves - so you keep the mapping back to your original array.

The inputs that matter

  • boxes - [N, 4] corner-format boxes (x1, y1, x2, y2).
  • scores - a matching confidence score per box.
  • iou_threshold - the only widget, default 0.5. Lower it toward 0.3 and you suppress more aggressively (fewer boxes, risk of merging distinct objects); raise it toward 0.7 and you keep more overlap.

Where people get burned: the IoU threshold default of 0.5 is the classic value, but if your boxes are small or your objects are dense, 0.5 can merge two things sitting close together. When you see one label swallow a neighbor, nudge the threshold up rather than assuming the model is broken.

Output

keep_indices - a torch.int64 tensor of the surviving box indices, sorted by score. In the ComfyDL world that's a cdlTensor, so it flows into the pack's other detection and visualization nodes. A typical end-to-end: Multibox Detection already runs NMS internally, so this standalone node is for the case where you have raw boxes + scores - say, thresholded class probabilities you want to turn into final detections - and you want the surviving picks to feed Show BBoxes.

Installing ComfyDL

ComfyDL is one pack with a light install - its only extra dependency is matplotlib:

cd ComfyUI/custom_nodes
git clone https://github.com/Cynthia-lxx/ComfyDL
cd ComfyDL && pip install -r requirements.txt

Restart ComfyUI and look under the ComfyDL → ObjectDetection menu. ComfyUI Manager users can just search "ComfyDL". No models to download - nothing here touches a checkpoint.

The trap to remember

NMS is per-image and operates on a flat [N, 4] tensor. If your boxes come out of a batch-shaped tensor with a leading dimension, squeeze it first, or you'll be sorting IoUs against a whole batch's worth of boxes as if they were one image. It's the single most common shape mistake with this node, and the error messages won't tell you why - you'll just get nonsense indices.

Categoryd2l/ObjectDetection

Inputs (3)

NameTypeDefaultDescription
boxesTENSOR
scoresTENSOR
iou_thresholdFLOAT0.500–1

Outputs (1)

NameTypeDescription
keep_indicesTENSOR