Nodes/ComfyUI-Depth-Visualization/Export Depth Point Cloud (PLY)
ComfyUI Node

Export Depth Point Cloud (PLY)

The node that turns your flat image into actual 3D points

By gokayfem·Created 2 years ago·Updated about a month ago· 70
Export Depth Point Cloud (PLY)
  • depth_map
  • color_image
  • ply_paths
  • manifest_json
field_of_view60
depth_scale1.00
stride4
drop_zero_depthtrue
filename_prefixdepth_exports/point_cloud

This is the node where the magic becomes math. You give it an image and a depth map, and it unprojects every pixel into a 3D point, colored by the RGB of the original image. One flat photo in, a real point cloud out - the thing you can fly a camera through, orbit, and reproject from new angles. Everything downstream in camera-comfyUI - camera motion, point-cloud inpainting, splat building - starts here.

It sits right after a depth estimator in every single cloud workflow in the pack. The PointCloud.json demo, the fisheye-to-pointcloud pipeline, the pointcloud_inpaint flow - all of them open with this node. If you've ever done the "living photo" parallax trick and wanted to push further than a subtle warp, this is the honest 3D version of it.

How it works

For each pixel, it takes the depth value and the pixel's position in the frame, then inverts the camera projection using your chosen input_projection (PINHOLE, FISHEYE, or EQUIRECTANGULAR) and input_horizontal_fov (default 90°) to get a ray direction; the depth tells it how far to travel along that ray. The result is a point cloud tensor of shape (N,7) - X, Y, Z plus R, G, B, A per point - the format the whole pack speaks.

The image is required because the node is built around coloring points; the depthmap is actually optional, fed in via the optional input slot. If you leave depth disconnected, the node still emits a cloud - it just can't place geometry correctly without a real depth source, so don't do that. When you do wire in depthmap, also wire the optional mask if you have one (e.g. from DepthEdgeFilter) so masked-out pixels don't become stray points.

Three settings get most of the attention:

  • input_projection - must match how your depth was produced. Fisheye depth from FisheyeDepthEstimator goes with FISHEYE, pinhole depth with PINHOLE. Get this wrong and the cloud folds in on itself.
  • depth_scale (default 1.0) - a multiplier on depth values; effectively your scene's unit of measurement.
  • invert_depth (default off) - flips the map if your estimator outputs "closer = darker."

The Z-depth trap (again)

The depth tensor you feed this node should be ray depth, not Z-depth. Depth Anything V2 outputs Z-depth, so the pack's README is emphatic: run the map through ZDepthToRayDepthNode before this node, or your point cloud bows outward at wide FOVs. At 90° it's a subtle curve; at 180° fisheye it's a wrecked scene. This is the single most common "why is my point cloud curved" issue in the pack.

Install

Shared camera-comfyUI install: ComfyUI Manager → search "camera-comfyUI" → Install, or clone https://github.com/Alexankharin/camera-comfyUI into custom_nodes/ and run python install.py. No models of its own - the depth comes from upstream - and it runs on CPU fine.

Troubleshooting

  • Cloud is a folded mess: input_projection doesn't match the depth source, or the depth is Z-depth at wide FOV. Check both.
  • Black point everywhere: the mask (or depth) is cutting out most pixels, or the image fed in has a lot of alpha=0. Check your mask's polarity.
  • Point cloud is the right shape but wrong size: depth_scale - divide or multiply to set units.
  • Flying pixels at object edges: pass the depth through DepthEdgeFilter and feed its valid_mask into the mask input here.
Categorydepth/3D export

Inputs (7)

NameTypeDefaultDescription
depth_mapIMAGE
field_of_viewFLOAT601–179
depth_scaleFLOAT1.000.001–1000
strideINT41–64
drop_zero_depthBOOLEANtrue
filename_prefixSTRINGdepth_exports/point_cloud
color_imageoptIMAGE

Outputs (2)

NameTypeDescription
ply_pathsSTRING
manifest_jsonSTRING