YOLO BBox Coordinates
Detect anything, get exact pixel coordinates — no Impact Pack required
- image
- annotated_image
- bbox_json
- x1
- y1
- x2
- y2
- width
- height
- center_x
- center_y
- confidence
- label
- class_id
- box_count
Most YOLO nodes in ComfyUI hand you a pretty picture. This one hands you numbers. YOLO BBox Coordinates runs an Ultralytics model over your image and returns the actual pixel coordinates of every detection - x1, y1, x2, y2, width, height, center, confidence, label - plus the red-boxed annotated image and a machine-readable JSON blob. If your workflow only needs "where is the person," not "refine the person's face," this is the node you reach for.
The README is refreshingly honest about why it exists: it's a lightweight replacement for the Impact Pack SEGS chain when the only thing you want out of it is bounding boxes. In Impact Pack you wire a BBOX detector into a SEGS producer, then pull coordinates out of the segments. That's a lot of machinery for a number. This node does the whole detection in one shot, no SEGS dependency, no Impact Pack install.
How it works
This is the part people get burned on with other YOLO nodes, and the author built around it. ComfyUI images are BHWC float tensors; Ultralytics expects BCHW inputs divisible by stride 32. Feed it a 1200x672 tensor directly and you get the classic "torch.Tensor inputs should be BCHW ... divisible by stride 32" error. YOLO BBox Coordinates sidesteps the whole mess by converting each image to a numpy uint8 HWC array and passing that to model.predict(), letting Ultralytics handle resizing and padding internally. Coordinates are then converted back into original pixel space and clamped to the image bounds.
The model is loaded once and cached by resolved path, so you're not reloading yolo11m.pt every run. The annotated output is a copy - the input tensor is never mutated.
The inputs that matter
image- the only required input. Any ComfyUI IMAGE.model_path- defaults tobbox/yolo11m.pt. The node checks the absolute path, thenComfyUI/models/ultralytics/<path>, thenComfyUI/models/<path>, then a relative path. If it can't find the file it raises a clear error listing every place it looked.class_filter- defaults toperson. Comma-separated names or numeric class IDs (person,caror0,2). Empty string means all classes.conf(0.25) andiou(0.70) - the usual detection and NMS thresholds. Leave them alone until you know what you're doing.sort_by/sort_order/selected_index- this trio is the actual superpower.
The selected-index trick
The scalar outputs (x1, y1, x2, y2, width, height, center_x, center_y, confidence, label, class_id) don't describe "the detection." They describe one detection: the one at selected_index after sorting by sort_by in sort_order. Set sort_by=x1, sort_order=ascending, selected_index=0 and the node becomes "leftmost person." Swap to area + descending and it's "biggest person." Second person from the left is just selected_index=1. That's the thing to remember - these outputs are one box, deliberately, so you can wire them straight into a crop, a regional prompt, or a bounding-box primitive.
For everything else there's bbox_json - a stable, parseable JSON with every detection for every image in the batch. The scalar outputs only ever refer to the selected box from the first image; if you're driving a batch, read the JSON.
box_count is the number of boxes found in the first image.
Installing it
From ComfyUI Manager, search "ComfyUI-Ultralytics-YOLO-BBOX-Coordinates". Or the old-fashioned way:
cd ComfyUI/custom_nodes
git clone https://github.com/kayselmecnun/ComfyUI-Ultralytics-YOLO-BBOX-Coordinates.git
Restart ComfyUI. Dependencies are ultralytics, numpy, pillow, torch - if your environment lacks ultralytics, pip install ultralytics. That's the heavy one, and it's AGPL-3.0 with a real supply-chain history (a poisoned December 2024 release shipped a cryptominer through ComfyUI). Pin ultralytics to a version you trust rather than letting it float.
The model does not download itself. Drop any YOLO .pt in - for the default path, ComfyUI/models/ultralytics/bbox/yolo11m.pt - or point model_path at one you already have.
Gotchas
- Class filter typos are silent-ish. A name not in the model prints a console warning, and if nothing resolves, detection is skipped entirely - you get zero boxes, not "all boxes." Empty string = all classes; typo = nothing.
- No detections → original image returned unchanged, coordinates 0,
confidence0.0,class_id-1,label"". Wire those straight into a crop and you'll crop a corner of nothing, so checkbox_countfirst. imgszsteps by 32 and defaults to 640 - standard, no need to touch.
It's a narrow, one-job tool: find boxes, hand you numbers, get out of the way. For that job it's the cleanest option in the ecosystem, and it saves you from installing Impact Pack just to count people.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| model_path | STRING | bbox/yolo11m.pt | — |
| class_filter | STRING | person | — |
| conf | FLOAT | 0.250–1 | — |
| iou | FLOAT | 0.700–1 | — |
| imgsz | INT | 64032–4096 | — |
| device | STRING | cuda:0 | — |
| half | BOOLEAN | false | — |
| sort_by | COMBO | 8 options: x1, center_x, x2, y1, center_y, y2, +2 | |
| sort_order | COMBO | 2 options: ascending, descending | |
| selected_index | INT | 00–100000 | — |
| max_boxes_json | INT | 500–100000 | — |
Outputs (14)
| Name | Type | Description |
|---|---|---|
| annotated_image | IMAGE | — |
| bbox_json | STRING | — |
| x1 | INT | — |
| y1 | INT | — |
| x2 | INT | — |
| y2 | INT | — |
| width | INT | — |
| height | INT | — |
| center_x | FLOAT | — |
| center_y | FLOAT | — |
| confidence | FLOAT | — |
| label | STRING | — |
| class_id | INT | — |
| box_count | INT | — |