CV Plot 2D (cv2.plot)
Turn a column of numbers into an image you can actually save
- values
- x_values
- plot
Charts inside ComfyUI are usually either interactive widgets (great for reading, useless for output) or a bunch of drawing nodes. CV Plot 2D takes the third path: it renders a plot as an ordinary IMAGE using cv2.plot.Plot2d, OpenCV's own plotting module. Because it's just an image, it composites, diffs, saves and stacks like anything else - which is exactly what you want when the plot is going into something: a report sheet, a video frame, a PNG that lands next to the data it describes.
It draws one series, with no legend and no labels. This is not the ECharts family - if you need several series, category names, tooltips or a threshold line, the pack's CV Chart Series / CV Chart Scatter / CV Chart Matrix nodes are the interactive, fancier option. Pick by destination: image out → this; inspect in the UI → those.
What goes in
values is the series. A 1-D array (or (N,1) / (1,N)) gets plotted against its sample index; an (N,2) array is read as x,y pairs. x_values (optional) overrides the x axis, ignored when values is already pairs. Larger values are drawn upward by default.
Then the layout: width (default 640) and height (default 400). Watch the clamps - cv2.plot itself clamps width up to 400 and height up to 300, so asking for a 200-wide plot gets you a 400-wide one. That's the module, not the node.
draw picks line (connects consecutive samples) or points only (marks them without segments). Points-only is the honest choice when the samples are independent measurements rather than a signal - joining them implies continuity you don't have.
Cosmetics are all optional widgets: line_width, show_grid, grid_lines, and the colors as BGR tuples (line_color (0, 255, 0), background_color (30, 30, 30), axis_color, grid_color, text_color). BGR, not RGB - the pack is consistent about this, but it's the kind of thing you'll get wrong once.
Two more that earn their place:
value_range-auto (data range)lets Plot2d fit the axes, which is convenient and hides how big the values actually are;manualpins the axes withmin_x/max_x/min_y/max_y. Manual is how you compare two runs side by side, and it's the reason those four inputs exist.print_point_index- annotates ONE sample's value onto the plot.-1is none. Perfect for calling out the winner in a comparison without a second annotation pass.y_down(default false) flips the axis so larger values go down. Worth knowing: this is the opposite of rawcv2.plot, whose own default draws downward - the node corrects it, so the default here matches every other plot in the pack.
One output: plot, an IMAGE (BGR converted to ComfyUI RGB) ready for Save Image or compositing.
Install
Manager → search ComfyUI CV, or:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install "opencv-contrib-python-headless~=5.0.0.93"
Restart. Python ≥ 3.12, V3 node API. Plot2d is a cv2 class that only accepts float64, which the node handles for you - feed it whatever dtype you have.
Common issues
- Blank or empty plot - either the input was empty (which renders an empty plot rather than failing) or the values are all identical and the auto range collapsed. Use
manualrange to check. - Your requested size was ignored - the 400/300 clamps above.
- The colors are wrong - BGR tuples. Swap the first and third numbers.
- Multiple series came out only once - one series per node. Use
CV Chart Seriesif you need more, or stack images. - Values went the wrong way up -
y_downis off by default specifically so this node doesn't inherit cv2.plot's downward convention. If you turned it on for image-coordinate data, that's why.
Pack disclaimer as usual: LLM-assisted, personal, not production-grade, no promised updates. The nice thing about a plot is that a wrong one usually looks wrong.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| values | NPARRAY | The numbers to plot: 1-D (or (N, 1) / (1, N)) is plotted against the sample index; an (N, 2) array is read as x, y pairs. Converted to float64, which is the only dtype Plot2d accepts. Larger values are drawn UPWARDS (see y_down). | |
| width | INT | 640400–4096 | Plot width in pixels. cv2.plot CLAMPS anything below 400 up to 400 - that is the module, not this node. |
| height | INT | 400300–4096 | Plot height in pixels; clamped up to 300 minimum by cv2.plot itself. |
| draw | COMBO | line | 'line' connects consecutive samples; 'points only' marks them without the connecting segments - the honest choice when the samples are independent measurements rather than a signal. |
| x_valuesopt | NPARRAY | Optional x coordinate per sample (same length as values). Without it samples are plotted against their index. Ignored when values is (N, 2). | |
| line_widthopt | INT | 11–16 | Stroke width of the plotted line in pixels. |
| show_gridopt | BOOLEAN | true | Draw the background grid. |
| grid_linesopt | INT | 101–100 | Number of grid divisions when the grid is shown. |
| show_textopt | BOOLEAN | true | Draw the axis value texts (the min/max readouts cv2.plot prints along the axes). |
| value_rangeopt | COMBO | auto (data range) | 'auto' lets Plot2d fit the axes to the data - which hides how big the values are in absolute terms. 'manual' pins the axes so two plots of different runs are comparable. |
| min_xopt | FLOAT | 0.00-1000000000–1000000000 | Left edge of the x axis ('manual' range only). |
| max_xopt | FLOAT | 1.00-1000000000–1000000000 | Right edge of the x axis ('manual' range only). |
| min_yopt | FLOAT | 0.00-1000000000–1000000000 | Bottom of the y axis ('manual' range only). |
| max_yopt | FLOAT | 1.00-1000000000–1000000000 | Top of the y axis ('manual' range only). |
| line_coloropt | STRING | (0, 255, 0) | Series color as a BGR tuple, e.g. '(0, 255, 0)'. |
| background_coloropt | STRING | (30, 30, 30) | Plot background color, BGR. |
| axis_coloropt | STRING | (200, 200, 200) | Axis line color, BGR. |
| grid_coloropt | STRING | (70, 70, 70) | Grid line color, BGR. |
| text_coloropt | STRING | (230, 230, 230) | Axis text color, BGR. |
| print_point_indexopt | INT | -1-1–1000000 | Prints the value of ONE sample onto the plot: the index to annotate, or -1 for none. Useful to call out the winner of a comparison. |
| y_downopt | BOOLEAN | false | Flips the y axis so larger values go DOWN, matching image coordinates (or a cost/error where lower is better). Off - the default - draws larger values UP, like 'CV Chart Series' and every other plot. Note this is the OPPOSITE of raw cv2.plot, whose own default draws downward; the node corrects it. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| plot | IMAGE | The rendered plot as a normal IMAGE (BGR converted to ComfyUI RGB), ready for Save Image, compositing or stacking next to the data it describes. |