3D visionExplainer

Hue colormap depth encoding: why disparity beats depth for 8-bit color

How hue colormap depth encoding packs a depth map into 256 codes of one hue, why disparity beats raw depth at close range, and how to invert it back.

LumaSpec Vision11 min read Share on LinkedIn

On this page 8 sections
  1. 01What is hue colormap depth encoding?
  2. 02Why encode disparity instead of raw depth?
  3. 03How much depth does one hue code cost?
  4. 04Why do intermediate RGB values go negative?
  5. 05How do you invert the colormap back to depth?
  6. 06Which depth cameras benefit most?
  7. 07When should you not encode depth as hue?
  8. 08Questions

Depth cameras output 16-bit numbers that image tools treat badly: viewers stretch them arbitrarily, codecs mangle them, and pipeline bugs hide inside a gray soup that looks like noise. Hue colormap depth encoding fixes the transport by turning every depth value into a color on an ordinary RGB image, which any viewer opens, any codec compresses and any colleague reads without plugins. The one decision that matters is what the hue cycle spans: raw depth or disparity. Span disparity and a triangulation camera keeps its near-field precision through the whole encode-decode round trip; span raw depth and you spend codes where the sensor has no precision left to protect. This guide gives the mapping, the quantization arithmetic for a concrete camera, the reason intermediate RGB values go negative, the inverse procedure, and the cases where encoding something else is the better call.

What is hue colormap depth encoding?

Hue colormap depth encoding maps each depth or disparity value onto the 256 codes of a single hue cycle and writes the result as an RGB image, so a 16-bit depth map becomes a 24-bit RGB frame that any viewer opens and a standard codec compresses.

The encoder works in three moves. It splits the input range into 256 equal bins; the bin number is the code. It turns the code into a hue angle, hue = code × 360° / 256. It converts that hue into three RGB channels of one byte each. One full turn of the color wheel is one pass across the working range, so the pixel's color position, not its brightness, carries the measurement. Each channel being a byte makes the encoded frame an ordinary 8-bit-per-channel RGB image, the layout every format and viewer already assumes; the 24-bit total is common enough to have its own name, color depth. Keep x_min, x_max and the bin count alongside the frame: a decoder that assumes a different range turns millimeters into meters without an error message.

Why encode disparity instead of raw depth?

Encode disparity because a triangulation camera's depth error grows with the square of distance, so an 8-bit cycle laid over inverse depth gives about 8× finer quantization at the near face of the worked example (1.7 mm versus 13.7 mm per code at 0.5 m), matching the code steps to the precision.

A stereo or structured-light camera does not measure distance directly. It measures disparity, the offset in pixels of one surface point between two views, and converts with Z = f·B / d, where f is focal length in pixels and B is the baseline. Differentiate that conversion and dZ/dd = -Z²/(f·B): a one-pixel disparity error costs four times more depth at 2 m than at 1 m, and sixteen times more at 4 m. Sensor noise follows the same law, so quantization should too.

Bin disparity uniformly and the depth steps grow as Z², tracking the camera's own precision curve. Bin depth uniformly and the steps sit constant at 13.7 mm in the worked example, about 8× coarser than the 1.7 mm the camera actually resolves at its closest working distance. The technique is published under the name inverse colorization, and its stated advantage for cameras that derive depth from triangulation is precisely this finer quantization at close range.

How much depth does one hue code cost?

One 8-bit hue code over disparity costs about 1.7 mm of depth at 0.5 m, 6.8 mm at 1 m, 27 mm at 2 m and 109 mm at 4 m, for a 1,000-pixel focal length, a 100 mm baseline and a 0.5–4.0 m range.

Take that camera: f·B = 1,000 px × 0.100 m = 100 px·m sets the scale. Disparity runs from 200 px at the near face (100/0.5) to 25 px at the far wall (100/4.0), a span of 175 px. Split the span into 256 bins and one code moves disparity by 175/256 ≈ 0.68 px; its depth cost follows the Z² law:

f·B = 1,000 px × 0.100 m = 100 px·m d(Z) = f·B / Z Δd = 175 px / 256 ≈ 0.68 px per code ΔZ ≈ (Z² / (f·B)) × Δd
Working distance Disparity Depth step per hue code Uniform depth step (3.5 m / 256)
0.5 m 200 px 1.7 mm 13.7 mm
1.0 m 100 px 6.8 mm 13.7 mm
2.0 m 50 px 27 mm 13.7 mm
4.0 m 25 px 109 mm 13.7 mm

At the nearest row the disparity scheme is 13.7 / 1.7 ≈ 8× finer than uniform depth codes; at the farthest it is 109 / 13.7 ≈ 8× coarser. The cycle is a fixed budget of 256 codes, and you choose where it lands. For scale, sub-pixel matching noise of 0.2–0.5 px becomes 0.5–1.3 mm of depth noise at the near face and 32–80 mm at 4.0 m, so the code steps sit on the same curve as the sensor's own precision.

If the disparity map arrives noisy, as learned stereo stacks sometimes deliver, clean it before encoding: the noisy stereo disparity depth troubleshooting guide is written for that stage. Doubling the baseline to 200 mm halves every step in the depth column, and the long-range stereo depth accuracy guide covers what a wider baseline buys at distance. Quantizing disparity is also why a stereo height can read high: the disparity quantization height overestimation article works that failure in detail.

Why do intermediate RGB values go negative?

The negative numbers are floating-point intermediates of the hue-to-RGB conversion, whose sine and cosine terms leave the 0–1 range for part of the cycle; the encoder clamps each channel to 0–255 when it writes the RGB24 buffer, so the stored image never holds a negative byte.

The hue-to-RGB conversion builds each channel from sine and cosine terms of the hue angle, and sines and cosines span −1 to +1. Offsets and scale factors center the channels near mid-gray, but for part of the cycle the raw terms in the published equation sit below zero. Nothing needs managing at display time: the clamp at the write step is the management, and a negative number exists only in intermediate floating-point math, never in the stored image or on screen.

The same container choice answers why recovery returns RGB24. A colorized depth map is deliberately an ordinary 8-bit RGB frame, because that is what lets formats, viewers and codecs treat it as a photo. The decode side reads that 24-bit layout back and reconstructs depth from it, instead of returning the original 16-bit numbers.

How do you invert the colormap back to depth?

Recovery turns each pixel back into a code, undoes the scaling to disparity, then applies Z = f·B / d, so the round trip reintroduces nothing beyond the quantization error tabulated above, about 1.7 mm at the near face of the example.

Per pixel the procedure is: match the stored RGB triple to its nearest entry in a 256-row lookup table, undo the scaling to disparity, convert to depth. Build the table once from the encoder's own channel math; noise moves a pixel a few bytes, not a few codes, so nearest-neighbor matching absorbs it. With the example numbers, d = 25 px + code × 0.68 px, then Z = 100 px·m / d. The same conversion worked per point pair is in the disparity-to-3D coordinates walkthrough.

Round-trip error stays at the quantization table provided nothing touches the color channels in between. Three things routinely do: chroma-subsampled compression, palette reduction, and white balance or color correction. GIF and palettized PNG at 256 colors survive only if the palette matches the code table.

Display-only colormaps are a different tool. If you want a stretched or false-color view and intend to keep measuring from the original 16-bit data, the JET colormap normalization guide changes the look while keeping the values, and the depth display inversion guide covers flipped views. Hue encoding is the stronger medicine: it replaces the stored representation, so measuring again requires the inverse above.

Which depth cameras benefit most?

Any triangulation design gains: stereo cameras, projected structured-light cameras and laser profilers all measure an offset or angle and convert through the same inverse relationship, so the Z² quantization law and the hue-over-disparity encoding match by construction.

Time-of-flight cameras time the returned light directly. Their error grows closer to linearly with distance, and there is no disparity to encode, so the near-field bonus mostly disappears. When the choice between the families is still open, the industrial 3D camera selection guide compares stereo, ToF and structured light on this kind of error behavior.

In the shop's 3D sensors category, also browsable as the camera finder, the projected structured-light cameras form depth from the offset between a projected pattern and its image, which is the relationship the scheme rides on:

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

The laser galvanometer stereo cameras sweep a laser line and triangulate from a stereo pair, so their measurements follow the same inverse law:

3D sensorsHikrobot MV-DLS300P-04 Laser galvanometer stereo cameraMV-DLS300P-04
Type
Stereo / structured light
$16,579.00 · quotedView and quote

One encoder and one decode table serve either; only f·B, d_near and d_far change with the model.

When should you not encode depth as hue?

Skip hue encoding when far-field precision drives the decision, when the consumer already reads 16-bit depth natively, or when the transport chain forces chroma-subsampled compression; in the example, the disparity scheme costs about 8× coarser codes at 4 m (109 mm versus 13.7 mm).

Far-field measurement is the main case against it. The scheme spends its 256 codes buying 8× precision at the near face and pays with 109 mm steps at 4.0 m, where uniform depth keeps 13.7 mm. Second, a downstream consumer that reads 16-bit depth natively on the wire needs no encoding at all; keep the numbers exact. Third, a transport chain that forces chroma-subsampled video will damage the encoding no matter how well you build it.

Alternatives that keep the arithmetic honest. If the link is lossless anyway, store the disparity field itself as 16-bit PNG and skip color entirely; quantization drops to zero. If one cycle must cover a huge range with roughly constant relative precision, scale the codes over log depth, which tracks relative error instead of the Z² law and splits the difference between the two table columns.

If the near field drives your application, as it does for parts presented to a robot or a gauging station at around half a meter, hue over disparity earns its decode step. Plan the camera's position and range with the 3D camera working distance guide, browse the rest of the depth-map toolkit on the 3D topic page, then size and assemble the camera in the camera configurator.

Questions

Does the pixel's brightness or exposure change the decoded depth?

No. The value lives in hue, not in brightness: the encoder fixes the saturation and value components, so two frames of the same scene decode identically no matter how the viewer sets brightness. What corrupts decoding is anything that shifts color — white balance, color LUTs, demosaicing raw data, viewer filters. Keep the pipeline color-neutral from encoder to decoder, and prove the round trip on one captured frame before trusting decoded millimeters.

Can 16-bit depth be stored losslessly in RGB24 instead?

Yes. Split each 16-bit sample into a high byte and a low byte and write them into two of the three channels; the third can carry a validity flag. This survives only lossless steps such as PNG or lossless WebP, and it displays as noise. It also compresses far worse than hue encoding, because neighboring pixels rarely share a byte. Choose byte packing for exactness, hue for image-like compressibility.

What depth range should the hue cycle cover?

Set the cycle to the real working range with margin, not the camera's full specification: every code spent on meters no part occupies is precision lost where parts live. For a 0.5–4.0 m task, encode 0.4–4.4 m. Add margin at both ends so sensor noise near the limits does not push pixels across the wrap point between code 255 and code 0, where nearest and farthest sit side by side.

What causes banding after decoding, and is it always the encoder?

Banding whose steps grow as distance squared is the encoding working as designed: 256 codes over disparity give 1.7 mm rings at the near face and 109 mm rings at 4.0 m in the worked example. Constant-width banding, or rings that wander between frames, points at the transport instead — chroma subsampling, palette reduction or a color-management stage shifting hues. Compare a PNG round trip against the compressed one to separate the two causes.

Do SDK colorization filters use this exact scheme?

Most depth SDKs ship colorization as a post-processing block with a numbered scheme selector, and a hue-over-disparity mode is a common option alongside rainbow and grayscale schemes. Two settings decide everything: whether the filter scales over depth or over disparity, and which depth range it assumes. Decode one captured frame with your own inverse table and compare against the source depth; a near-field match confirms the filter quantizes disparity.