Back to LuminaBone
🦴 LuminaBone

Bench Results — 17-Sample Bone Depth Study

Results June 2026 3 min read

17 bone samples (“locations”), each photographed 4 times by a multi-LED rig. Depth was recovered per sample with Woodham photometric stereo (per-pixel surface normals from 3 single-LED images) + Frankot–Chellappa FFT integration.

Capture convention (verified on all 17 locations)

File Lighting Notes
pN-1.jpgAll LEDs onUniform reference; NOT used for the depth solve
pN-2.jpgRIGHT LEDLight azimuth ~0°
pN-3.jpgTOP/upper LEDLight azimuth ~40–90°
pN-4.jpgLEFT LEDLight azimuth ~180°

Files in this folder

The bundled PNGs — per-sample depth maps, normal maps, and panel figures — are not mirrored on this page.

depth_summary columns

Column Meaning
locationSample number 1..17
width, heightWorking resolution used (640×360)
n_lightsLEDs used for the solve (3)
azimuths_degLight directions used (0; 90; 180 = right; top; left)
depth_min/maxRelative depth extremes
depth_mean/stdMean is ~0 by construction; std = overall roughness
relief_p2_p98Headline number: robust peak-to-valley surface relief (bigger = more pronounced 3-D structure on that sample)

What the numbers mean

Photometric stereo recovers SHAPE up to an unknown offset and scale, so depth is RELATIVE (working-pixel units), not absolute millimetres. The shape and the relative height differences are meaningful; the absolute value is not. To get true mm later you would add one coaxial point-light image and rescale — see the note at the bottom of bone_depth_batch.py.

How to re-run

pip install numpy opencv-python scipy matplotlib
# put the pN-M.jpg photos in a folder, set INPUT_FOLDER at the top of the
# script to point at it, then:
python bone_depth_batch.py

Outputs land in ./depth_outputs (the PNGs and the CSV in this folder).

Caveat

With 3 oblique, uncalibrated LEDs on a glossy specimen, fine relief is reliable but the very-low-frequency “overall tilt” of each map is approximate — inherent to photometric stereo, not a bug. Specular-glint removal is on by default.

Per-location depth estimates

One row per sample location. depth_px is the robust peak-to-valley relief in working-resolution pixels; depth_mm_at_30mm_FOV is the same relief converted to millimetres assuming a 30 mm field of view.

location image_width_px image_height_px depth_px depth_mm_at_30mm_FOV max_relief_px roughness_px
164036064.483.02373.1919.35
264036061.282.87266.8317.67
364036059.192.77468.2815.59
464036057.882.71365.3717.55
564036056.942.66965.2517.73
664036052.732.47261.3417.48
764036051.932.43457.1616.00
864036050.482.36660.1313.58
964036045.612.13856.3711.69
1064036048.492.27355.8712.99
1164036053.442.50559.5215.33
1264036056.312.6464.6517.59
1364036055.952.62362.2818.23
1464036055.792.61562.6917.44
1564036049.822.33555.8814.91
1664036042.611.99752.8811.36
1764036046.012.15755.3311.37

Across the 17 locations, mean peak-to-valley relief is roughly 2.5 mm (range 2.0–3.0 mm) under the 30 mm field-of-view assumption. These millimetre figures inherit the relative-scale caveat above: the pixel-to-mm conversion assumes the stated FOV rather than a metric calibration.