CV Points To Contour
The adapter between cv2's output and the contour nodes
- points
- contours
- count
A small type bridge, and exactly the kind of node that saves you an hour. Half of OpenCV's contour work produces plain arrays; the other half consumes OpenCV's contour type. This joins them.
What it's for
cv2.findContours returns a Python list of point arrays, which bare function wrappers can't represent, so this pack carries a CV_CONTOURS type for the contour nodes - select, filter, measure, draw. Meanwhile a bunch of useful operations produce something that is geometrically a contour but technically just an NPARRAY of points: a cv2.convexHull result, a cv2.intersectConvexConvex intersection, four corners you typed into CV Points, a hull of detections. Those cannot be fed to the contour nodes as-is. This node converts them.
The practical use, most of the time, is drawing. You compute a hull or a hand-picked polygon with cv2, bridge it here, and feed CV Draw Contours to render it onto the image. The other direction exists too - CV Contour To Points - so you can go round the loop: detect, convert to points, do arithmetic on the coordinates, convert back, draw.
How it converts, and the one detail that matters
Contours in OpenCV live on the integer pixel grid: each point is int32. Your input array can be any numeric dtype, including the float32 subpixel coordinates a corner-detector or a homography produces, so this node rounds to int32 on the way in. For drawing and area measurement that's fine and expected. For anything where half-pixel precision is load-bearing - sub-pixel corner refinement, then measuring an angle - you've just thrown that precision away, so do the maths on the array side and only convert when you're ready to draw.
Inputs and outputs
points is the only input, and it is forgiving about layout: (N,2), (N,1,2) or (1,N,2), any numeric dtype. The contours output is a one-contour set - one outline, which is what a single point array is. count is how many points that contour holds, not how many contours came out, so it reads 0 for an empty input rather than an empty set count of 1. Wire it to a text preview when a downstream contour node is complaining: 3 points is the minimum that makes a polygon, and two points will round-trip through this node happily and then misbehave in the drawing node.
None or an empty array gives you an empty set with count = 0 and no error. That's deliberate - the pack is uniformly failure-tolerant on empty inputs, which matters when a detector upstream legitimately finds nothing on some frames.
Installing
Same pack-wide install. ComfyUI Manager → search "ComfyUI CV", or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
# restart ComfyUI
Python ≥ 3.12, a recent ComfyUI on the V3 node API, and the pinned OpenCV contrib build:
pip install "opencv-contrib-python-headless~=5.0.0.93"
Gotchas
Install it as a contrib wheel and only that. All OpenCV distributions share site-packages/cv2, so dropping a non-contrib opencv-python on top of a contrib install silently strips the contrib submodules and a chunk of this pack's nodes vanish from the menu. The pack ships a diagnostic for it:
python tools/repair_opencv_contrib.py --check
And keep expectations calibrated. This node doesn't clean anything up: an open polyline stays an open polyline, a self-intersecting point order stays self-intersecting, and duplicated points stay duplicated. It converts a type. If your drawn outline looks wrong, the points were wrong before they got here.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| points | NPARRAY | (N,2), (N,1,2) or (1,N,2) point array, any numeric dtype (subpixel coordinates are rounded). |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| contours | CV_CONTOURS | A 1-contour set (empty when the input is None/empty). |
| count | INT | How many points the contour holds. |