Nodes/ComfyUI CV/CV Grid Points
ComfyUI Node

CV Grid Points

The object points solvePnP needs and you can't type

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
CV Grid Points
    • points
    • count
    ◄cols9►
    ◄rows6►
    ◄spacing1.00►
    ◄z0.00►

    Every pose-estimation call in OpenCV takes two matched point sets: where the points are in the image, and where they are in the world. The first you get from a detector. The second you have to construct - a 9×6 chessboard is 54 points × 3 coordinates, and nobody is typing that into a widget. This node generates it.

    One of the hand-written helpers in bmad4ever's ComfyUI CV (bmad4ever/comfyui_cv, a fork of Gerold Meisinger's opencv-comfyui) - a pack of ~470 auto-generated raw cv2.* wrappers plus curated nodes that do the multi-step plumbing. It's pure numpy, and it's the quiet prerequisite for board pose, AR overlay and calibration examples.

    Inputs

    cols (9) - points per row, i.e. the chessboard's inner corners per row. rows (6) - points per column. spacing (1.0) - the distance between adjacent points, i.e. the square size. Set it in millimetres and your poses come out in millimetres; leave it at 1.0 for relative/unit geometry, which is what you want if you're only drawing an overlay and don't care about absolute scale. z (0.0, advanced) - a constant plane height for every point. Leave it at 0 for a flat board on the z=0 plane.

    Outputs

    points - (cols * rows) x 1 x 3 float32, row-major. count - the number of points, for sanity checks and for matching against how many corners your detector returned.

    That row-major ordering is not cosmetic. It's built to match the order cv2.findChessboardCorners reports corners in - (0,0,z), (1,0,z), … - and the pairing is the whole ballgame. If the object points and the image points are in different orders, solvePnP doesn't error; it returns a pose that is confidently, plausibly wrong. You'll get a cube floating at the wrong angle and assume your camera matrix is off.

    What you wire it into

    Object points in one hand, image points in the other, camera matrix in the third:

    • cv2_solvePnP (or the pack's CV Solve PnP (Pose) / (All Poses) nodes) to recover the board's pose - the standard path to an AR overlay.
    • CV Calibrate Camera (Chessboard) or its fisheye sibling if you're calibrating rather than posing (those nodes build their own grids internally, so this is for the pose case and for anything you're wiring by hand).
    • cv2_projectPoints with the recovered rvec/tvec to draw a virtual object on the board. The pack's planar-AR examples do exactly that: grid points, detected corners, a pose, then a projected cube. workflows/exercise_ar_planar_cube.json, workflows/exercise_ar_planar_video.json and workflows/57_camera_pose_3d_preview.json are the working versions.

    For a non-regular point set - the corners of a virtual cube, click locations on a model - use CV Points instead, which takes a Python list literal.

    Install

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

    Or search ComfyUI CV in ComfyUI Manager. Python ≥ 3.12 and a recent ComfyUI with the V3 node API. Example inputs (the chessboard images, MilkTruck.glb for the AR demos) live in example_inputs/ and are copied into ComfyUI/input by running workflows/01_install_example_inputs.json once - then reload the page, because the Load dropdowns are built from what's in input when node definitions load.

    Common issues

    A plausible but wrong pose. Order mismatch, or a cols/rows swap. Inner corners, remember - squares minus one on each axis - and if your detector reports 54 corners for a board you've described as 6×9, the count output here will tell you immediately.

    The overlay is the right shape at the wrong size. spacing doesn't match the physical square size, so your translation vector is in the wrong units. Only matters if you're mixing with a metric depth map or another measurement; for a pure overlay, leave it at 1.0.

    Nothing detected on the board at all. Nothing to do with this node - that's detection thresholds and lighting. Check the corner-detector node's own found first, since this node will happily hand you a correct grid for points that don't exist.

    Non-planar geometry. z is a constant, so this is a planar grid by construction. A 3D calibration object needs CV Points and a typed list.

    Categoryimage/CV/low-level

    Inputs (4)

    NameTypeDefaultDescription
    colsINT91–1000Points per row (e.g. chessboard inner corners per row).
    rowsINT61–1000Points per column (e.g. inner corners per column).
    spacingFLOAT1.000.000001–1000000Distance between adjacent points (e.g. the square size in mm). 1.0 = unit / relative coordinates.
    zoptFLOAT0.00-1000000–1000000Constant plane height for every point (0 = a flat board on the z=0 plane).

    Outputs (2)

    NameTypeDescription
    pointsNPARRAY(cols*rows)x1x3 float32 grid points, row-major.
    countINT—