Nodes/ComfyUI CV/CV Coordinate Grid
ComfyUI Node

CV Coordinate Grid

See what your classifier actually thinks

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Coordinate Grid
    • points
    • cols
    • rows
    • count
    ◄width224►
    ◄height224►
    ◄step2►

    What it's for

    The pack has a small machine-learning corner: CV Train Classifier, CV Predict Classifier, CV Deep Features. Train one on pixel colours or features, and you get numbers back - but "94% accuracy" tells you nothing about where the classifier is wrong. Does it carve the image into clean regions, or is it slicing noise through the middle of your subject?

    This node answers that by brute force. It hands you every sample position on a grid; you ask the classifier what each position is; you reshape the answers into a picture. The picture is the decision boundary. It's a genuinely useful debugging move, and it takes about four nodes.

    How it works

    CV Coordinate Grid builds a meshgrid of pixel coordinates over a width × height canvas at a fixed step, ordered row-major: y outer, x inner. So row 0 is every x position at y=0, row 1 is every x at y=step, and so on. That ordering isn't cosmetic - it's the same order you'll reshape the classifier's answers back into, and getting it backwards gives you a transposed map that still looks plausible.

    Four outputs, and the small ones matter as much as the array:

    • points - Nx1x2 float32 (x, y) coordinates. This is what goes into the classifier's query_features.
    • cols - number of x positions.
    • rows - number of y positions.
    • count - rows * cols.

    Those three integers exist so you never type the grid math by hand. Wire rows and cols into CV Reshape Array and the dimensions are always the ones the classifier was actually asked about.

    The inputs that matter

    • width, height - the canvas in pixels, 1 to 8192, default 224.
    • step - grid spacing in pixels, default 2, range 1 to 1024. This is the cost knob: step=1 classifies every single pixel, step=2-4 is plenty for a preview.

    Do that arithmetic before you run it. A 224×224 canvas at step=2 is a 112×112 grid - 12,544 samples, each one a classifier call. At step=1 it's 50,176. The node's own tooltip warns that 1 is "slow to classify", and it means it.

    Typical wiring, from the node's description: points → CV Train Classifier's query_features → predictions → CV Reshape Array with rows/cols → CV Color Map to paint it. Workflow 80_ml_decision_boundary.json in the repo does exactly this if you want a reference.

    Install

    ComfyUI Manager, search ComfyUI CV, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/bmad4ever/comfyui_cv
    

    Restart afterwards. Needs Python ≥ 3.12, a recent ComfyUI (V3 node API) and the contrib OpenCV wheel:

    pip install "opencv-contrib-python-headless~=5.0.0.93"
    

    Where people get burned

    The transpose trap. Use the node's rows and cols outputs rather than typing numbers, because row-major ordering means a (rows, cols) reshape is right and a (cols, rows) reshape silently gives you the mirror of your boundary. The map looks fine. It's just wrong.

    The grid is in canvas pixels, not output pixels. After the reshape you have a rows × cols image - a coarse map, not a full-size overlay. If you want it on top of the original frame, scale the class map (or the source) back to width × height with a resize; the pack's CV Transform or the raw cv2_resize will do it.

    Features have to come from somewhere. The grid gives positions and nothing else. What the classifier is asked about at those positions is your job - sample the image at those points, or feed whatever feature array your pipeline builds. A grid of positions with no features behind it just classifies zeros.

    Every sample is a real call. People set step=1 on a 4K canvas and assume it's free. It isn't. Preview at step=4, then drop it for the final render.

    On this pack generally: it's a GPL-3.0 fork of geroldmeisinger's opencv-comfyui, written by bmad4ever as a personal project, generated with substantial LLM assistance, and the README says outright not to trust it in production without reading the code and testing it yourself. The node-registry is also generated from whatever OpenCV build is installed, which is why the contrib wheel matters - swap in a non-contrib opencv-python and a chunk of this pack stops existing.

    Categoryimage/CV/ml

    Inputs (3)

    NameTypeDefaultDescription
    widthINT2241–8192Canvas width in pixels the grid covers (x goes 0, step, 2*step, ... below width).
    heightINT2241–8192Canvas height in pixels the grid covers (y goes 0, step, 2*step, ... below height).
    stepINT21–1024Grid spacing in pixels. 1 = every pixel (slow to classify); 2-4 is plenty for a preview.

    Outputs (4)

    NameTypeDescription
    pointsNPARRAYNx1x2 float32 (x, y) grid coordinates, row-major: N = rows * cols. Feeds query_features of 'OpenCV Train Classifier'.
    colsINTGrid columns = number of x positions. Use as the cols of 'CV Reshape Array' on the predictions.
    rowsINTGrid rows = number of y positions. Use as the rows of 'CV Reshape Array' on the predictions.
    countINTrows * cols.