Nodes/ComfyUI CV/cv2.pointPolygonTest
ComfyUI Node

cv2.pointPolygonTest

Is this point inside my shape, and by how much

By bmad4ever·Created 4 months ago·Updated 15 days ago· 1
cv2.pointPolygonTest
  • contour
  • pt
  • float
◄measureDistfalse►

The API docs call it pointPolygonTest, which sounds like a unit test. It's a hit test: given a polygon and a point, tell me inside, outside, or exactly on the boundary - and optionally, how far away the boundary is in pixels.

Three inputs, one float out.

  • contour - an NPARRAY, "Polygon as (N,1,2) points (int32 or float32) - bridge a contour in with 'CV Contour To Points'". That's the important sentence in the whole node: this input is a point set, and the pack's NPARRAY-only sockets actively reject an IMAGE or MASK link here, because a picture is not a polygon. Get the points with CV Contour To Points, CV Find Contours, CV Detect Corners, CV Points, or the corner output of a quad detector.
  • pt - a CV_TUPLE: "(x, y) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place." It defaults to (0, 0), which is the top-left pixel, so wipe that default before you trust anything.
  • measureDist - a boolean, off by default (technically required in the schema, but it's a widget).

Output is a single FLOAT, and its meaning depends on that boolean. With measureDist off, you get +1 inside, -1 outside, 0 exactly on the edge. With it on, you get the signed distance in pixels: positive inside, negative outside, zero on the boundary. Same call, two very different answers - and the sign convention is worth internalising before you write any conditionals, because "outside" being negative rather than zero trips people up constantly.

What people use it for

Region tests on detected points. You've got boxes or landmarks and you want to know which ones are in a zone - a mask you defined once as a polygon. Draw it with CV Points (a literal list of vertices) or read it from a contour you found, then hit test. This is the "is the face inside the crop window" question, and it answers it exactly rather than by bounding-box overlap.

Distance to a boundary as a number. Run with measureDist on and you get a signed distance, which is a soft version of the same question: how close to the edge is this? Useful for feathering decisions, for "is this point comfortably inside or just barely", and for building your own implicit distance field one point at a time. The pack also has cv2.distanceTransform and CV Shape Distance if you want that field for a whole image instead of one point - read those before you loop this node over a million pixels.

Hit testing UI-ish things. Which button in a custom overlay panel did the click land on, where a click is a point coming from elsewhere in the graph. Rare in ComfyUI, but it's the same call.

The one thing to be clear about: this is a single-point query. One polygon, one point, one float. Testing a whole cloud means one node per point or a loop, and the pack has batch-ish alternatives for the common cases - CV Filter Points By Mask for "keep the points inside this mask", and CV Draw Polygon (or low-level cv2.fillConvexPoly) to turn a polygon into a mask and do the whole job in one raster pass. Reaching for the raster version is usually the right call; this node is for the one-point case where you'd otherwise be doing it by hand.

Gotchas

Layout matters. cv2 wants (N, 1, 2) int32 or float32. Contours stripped from a detector usually arrive in exactly that shape; if you reshaped something by hand you may end up with (N, 2) and the Python binding will give you the unhelpful "Overload resolution failed". CV Array Shape tells you which you've got.

The polygon is treated as closed. Your last vertex connects to your first - there's no "polyline vs polygon" mode, so a contour that's actually an open arc will be tested as if a line joined its ends.

A degenerate polygon is silent nonsense. Fewer than three distinct points, or three collinear ones, and every test returns whatever the math produced for a zero-area region. If everything reads as -1, check the vertex count with the count output of whatever produced the points.

Frame 0 only. No batch handling; this is a math node, and cv2 evaluates it once per call.

Installing

ComfyUI Manager → search ComfyUI CV → Install → restart:

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

Python ≥ 3.12 and a recent ComfyUI - the pack is built on the V3 node API, and its raw cv2 wrappers are generated at import from the functions your installed OpenCV actually has. pointPolygonTest is core cv2, present in every wheel; no contrib, no models, nothing to download. It lives under image/CV/low-level/cv2 P, and note it's cv2.pointPolygonTest in the menu, not "pointInPolygon" - the name is OpenCV's, and OpenCV spelled it that way.

Categoryimage/CV/low-level/cv2 P

Inputs (3)

NameTypeDefaultDescription
contourNPARRAY - - - A data array (points / matrix), NOT an image - only an NPARRAY link is accepted here.
ptCV_TUPLE0,0One value with 2 components (x, y) - it travels as a whole, so it cannot arrive half-connected. Wire it from 'CV Tuple' or type the components in place.
measureDistBOOLEANfalse - - -

Outputs (1)

NameTypeDescription
floatFLOAT—