Nodes/ComfyUI CV/CV Slice Array
ComfyUI Node

CV Slice Array

Numpy slicing as a node, one axis at a time

By bmad4ever·Created 4 months ago·Updated 14 days ago· 1
CV Slice Array
  • nparray
  • nparray
◄axis0►
◄start0►
◄stop0►
◄step1►
◄keep_axistrue►

Every CV graph eventually needs a slice of an array: crop a padded result back to its original size, pull a column out of a detection table, take every third row, flip an axis. In pure numpy that's one line; in a graph it's a node.

CV Slice Array exposes numpy slicing with a widget per parameter, and the source comment says why it got built: the pack kept working around the lack of it, notably in a Draw Labels chain that needed Permute → Take By Index → Permute just to get a column out of an (N,4) table. Now it's start=2, stop=3.

The semantics that trip people up

It slices one axis per node. Need rows and columns? Two nodes chained. That's not a limitation being hidden - it's the design, and it's why each node stays comprehensible.

  • axis - INT, -8 to 8, default 0. 0 is rows (image height, detections in a table), 1 is columns, -1 is the last axis (channels). Negative counts from the end.
  • start - first index kept. Negative counts from the end, so -2 is the second-to-last.
  • stop - one past the last index. And here's the genuinely useful quirk the tooltip calls out: stop = 0 means "to the end of the axis", because a real slice ending at 0 would be empty, and the common case in this pack is cropping a padded array back to a size that arrives as a link. If that computed size is 0, you get the whole axis rather than an empty result. Negative stop counts from the end (-1 drops the last element), which follows numpy.
  • step (optional, advanced) - stride, -1024 to 1024. 2 keeps every other index. Negative walks backwards, and then start is where it starts from: to reverse a whole axis you need start=-1, stop=0, step=-1. With the default start=0, a backwards walk stops immediately and hands you one element. That is the trap of the node, stated in its own tooltip, and it's easy to hit. step = 0 is rejected, because numpy doesn't define it.
  • keep_axis (optional, advanced, default true) - when the slice keeps exactly one index, does the axis survive with length 1, or get dropped? (N,4) → (N,1) versus (N,4) → (N,). On keeps a table a table; off is what a downstream node wanting a flat vector of scores expects.

One input, nparray - any shape, any dtype, values untouched. One output, nparray, same dtype.

The two behaviours worth knowing before you wire it

Out-of-range bounds clamp the numpy way instead of raising. An empty result is a valid outcome here, not a wiring mistake. That's consistent with the pack's style - plenty of its nodes return a found flag or an empty array instead of an exception - and it means a slice node in the middle of a batch graph won't kill the run when one frame is odd-sized. It also means silent emptiness is possible, so if something downstream is mysteriously blank, check the slice bounds rather than the downstream node.

You never get a view. The output is contiguous. That matters more than it sounds in a cv2 pipeline: a numpy view shares memory with its parent, so a later cv2 call that writes in place would corrupt the original array. The pack cuts that off deliberately.

What it's for

The canonical use is DNN letterboxing: you padded the input up to a multiple of 32 because the network demands it, so you slice the result back to the real size - axis 0 for rows, axis 1 for columns, two nodes, out comes the image you actually wanted. The other two: pulling a column out of a detection or score table (with keep_axis off if the consumer wants a flat vector), and subsampling a sequence with step.

Install

ComfyUI Manager → ComfyUI CV → install → restart, or:

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, recent ComfyUI on the V3 node API. No models. It's registered under image/CV/low-level, which is where the pack files its glue nodes - they ship alongside ~470 auto-generated cv2.* wrappers, so the category is deep.

Common issues

  • Reversing an axis returned one element. step=-1 with the default start=0. Set start=-1 and stop=0.
  • Axis out of range error. Real error, real message: it names the axis and the valid range for your array's dimensionality. A 2-D array has no -3.
  • Shape mismatch downstream. keep_axis. Turn it off for flat vectors, on for tables.
  • Empty array slipped through. Check bounds. The node won't tell you it clamped.
  • Nodes gone from the menu after another pack installed. Non-contrib OpenCV wheel overwrote the contrib one in the shared site-packages/cv2. python tools/repair_opencv_contrib.py --check, then --apply.
Categoryimage/CV/low-level

Inputs (6)

NameTypeDefaultDescription
nparrayNPARRAYArray to slice. Any shape and dtype; values are not touched, only selected.
axisINT0-8–8Which axis to slice. 0 = rows (height of an image, detections of a table), 1 = columns (width), -1 = the last axis (channels). Negative counts from the end.
startINT0-2147483647–2147483647First index to keep, counting from 0. Negative counts from the end (-2 = the second-to-last).
stopINT0-2147483647–2147483647One PAST the last index to keep. 0 means 'to the end of the axis' - the common case when cropping a padded array back to a computed size, where the size arrives as a link. Negative counts from the end (-1 = drop the last element).
stepoptINT1-1024–1024Stride between kept indices. 2 = every other one. A NEGATIVE step walks backwards, and then 'start' is where it starts FROM: reversing a whole axis is start=-1, stop=0, step=-1 - with the default start=0 a backwards walk stops immediately and returns a single element. 0 is rejected (numpy does not define it).
keep_axisoptBOOLEANtrueWhen the slice keeps exactly ONE index, whether the axis survives with length 1 (True, e.g. (N,4) -> (N,1)) or is dropped (False, (N,4) -> (N,)). Off is what a downstream node wanting a flat vector of scores expects; on is what keeps a table a table.

Outputs (1)

NameTypeDescription
nparrayNPARRAYThe selected part of the input, same dtype. A view is never returned - the result is contiguous, so a later cv2 node cannot write into the original.