Nodes/ComfyUI CV/cv2.rapid.extractLineBundle
ComfyUI Node

cv2.rapid.extractLineBundle

The strip of pixels RAPID searches along, as an array

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.rapid.extractLineBundle
  • ctl2d
  • img
  • bundle
  • locations
◄len0►

Edge-based model tracking works by sampling the image along short lines perpendicular to a model's projected silhouette and looking for the strongest intensity gradient on each one. This node does the sampling. It takes the control points from the previous stage and returns two things: the intensities along every search line, and the pixel coordinates those intensities were read from.

The two outputs

  • bundle - the pack's return documentation describes it precisely: a num × (2*len+1) × 3 array of image intensities sampled along each control point's silhouette-normal search line. So for each of your num control points you get a strip of 2*len+1 samples, each with three channel values. It's a stack of little 1D image profiles - which is exactly what you'd want to look at if you suspected the search was picking up the wrong thing.
  • locations - the pixel coordinates of those samples. This is the half people forget about, and it's the input to rapid.drawSearchLines, which renders them over the frame so you can see where the algorithm is actually looking.

bundle and locations are the pair that keeps the geometry and the intensities in lockstep. Any stage downstream that consumes the intensities needs the coordinates if it's going to produce image points, which is what rapid.convertCorrespondencies does: bundle + the matched locations → pts2d (the pixel each line landed on) plus a validity mask.

Inputs

  • len - the half-length of each search line in pixels. It's the single most consequential number in a RAPID round, and the pack's own guidance is unambiguous: too short and the line never reaches the real edge; too long and it finds background clutter. Typical values are on the order of 10–30 px for a subject occupying a decent part of the frame - but the honest answer is that it depends on how far off your incoming pose is, because the search has to be long enough to reach the edge the pose thinks is nearby.
  • ctl2d - the control points in image space, straight from rapid.extractControlPoints' ctl2d output. They carry the silhouette-normal directions with them, which is why this node doesn't need the mesh.
  • img - the frame to sample. This is the image the tracker is looking at, at the resolution the control points were computed for. Mismatch here is a silent disaster: the samples will be read from the wrong pixels and the "gradients" will be pure noise.

Output → next step

Wire bundle into the matching stage (rapid.findCorrespondencies in the raw set, or your own gradient search), and locations into rapid.convertCorrespondencies. For debugging, hand locations to rapid.drawSearchLines with the same frame as the canvas and a colour literal in BGR ("(0, 255, 0)" for green) - it's the fastest way to see whether your search geometry is sane. All three drawing nodes in this family return NPARRAY, so you'll need CV Array → Image before anything previews.

The whole round, if you want it as one node: CV Rapid Pose Refine in the pack's subgraph library, or the curated CV Rapid Track (Sequence) to run the loop across a batch of frames with the pose warm-started from frame to frame.

Install

Part of ComfyUI CV (bmad4ever). ComfyUI Manager, search comfyui_cv, or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Then restart ComfyUI. Python ≥ 3.12 and a recent V3-API ComfyUI are required. No models.

Common issues

The node isn't listed. cv2.rapid is an opencv-contrib module. Installing opencv-python over opencv-contrib-python silently removes contrib submodules from the shared cv2 package and the pack skips those entries at import. python tools/repair_opencv_contrib.py --check in the pack folder, then --apply.

Every search line finds "an edge" and the pose drifts. Classic too-long len: the line is reaching a background boundary. Shorten it, and check with rapid.drawSearchLines that the lines are crossing the object's outline at something close to a right angle rather than glancing along it.

Nothing ever matches. The opposite failure: the silhouette isn't near the object (pose too far off, or the mesh isn't in the pose's coordinate frame). RAPID refines an existing pose - it doesn't find one from scratch. If you have no starting pose at all, get a global estimate first with CV PPF Pose Estimation, then refine.

The bundle is enormous. It scales with num × len. Hundreds of control points with 60-pixel search lines is a big array to push around a graph, and on a clip it's per frame. Keep num modest unless you're actually debugging.

Categoryimage/CV/low-level/rapid

Inputs (3)

NameTypeDefaultDescription
lenINT0-2147483648–2147483647 - - -
ctl2dNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
imgNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.

Outputs (2)

NameTypeDescription
bundleNPARRAY—
locationsNPARRAY—