CV Filter Point Cloud
Pruning the depth points that ruin your view
- points
- colors
- points
- colors
Stereo reprojection and monocular depth both produce a small number of points that are spectacularly wrong - a triangulation that flew off to infinity, a disparity spike, a point behind the camera. Ten of those in a hundred thousand points is enough to blow up the bounding box, and once the bounding box is wrong every viewer, every normalisation and every camera fit downstream is wrong too. This node deletes them by distance from the origin.
How it works
Straightforward and deliberately boring: it takes the Euclidean distance of each point from the origin, keeps the ones inside [min_distance, max_distance], and - if you connected colours - slices the colour array with exactly the same mask so per-vertex colours stay aligned. It logs how many points it removed and what percentage that was, which sounds trivial and is actually the most useful part when you're calibrating a stereo rig, because a filter that drops 0.02% of points is doing nothing while one that drops 40% is telling you your reconstruction is broken.
Two conventions to internalise:
- The reference is the origin, not the centroid of the cloud. Not roughly the origin, not the average.
(0, 0, 0). If your point cloud is expressed in a coordinate frame where the scene sits at, say, x ≈ 4000, this filter will remove everything the moment you set a max distance. Recentre first (the pack's point-cloud transform nodes do this) or leave the bounds wide. - 0 means "no bound", for both fields.
min_distance = 0disables the lower bound,max_distance = 0disables the upper bound. So the defaultmax_distance = 100is an actual limit, and setting it to 0 is how you say "don't cap it" - which is the opposite of what people assume a 0 default would mean.
Inputs and outputs
points-Nx3orNx1x3float array of 3-D positions. Both shapes are fine; it reshapes internally.min_distance(default 0) - drop points closer than this to the origin.max_distance(default 100) - drop points farther than this. 0 = no upper bound.colors(optional) -Nx3per-vertex colours filtered in sync. If you don't connect it, the outputcolorsis whatever the node produces, so wire your colours through if you care about them.
Outputs are points and colors, same ordering, colours aligned. There's no count output here, which is why that log line matters - check the console if you want to know how aggressive your filter was.
Where it belongs
Put it immediately after whatever generated the cloud and before anything that summarises the cloud: bounding-box fitting, normal estimation (CV Point Cloud Normals), or registration. The classic tell that you needed it: the rendered cloud looks like a normal scene with a few enormous spikes, or your viewer's zoom level is set for a scene a hundred times bigger than the one you can see. Stereo disparity maps are the worst offenders, since one bad block match near the image edge can triangulate to a point kilometres away.
It's in the pack's low-level category rather than the curated geometry ones, and it shows - a two-threshold filter with no statistics attached. If you want something more principled, the pack has a nearest-distance node that computes per-point neighbourhood distances, which is the input to actual outlier detection. This one is the blunt instrument, and the blunt instrument is usually enough.
Install
# ComfyUI Manager → search "ComfyUI CV" → install → restart
# or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
cd comfyui_cv && pip install -r requirements.txt
Python ≥ 3.12 and a recent ComfyUI built on the V3 node API. Only dependency: opencv-contrib-python-headless~=5.0.0.93 (plus numpy and torch). This node does pure numpy work, so it's unaffected by the pack's usual contrib-wheel hazard - but keep the contrib build anyway, since installing plain opencv-python over it silently empties the shared cv2 contrib submodules and removes the pack's Contrib-category nodes. tools/repair_opencv_contrib.py --check / --apply diagnoses and repairs that.
Gotchas
- Everything vanished. Your cloud isn't near the origin. Recentre, or set
max_distanceto 0 (no bound) and use only the minimum. - Nothing changed. Check the console log - if it removed 0 points, your outliers are within the band and you need a different criterion entirely (depth statistics, neighbourhood distance, a confidence mask).
- Colours came back white or missing. You didn't connect
colors, so there was nothing to filter in sync. - It's not a statistical filter. It can't tell an outlier from a genuinely distant object; it only knows distance from the origin. If your scene has real depth range, tighten this and then use a mask-based filter driven by a second view's inliers instead.
The pack is bmad4ever's fork and rewrite of geroldmeisinger's opencv-comfyui, and the author is upfront that it's LLM-assisted and not production-grade. A distance threshold is about as verifiable as code gets, so this is a low-anxiety corner of the pack.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| points | NPARRAY | Nx3 or Nx1x3 float array of 3-D positions. | |
| min_distance | FLOAT | 0.0 | Minimum Euclidean distance from the origin. Points closer than this are removed (0 = no lower bound). |
| max_distance | FLOAT | 100.0 | Maximum Euclidean distance from the origin. Points farther than this are removed (0 = no upper bound). |
| colorsopt | NPARRAY | Nx3 per-vertex colors to filter in sync. If disconnected, all surviving points are white. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| points | NPARRAY | Filtered Nx3 points. |
| colors | NPARRAY | Filtered Nx3 colors (same order as points). |