Nodes/ComfyUI-pixel-perfect-depth/Pixel Perfect Depth (Save Point Cloud)
ComfyUI Node

Pixel Perfect Depth (Save Point Cloud)

One photo in, a colored point cloud out — Save Point Cloud

By Apache0ne·Created 8 months ago·Updated 8 months ago· 5
Pixel Perfect Depth (Save Point Cloud)
  • image
  • ppd_depth
    filename_prefixppd3d/PPD
    apply_filtertrue
    use_fp16true
    save_glbtrue
    save_plytrue
    moge_resolution_level9
    point_stride1
    max_points0
    voxel_size0.000

    This is the payoff node. Everything else in the pack produces a depth map; PPDPointCloudSave is what turns one photo into an actual 3D thing - a colored point cloud you can drop into Blender, MeshLab, a game engine, or a 3D printer slicer. It's the node that justifies the pack's name, and it's the one people see the sample GIF for and immediately want. Manage expectations first: you get a point cloud, not a clean watertight mesh - thousands of colored vertices, no topology, no back faces. For a 3D print or a "wow, it's 3D" prop it's fantastic; for a rigged character you'd still be doing retopo by hand, which is true of every single-image-to-3D tool in this space.

    How it works

    The trick is that a relative depth map alone isn't enough for real 3D - you need scale, a camera model, and per-pixel 3D coordinates. The node does this by combining two models:

    1. It loads MoGe (Microsoft's monocular geometry estimator), which predicts an affine-invariant point map plus a validity mask and camera intrinsics - real-ish 3D geometry from a single image.
    2. It takes your PPD relative depth from the upstream depth node and fits it onto MoGe's geometry using a RANSAC regression in log-depth space. That step converts the diffusion model's clean, edge-accurate relative depth into a metric-scaled depth, which is the best of both models: PPD's edges, MoGe's scale.

    The depth is then unprojected through the camera intrinsics into 3D points, each carrying the original image's color, and exported via trimesh as GLB and PLY (both on by default). The Y/Z axes get flipped to a conventional coordinate orientation so the cloud sits the right way up in standard tools.

    The inputs that matter

    • image + ppd_depth - feed the same image you generated depth from, and the payload from the depth node. Mismatched resolutions are handled (the depth is resized to match), but don't mix sources.
    • apply_filter (default on) - removes statistical outliers (floating noise points). Keep it on.
    • point_stride (default 1) - sample every Nth pixel. At 1 you get the full-resolution cloud (could be a million points); higher values thin it out fast. This is your first lever if export is slow.
    • max_points (default 0 = unlimited) - hard cap on output points, random downsampling if exceeded. voxel_size does the same job more evenly by merging points into voxel cells.
    • moge_resolution_level (default 9, max 9) - MoGe's internal resolution; 9 is full quality, lower is faster/leaner.
    • save_glb / save_ply - GLB is the modern drop-into-Blender format; PLY is the point-cloud workhorse. Both cost nothing extra, so leave them on.

    Outputs: none - it's a terminal output node. Files land in ComfyUI/output/ppd3d/ (or whatever filename_prefix you set), and a preview appears in the UI.

    Install

    One pack, all seven nodes:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Apache0ne/ComfyUI-pixel-perfect-depth
    cd ComfyUI-pixel-perfect-depth
    pip install -r requirements.txt
    

    Restart, then models. This node needs MoGe weights in addition to the depth pack's own files:

    ComfyUI/models/ComfyUI-pixel-perfect-depth/
    ├── MoGe2/model.pt        (~1.3 GB)
    └── (plus DA2/ or MoGe2/ depth weights from the depth-map node)
    

    There is no auto-download anywhere in this pack - the vendored MoGe loader explicitly rejects remote paths, so if MoGe2/model.pt is missing you'll get a FileNotFoundError on first run, not a download.

    Troubleshooting

    The two things that bite: missing MoGe weights (above - this is the #1 error) and VRAM. You're running PPD's diffusion model, MoGe, and then unprojecting a full-resolution cloud, so this node wants a real GPU; on 8 GB, lower moge_resolution_level, raise point_stride, and cap max_points. If the cloud looks like it's covered in fuzz, that's outliers - apply_filter handles it, but a higher point_stride plus voxel filtering gives cleaner results on noisy inputs. And if you're on the newest ComfyUI and this node's export crashes, the author's own advice applies: use the V2 save node, which swaps Open3D for a scipy-based filter.

    CategoryPixelPerfectDepth

    Inputs (11)

    NameTypeDefaultDescription
    imageIMAGE
    ppd_depthPPD_DEPTH
    filename_prefixSTRINGppd3d/PPD
    apply_filterBOOLEANtrue
    use_fp16optBOOLEANtrue
    save_glboptBOOLEANtrue
    save_plyoptBOOLEANtrue
    moge_resolution_leveloptINT91–9
    point_strideoptINT11–16
    max_pointsoptINT00–2000000
    voxel_sizeoptFLOAT0.0000–0.2

    Outputs (0)

    No outputs