3D visionHow-to

Clamp depth range on a 3D camera to crop the point cloud

Set a depth clamp min and max to crop the point cloud so background never becomes data: steps, a worked face-scan example and the cost of filtering afterwards.

LumaSpec Vision10 min read Share on LinkedIn

On this page 10 sections
  1. 01The decision: clamp on the camera, not after
  2. 02Set the clamp in four steps
  3. 03Worked example: clamping a face scan at 500 mm
  4. 04Why filtering built vertices costs the frames
  5. 05Clamp, exposure ROI and XY crop do three different jobs
  6. 06No clamp control? Filter the depth map instead
  7. 07Checks before you lock the preset
  8. 08When the clamp alone is not enough
  9. 09Cameras for a fixed working band
  10. 10Questions

You want the face, not the room behind it. Every depth camera streams a full frame of range samples, and if you let them all become points you pay for the wall, the desk and the door in conversion time, memory and rendering - usually right at the moment you need frame rate. The fix is a depth clamp: a minimum and maximum distance set on the camera, outside which depth comes back invalid and no vertex is ever created. This guide shows where the control lives, how to pick the two numbers with margins, a worked face-scan example with the arithmetic, and why filtering a bounding box over already-built vertices is the expensive way to do the same job.

The decision: clamp on the camera, not after

Set a minimum and maximum depth on the camera itself. Most viewers call this the depth clamp or the acquisition range, with one entry box for each end. Every sample outside the band returns invalid depth, and invalid depth never becomes a vertex: the cloud is cropped by distance before it exists. Nothing downstream has to filter, copy or render the background, so the frame budget you had without the clamp is the frame budget you keep.

Configure it once in the viewer, then export the full setting set as a JSON preset file and load that preset in your start-up code, so the clamp applies on every run rather than only in the session where you typed it. Order matters when you tune: cut the far end first.

Set the clamp in four steps

You need the camera's viewer software, three distances, and the application code that loads a preset file.

  1. Measure three distances in millimetres: the nearest surface you must keep, the farthest surface you must keep, and the nearest background you want gone. Read them from the viewer's live depth value at a clicked pixel, or with a tape measure.
  2. Set the two ends: minimum = nearest kept surface minus 100 mm; maximum = farthest kept surface plus 100 mm. If the subject moves toward the camera, widen the near margin to 150 mm.
  3. Enter both values and export the preset: confirm in the viewer that the background disappears while the target stays solid, then save the settings file your application loads at start-up.
  4. Verify at full speed: the frame rate with the clamp should equal the camera's rated rate for that resolution, and the target's nearest points - nose tip, ear edges - must still be present. A minimum set too high shaves the closest surface and shows up as a hole.

Worked example: clamping a face scan at 500 mm

Example inputs; swap your own measurements in:

  • Working distance to the face: 500 mm
  • Nose, the nearest surface: 450 mm; back of head, the farthest kept surface: 550 mm
  • Background wall: 2,500 mm
  • Horizontal field of view: 70 degrees, taken from the camera's data sheet
  • Depth map 640 x 480 at 30 fps; each point stored as three 32-bit floats, 12 bytes
frame_width = 2 x WD x tan(HFOV / 2) pixels_kept = target_width / footprint x target_height / footprint bytes_per_frame = pixels_kept x bytes_per_point

The arithmetic:

  • Coverage: width = 2 x 500 mm x tan 35 deg = 2 x 500 x 0.700 = 700 mm. Height = 700 x 480 / 640 = 525 mm. Pixel footprint on the face plane = 700 / 640 = 1.09 mm per pixel.
  • Clamp: minimum = 450 - 100 = 350 mm; maximum = 550 + 100 = 650 mm. The wall at 2,500 mm sits 1,850 mm past the maximum and is rejected camera-side; a chest at 700 mm also falls outside the band.
  • Points kept: a head about 250 mm x 330 mm covers (250 / 1.09) x (330 / 1.09) = 229 x 303 = about 69,000 pixels, out of 640 x 480 = 307,200 samples. Roughly 238,000 points are never built.
  • Data into your conversion: full cloud 307,200 x 12 B = 3.7 MB per frame, about 111 MB/s at 30 fps; clamped cloud 69,000 x 12 B = 0.83 MB per frame, about 25 MB/s. That is a 4.5x cut in bytes moved per second.

Decision: with the clamp at 350 / 650 mm the cloud contains the head only and the conversion moves under a quarter of the bytes. Commit to the camera-side clamp whenever the nearest background lies beyond about twice your maximum kept distance - here 2,500 mm against 650 mm - or the target fills less than half the frame. Both hold in this example, and 77 percent of the work disappears before your code sees a frame.

Why filtering built vertices costs the frames

The manual alternative - build every vertex, keep the ones inside a box - does the same job at the wrong end of the pipeline. With no clamp the SDK produces all 307,200 vertices every frame. Your filter then runs six comparisons per point: 307,200 x 6 = 1.84 million comparisons per frame, about 55 million per second at 30 fps. Comparisons at that scale cost a modern CPU very little. The allocation and copying are what eat the frame time: 3.7 MB per frame created, copied again into a viewer cloud object, rendered, then discarded - and the camera keeps streaming exactly the same frames throughout. Frame rate that collapses right after a points-to-cloud conversion traces to this memory traffic, not to the geometry test.

Filtering built vertices is the right tool offline, on recorded scans. Mapping an image-space box into world coordinates is covered in 2D bounding box to 3D extent and bounding box depth mapping. On the live path, preallocate one reusable buffer if you must post-process, and let the clamp make the distance cut.

Clamp, exposure ROI and XY crop do three different jobs

Control What it restricts What it leaves alone Reach for it when
Depth clamp (min/max Z) Which distances become points Image area, frame rate Background sits beyond the target band
XY crop of the depth map Which pixels are converted Distances inside the kept area Target occupies one part of the frame
Auto-exposure ROI The region the exposure loop measures Everything - no data is removed Target much darker or brighter than surroundings
Vertex bounding-box filter Points after they are built Camera output and conversion cost Offline analysis of saved clouds

The exposure ROI is the one that trips people up: selecting a region there changes brightness behaviour, not geometry - the full image is still captured and converted. For area, crop the XY region of a depth point cloud; for distance, the clamp. The two stack: crop the pixels, clamp the range, and the cloud shrinks in both dimensions at once.

No clamp control? Filter the depth map instead

If your camera's settings expose no clamp, apply the band yourself at the earliest stage you control: compare each depth value, write a validity mask, then deproject only the survivors. This stays in the depth domain, where a full 640 x 480 frame is 614,400 bytes of 16-bit samples - about 600 kB - instead of 3.7 MB of built vertices. Deprojection needs the camera's intrinsic parameters; read them from the device rather than copying old constants, as depth camera intrinsics and distortion parameters shows, and the full math is in depth map to point cloud: the deprojection calculation.

// Illustrative names, not a vendor API. depth and valid are W*H arrays.
const uint16_t clamp_min_mm = 350;   // mm, nearest kept surface minus margin
const uint16_t clamp_max_mm = 650;   // mm, farthest kept surface plus margin
size_t kept = 0;
for (size_t i = 0; i < W * H; ++i) {
    const uint16_t d = depth[i];     // depth map in mm, 0 means no return
    const bool inside = d != 0 && d >= clamp_min_mm && d <= clamp_max_mm;
    valid[i] = inside ? 1 : 0;       // uint8_t validity mask
    kept += inside ? 1 : 0;
}
// Deproject only pixels with valid[i] == 1. Test map {0, 349, 350, 500,
// 650, 651} keeps exactly 3 pixels (350, 500, 650) - assert kept == 3.

One pass, no per-point allocation, and the mask pairs naturally with the camera's own validity or confidence output.

Checks before you lock the preset

  • Frame rate with the clamp equals the camera's rated maximum at that resolution. If it dropped, the clamp is not the cause; look at exposure and bandwidth.
  • The nearest surface survives. Raise the minimum until the nose tip just disappears, then back it off 100 mm and leave it there.
  • Background pixels read invalid, not zero-coordinate points. An unmasked zero depth deprojects to the world origin and shows as a spike cluster at (0, 0, 0); mask zeros before conversion.
  • The preset loads at start-up: change one value, restart the application, confirm the change took.
  • With a paired colour stream, the texture stays full frame while the cloud is cropped; align the pair as covered in full frame texture images alongside a cropped 3D scan.

When the clamp alone is not enough

  • Target small in the frame. Coverage scales linearly with working distance: the same 70-degree camera at 350 mm covers 2 x 350 x 0.700 = 490 mm, so the head fills most of the width and framing does the rest. Positioning guidance is in the 3D camera working distance and positioning guide.
  • Target off to one side. The clamp keeps the whole frame's worth of distance; combine it with the XY crop from the table above so pixels outside the subject's area are never converted either.
  • Two objects at different depths. One band keeps both; separate them in image space and map each box to 3D with the bounding-box articles linked earlier.
  • Holes from dark or specular patches. A clamp cannot create data. Capture several frames and merge them, as in merging multiple depth frames into one gap-free cloud.

Cameras for a fixed working band

Near-range scanning is a camera choice as much as a settings choice. A time-of-flight camera such as the MV-DT01WMU is built for this class of close-range work on people and parts; a projected structured-light camera such as the MV-DPS200P-02 resolves finer surface detail on small targets; a laser galvanometer stereo camera such as the MV-DLS300P-04 covers larger volumes from a fixed station. Whatever you pick, set the clamp from that camera's own measured band, not from a previous camera's numbers.

3D sensorsHikrobot MV-DT01WMU ToF sensing cameraMV-DT01WMU
Type
Depth / ToF camera
Price on requestView and quote
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-DLS300P-04 Laser galvanometer stereo cameraMV-DLS300P-04
Type
Stereo / structured light
$16,579.00 · quotedView and quote

Compare the full range in the 3D sensors category or filter by type in the camera finder. If your target band is unusual - very close, very far, or shared with a second process - send us the distances and we will shortlist sensors that hold those ranges.

Questions

Does a depth clamp narrow the camera's field of view?

No. The clamp restricts distance only: every pixel is still imaged across the full field of view, and samples outside the band return invalid depth instead of a coordinate. To shrink the captured area as well as the range, combine the clamp with an XY crop of the depth map, or move the camera closer, which shrinks coverage linearly with working distance.

What min and max depth should I set for a face scan?

Take the nearest surface you must keep and subtract 100 mm, then the farthest surface you must keep and add 100 mm. For a face at about 500 mm working distance, with the nose near 450 mm and the back of the head near 550 mm, that gives roughly 350 to 650 mm; a chest at 700 mm and a wall at 2.5 m both disappear. Widen the near margin to 150 mm when the subject moves.

Why does converting every vertex into a point cloud library drop frames?

A 640 x 480 depth map is 307,200 vertices; at 12 bytes each that is about 3.7 MB allocated, copied and released every frame, around 111 MB/s at 30 fps before the viewer renders anything. The comparisons in a bounding-box test cost almost nothing - the copies are what hurt. Clamp camera-side so the surplus points are never built, and when you convert offline, reuse one preallocated cloud instead of creating a new object per frame.

Is an auto-exposure ROI a way to crop the point cloud?

No. An exposure ROI tells the camera's auto-exposure loop which part of the image to measure when it sets exposure or illumination power; the full image is still captured and converted. It changes brightness behaviour, not geometry. Use the depth clamp for range, an XY crop for area, and leave the exposure ROI for scenes where the target is much darker or brighter than its background.

Do clamped pixels disappear from the colour or texture image too?

No. The clamp acts on the depth stream: clamped samples become invalid depth, so they produce no points, but an RGB or texture camera keeps delivering its full frame. If you colour your cloud from that stream, keep the pairing in mind - the texture is full frame while the cloud is cropped, and the two must still be aligned before you sample colours.

My camera has no depth clamp control - what now?

Apply the band to the depth map before deprojection: one 16-bit comparison per pixel writing a validity mask, then build vertices only for pixels that pass. That keeps the work in the depth domain, where a full 640 x 480 frame is about 600 kB of samples, instead of on 3.7 MB of already-built vertices. Confirm the depth scale first so the comparison runs against real millimetres.