Nodes/ComfyUI CV/CV Chart Scatter
ComfyUI Node

CV Chart Scatter

CV Chart Scatter for k-means centres and feature vectors

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
CV Chart Scatter
  • points
  • classes
  • spec
◄title►
◄class_names►
◄point_names►
◄y_downfalse►
◄point_size10►
◄x_axis_name►
◄y_axis_name►
◄palettecolorblind-safe (Okabe-Ito)►
◄themedark►
◄decimals3►
◄chart_height340►

What this is for

Point data shows up all over a CV workflow: k-means cluster centres, PCA-projected feature vectors, keypoint coordinates, per-tile scores from a grid. The pack has CV Draw Points, which stamps points onto the image they came from - perfect when the question is "where on this frame". CV Chart Scatter answers the other question: "how do these points relate to each other". Two clusters overlapping, an outlier sitting miles from everything, a sweep that turns out to be monotonic - that's a plot, not an annotated photo.

It's an interactive Apache ECharts scatter drawn inside the node. Hover reads a point's name and exact coordinates, box-zoom gets you into a cluster, and the toolbar saves a PNG.

How it works

Everything that decides what the plot says - series, legends, class colours, axis names, formatting - is assembled in Python as an ECharts option, then handed to web/cv_charts.js, which only instantiates the chart. The same option comes back out as the spec STRING, so the plot is inspectable as text and testable without a browser.

The inputs that matter

points is the required array: (N, 2) x/y coordinates, and (N, 1, 2) - the shape the pack's point nodes emit - is accepted as-is. An empty array is valid and draws an empty plot, which is a deliberate choice: a failed detector upstream shouldn't turn into a red node.

classes is the optional one that earns its place. Give it an integer label per point (k-means labels, classifier predictions, which method a score came from) and the points split into one coloured, legend-named series per distinct value. class_names names those values in ascending order - JSON list, or ;/newline/comma text. point_names gives each point a tooltip name, one per point in the same order, which is how you get from "that dot is odd" to "that dot is tile 37".

Then two that quietly change whether the plot is honest:

  • y_down - turn it on when your coordinates are pixel positions. Image y grows downwards, and a scatter that doesn't know that will show you a mirror image of your layout. Leave it off for feature space, where you'd only be flipping a plot for no reason.
  • palette - the default is the colourblind-safe Okabe-Ito set, which is the right default for unordered classes. The sampled ramps are for ordered classes (a sweep, a rank), where the reader should be able to tell neighbouring classes apart by hue distance.

Presentation: point_size, x_axis_name/y_axis_name (worth filling in - an unlabelled axis is a guess), theme, decimals (trailing zeros dropped) and chart_height.

Output is spec, and the node is an output node, so the chart draws when you queue. Preview as Text on spec is the lazy way to read the plotted coordinates.

Install

Same pack, same steps:

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

ComfyUI Manager users: search ComfyUI CV (publisher bmad4ever). Needs Python ≥ 3.12, a ComfyUI recent enough for the V3 node API, and opencv-contrib-python-headless~=5.0.0.93 (in requirements.txt). Nothing to download for this node.

Common issues

  • classes length mismatch. It must have one label per point - that's the one place this node will complain instead of coping.
  • Blank chart area after install or update. Reload the page; the frontend half of this node is a JS module and a cached tab won't load it.
  • Y axis is upside down. Check y_down before you go debugging your detector. If the coordinates came out of pixel space, this is the setting.
  • A whole class of nodes vanished from the pack. Something overwrote site-packages/cv2 with a non-contrib OpenCV wheel. Diagnose and repair with tools/repair_opencv_contrib.py --check / --apply.
Categoryimage/CV/plots

Inputs (13)

NameTypeDefaultDescription
pointsNPARRAY(N, 2) x/y coordinates; (N, 1, 2) - the shape the point nodes emit - is accepted as-is. Empty is valid and draws an empty plot.
titleSTRINGHeading drawn above the chart. Empty draws none.
classesoptNPARRAYOptional integer label per point (k-means labels, classifier predictions): points are grouped into one colored, legend-named series per distinct value. Length must match the point count.
class_namesoptSTRINGNames for the class values, in ascending value order, as a JSON list or ';' / newline / ',' separated text. Defaults to 'class 0', ...
point_namesoptSTRINGName per point (same order as points), shown in the tooltip - use the same label list that names the matching image tiles.
y_downoptBOOLEANfalseFlip the y axis so it grows downwards, matching image/pixel coordinates. Leave off for ordinary feature-space data.
point_sizeoptINT102–60Marker diameter in pixels.
x_axis_nameoptSTRINGCaption under the x axis (what x measures).
y_axis_nameoptSTRINGCaption beside the y axis (what y measures).
paletteoptCOMBOcolorblind-safe (Okabe-Ito)Class colors. The sampled ramps suit ORDERED classes (a sweep, a rank); the fixed palettes suit unordered ones.
themeoptCOMBOdarkChart colors. 'light' is for a PNG that will be pasted into a document.
decimalsoptINT30–8Decimals shown for the coordinates in the tooltip. Trailing zeros are dropped.
chart_heightoptINT340160–2048Height of the chart area inside the node, in pixels.

Outputs (1)

NameTypeDescription
specSTRINGThe chart definition as JSON - the exact option the frontend renders. Wire into 'Preview as Text' to read the plotted coordinates.