Nodes/ComfyUI CV/cv2.ppf_match_3d.addNoisePC
ComfyUI Node

cv2.ppf_match_3d.addNoisePC

Stress-test your PPF pose before the scan does it for you

By bmad4ever·Created 3 months ago·Updated 14 days ago· 1
cv2.ppf_match_3d.addNoisePC
  • pc
  • nparray
◄scale0.0000►

Point-pair-feature matching is the part of computer vision that finds a known 3D object in a scene, and it has a reputation for looking amazing in a paper and falling apart on real data. cv2.ppf_match_3d.addNoisePC exists to find out which of those two you have: it takes a clean point cloud and perturbs every point, so you can then ask the matcher for a pose anyway and see whether it survives.

What it's for

The realistic path into this node is: you have a CAD model or a mesh, you convert it to a point cloud, and you want to know how much sensor noise the match tolerates before you point a depth camera at the real thing. Adding Gaussian jitter at 0.005, 0.01, 0.02 and re-running the pose estimate is a two-minute experiment that tells you whether your ICP fallback is going to be doing all the work. 3d-generation.md makes the broader point that reconstructed geometry is often messier than the demo suggests - this node is how you quantify that instead of hoping.

It's also just a generator. Any node in the pack that wants a slightly-wrong cloud as input can get one from here.

How it works

This is one of the two free functions the ppf_match_3d module exposes, which is why it shows up as a raw wrapper at all: the actual detection and registration in PPF are class-based (PPF3DDetector, ICP), and the pack's generator only parses top-level functions - those are reachable only through the curated nodes CV PPF Pose Estimation and CV ICP Register (Point Clouds). addNoisePC takes a cloud, adds Gaussian noise of the given magnitude to its points, and returns a new cloud. Your input is untouched; the wrapper always hands cv2 a private copy.

The expected container is an Nx3 or Nx6 cloud - XYZ, optionally with normals. Normals matter here because PPF consumes them: the pack's docs are explicit that CV Point Cloud Normals is "mandatory in front of the ppf nodes", and that if your cloud came from a mesh you want CV Mesh Vertex Normals instead, because a plane fit can't orient a closed model and will invert the pose by roughly 180 degrees. Noise on the XYZ columns doesn't fix or break that; orienting your normals is a separate step you still have to do.

Inputs and outputs

pc is the cloud. It'll accept an IMAGE or MASK link because every raw wrapper shares one polymorphic socket, but don't - this wants an NPARRAY from a loader or a mesh node. scale is the noise magnitude, and it defaults to 0, which means no noise at all, which is a great way to conclude the node does nothing. Set it.

The output is a single nparray: the noisy cloud. Wire it into CV PPF Pose Estimation for a global pose, CV ICP Register (Point Clouds) for a refinement pass, CV Write PLY (Point Cloud) to export it as a file you can inspect in MeshLab, or CV Transform Points 3D to move it around.

scale is in your model's own units. If the cloud is in metres, 0.01 is a centimetre of jitter, which is already a lot for a 20 cm object; on a millimetre-unit cloud, 0.01 is nothing. Scale is the single most common reason a noise experiment gives nonsense.

Install

Part of ComfyUI CV (bmad4ever). Manager search comfyui_cv, or:

cd ComfyUI/custom_nodes
git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"

Then restart. Python ≥ 3.12 and a recent ComfyUI on the V3 node API are required. No model downloads for this node.

Common issues

The node isn't in the menu. ppf_match_3d is an opencv-contrib module. If you're on a plain opencv-python / opencv-python-headless wheel, the submodule isn't there and the pack skips the entry at import. Run python tools/repair_opencv_contrib.py --check in the pack directory, then --apply if it reports the contrib modules missing.

"Nothing changed." scale is 0. It's the default, and it means zero noise.

PPF still returns garbage. That's usually the pose, not the noise. Feed it a cloud with clean, consistently-oriented normals, and remember the curated node applies normals internally while the raw wrappers don't. Also worth knowing: the pack's curated ICP node catches cv2's 1e10 divergence sentinel, which registerModelToScene happily reports alongside retval == 0 - so a "successful" raw match can still be junk.

Dependency friction. As with any OpenCV 5 pack, this wheel drags numpy 2.x along. If another pack in your install pins numpy 1.x, resolve that before blaming the node.

Categoryimage/CV/low-level/ppf_match_3d

Inputs (2)

NameTypeDefaultDescription
pcNPARRAY,IMAGE,MASK - - - Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size.
scaleFLOAT0.0000-1e+38–1e+38 - - -

Outputs (1)

NameTypeDescription
nparrayNPARRAY—