3D visionTroubleshooting

Dark or empty PLY exports: fix depth range and vertex color first

Why a PLY export opens dark or empty: read the header, clamp the depth range to your subject, write per-vertex color at the right scale, and check units.

LumaSpec Vision9 min read Share on LinkedIn

On this page 8 sections
  1. 01Separate a capture problem from an export problem
  2. 02Read the PLY header first
  3. 03Clamp the depth range to the subject
  4. 04Make the export carry color
  5. 05Check the units before you blame the geometry
  6. 06Prevention checklist
  7. 07When the camera itself is the limit
  8. 08Questions

You capture a clean, textured point cloud in your depth camera's own viewer, then your script saves a PLY that opens dark — or without the subject at all. That gap almost never means a corrupt file or a broken camera. Two causes cover nearly every case: the file carries the whole unclamped depth range instead of your subject, or it carries vertices with no usable color, so the viewer paints them a flat dark shade. Work through this guide in order and you will split capture problems from export problems in five minutes, prove what the file contains from its header, and set the clamp, color and unit values that fix each failure mode.

Separate a capture problem from an export problem

Run the fork test before touching a single setting. Open the live depth image in your depth camera's viewer with the same subject, distance and lighting you capture with. If the live depth is already full of holes or flat, no export setting can help: fix the capture first, starting with fixing depth holes in a point cloud and the working distance and positioning guide.

If the live depth looks right, export one frame from the viewer itself and open that file next to your script's output. Viewer file good, script file bad: your export code or its settings are the problem, and the sections below fix it. Both bad: the scene is the problem, not the code. The single-frame PLY/OBJ capture walk-through shows the viewer export step.

Desk-scale stereo and time-of-flight depth cameras resolve surfaces from roughly 0.3 m out to 3–5 m; compact depth modules' specifications cluster in that band. A wall 3 m behind your 0.5 m subject sits inside that range, so it gets captured — noisily, as the clamp section quantifies — and it fills the file until you crop it.

Read the PLY header first

A PLY carries a plain-text header even when its body is binary. Open the file in any text editor and read five lines — they settle most of the diagnosis in a minute:

format binary_little_endian 1.0
element vertex 307200
property float x
property float y
property float z
property uchar red
property uchar green
property uchar blue
Header line What it proves
element vertex 307200 A full VGA frame was written: the depth clamp never ran
property float x / y / z Geometry is present, single precision
property uchar red / green / blue Per-vertex color exists; without these three lines no viewer can ever color the cloud
format binary_little_endian 1.0 The byte order any reader must honor

Two verdicts fall straight out of this. No red / green / blue lines: the darkness is written into the file, so the fix belongs to the exporter. A vertex count equal to a full frame: the clamp never ran, so the fix belongs to the range settings. If the header lists color properties and the cloud still renders black, work through the color section below — and if values in the file look odd at the pixel level, decoding confidence image bitflags helps you mask the bad returns before export.

Clamp the depth range to the subject

Depth cameras carry a depth clamp — a minimum and maximum range pair — in the viewer's advanced depth controls, and the SDK exposes the same pair to your code. Set it around the subject, not around the room.

Worked example, desk plant: the pot sits about 0.5 m from the lens, and a tape puts the foliage from 0.45 m nearest to 0.85 m farthest. Set the clamp minimum to 0.30 m and the maximum to 1.20 m: 0.15 m of margin in front, 0.35 m behind. The wall at 3.0 m and the ceiling fixture at 2.1 m now fall outside the window and never reach the file.

The vertex count proves the crop. A VGA depth frame is 640 × 480 = 307,200 candidate vertices; an unclamped header reads element vertex 307200. With the plant covering about a tenth of the frame, the clamped file lands near 307,200 × 0.1 = 30,720 vertices, and every one of them is plant.

Clamping also throws out the noisiest points, because stereo depth error grows with the square of distance:

Z = (f × B) / d δZ = Z² × δd / (f × B)

Here f is the focal length in pixels, B the stereo baseline in metres and d the disparity in pixels. Hold the camera fixed and compare surfaces: the same disparity error at 3.0 m produces (3.0 / 0.6)² = 25 times the depth noise it does at 0.6 m. That is why an unclamped export reads as fuzzy static around a clean subject — the wall contributes the most vertices and the worst of them. The square law is stereo's; projected-pattern and time-of-flight cameras also lose accuracy with distance, only more gently, so clamping pays off there too. The depth-range clamping walk-through shows the settings in context.

Make the export carry color

A dark render with geometry intact is a color-mapping failure, and it takes three forms.

First, the exporter wrote positions only: the header check above shows no red / green / blue properties. Switch texture or color mapping on in the exporter and recapture.

Second, the exporter wrote colors at the wrong scale. PLY color properties are uchar holding 0–255; if your code computes normalized floats and stores them straight into that slot, every value collapses to black. A mid-gray pixel is 128 / 255 = 0.502 as a float, and 0.502 truncated into a uchar is 0 — the whole cloud sits at 0 out of 255 while the header looks healthy. Multiply floats by 255 and round before storing, or keep the channels 8-bit end to end. The same failure in array form is covered by the stride and dtype fixes for depth-to-cloud conversion.

Third, the viewer: if the header shows color properties with sane values, the file is fine and the display is the problem. Most viewers start with colors off and one-pixel points. Switch the color attribute on, raise the point size to 2–3 px and pick a light background before judging the file.

Color has to come from somewhere: map it from the RGB stream aligned onto the depth frame's geometry, or fuse an infrared intensity channel where the camera provides one. The full-resolution color-plus-depth workflow and the RGB and infrared intensity fusion guide cover the two routes.

Check the units before you blame the geometry

A PLY file stores no unit field. Depth-camera exporters write metres; CAD and printing tools assume millimetres. Put a 100 mm calibration cube in the scene: in a metre-based file its edge reads 0.10, and a millimetre-assuming viewer draws a 0.1 mm speck — which looks exactly like an empty scene. Multiply metre-based files by 1000 when they enter a millimetre tool, or set the importing tool's unit, then re-check extents before measuring anything.

If your own code builds the cloud from a depth image, the scale is yours to apply per axis: the per-axis scale factor guide works the arithmetic, and the depth-scale mismatch article covers the cousin symptom where close-range geometry vanishes.

Prevention checklist

Sixty seconds of checks that keep the next export honest:

Capture

  • Live depth image clean across the subject — holes in the live view become holes in the file; the noisy stereo cloud fixes belong here.
  • Pattern emitter on; no lamp or bright window inside the frame.
  • Subject inside the camera's usable span, about 0.3–3 m for desk-scale work.

Export

  • Depth clamp set to the subject with 0.15–0.30 m of margin each side.
  • Color mapping on, channels written as uchar 0–255.

File

  • Header lists red / green / blue and a vertex count well below the full frame.
  • Units known and extents sane: a desk subject reads in fractions of a metre.
  • Opened once in a second viewer before the file ships downstream.

When the camera itself is the limit

If the live depth stays noisy after lighting and range are right, the sensor class is working against you. Structured-light depth cameras project their own pattern, so they hold depth on textureless surfaces where passive stereo matching fails. Volume-measurement cameras exist to hand your code a clean, largely pre-cropped cloud of one object. Browse the 3D sensors category for the depth camera lines, and area scan cameras when the color side comes from a separate camera.

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote
3D sensorsHikrobot MV-DT01WMU ToF sensing cameraMV-DT01WMU
Type
Depth / ToF camera
Price on requestView and quote

The structured-light models project the pattern themselves; the time-of-flight model reads the return time of its own emitted light. To size any depth camera against your working distance and subject, start at the camera finder or the camera step of the configurator. The 3D vision topic page collects the rest of the depth-camera fixes.

Questions

Why does the same PLY look dark in one viewer and fine in another?

Display defaults differ: point size, the per-vertex color toggle and background shading start off in many viewers. First confirm the header lists red, green and blue properties with sane 0–255 values; then switch colors on and raise the point size in the viewer that showed black. A file with no color properties cannot be rescued by any viewer setting — that fix belongs in the exporter.

What units does a PLY point cloud use?

Depth-camera exporters conventionally write metres: a 100 mm cube reads 0.10 in the file. CAD and printing tools assume millimetres and draw that same file as a 0.1 mm speck. PLY itself stores no unit field, so set the unit at import or scale by 1000, and confirm with a known object before you measure anything.

How tight should the depth clamp be around the subject?

Read the nearest and farthest surfaces off the live depth display, then add margin: 0.15–0.30 m each side for a static subject, more if the part moves or swings past the camera. A clamp tighter than the foliage clips leaves as the plant shifts; a looser one lets the wall's noisy vertices back into the file. Re-check after any camera move.

Can I add color to a PLY that was exported without it?

Only if you kept the color frame and the camera's alignment data from that capture: re-map RGB onto the stored depth vertices and write new red, green and blue properties. Without the original frames there is nothing to map from, and recapturing is faster than reconstructing. From then on, switch color mapping on before capture so the file carries colors from the start.

Why does the ceiling light ruin the depth export?

Twice over. A bright fixture inside the clamp window is a surface like any other: the camera faithfully returns its geometry and it sits in the file unless the range crops it. Strong ambient light also washes out a stereo camera's projected pattern, raising noise on every surface at once. Keep lamps out of frame; clamp the ones you cannot move.