File size: 9,105 Bytes
372de9f
 
 
 
 
 
 
 
 
 
 
a33871a
 
372de9f
 
 
 
 
 
 
 
 
a33871a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
372de9f
a33871a
 
 
 
372de9f
 
a33871a
 
 
 
372de9f
 
 
 
a33871a
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!doctype html><html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>3D reconstruction workbench — every stage, 20 samples</title>
<style>body{background:#0f1420;color:#e8ecf4;font-family:system-ui,sans-serif;
margin:0;padding:28px}.wrap{max-width:1900px;margin:0 auto}
h1{font-size:26px;margin:0 0 6px}h2{color:#ffd9a0;font-size:18px;margin:26px 0 8px}
p{color:#b9c2d0;line-height:1.55;max-width:1000px}
img{width:100%;background:#fff;border-radius:5px;margin:5px 0}
table{border-collapse:collapse;margin:10px 0;font-size:13px}
th,td{border:1px solid #2c3648;padding:5px 10px;text-align:left}
th{color:#ffd9a0;font-weight:600}code{background:#1b2334;padding:1px 5px;border-radius:3px}
.note{color:#8e99ab;font-size:13px}
.good{color:#7be0a0}.bad{color:#ff9a8a}</style></head><body><div class="wrap">
<h1>3D reconstruction workbench — every stage, 20 samples</h1>
<p>Not a results figure: this is the full chain with every tunable quantity
exposed, so a defect can be attributed to a stage. Columns:
<b>1</b> raw · <b>2</b> reference · <b>3</b> dI = img−ref (×3) ·
<b>4</b> max|dI| · <b>5</b> valid mask · <b>6</b> LUT bin observed? ·
<b>7</b> gx · <b>8</b> gy · <b>9</b> |grad| · <b>10</b> div(g) = Poisson RHS ·
<b>11</b> depth · <b>12</b> depth halo-removed · <b>13</b> radial profile vs
analytic cap · <b>14</b> Open3D mesh.
Reproduce: <code>xvfb-run -a -s "-screen 0 1400x1000x24" python -m
force_recovery.recon_study glowtact</code>, then
<code>python -m force_recovery.recon_study page</code>.
The source here (GlowTact) is markerless, so the adopted marker step
(<code>marker_removal.stages_depth</code>) is a bit-exact no-op on these
frames; on a marker gel it inpaints the dots out of the reference and the
frame before column 3.</p>

<h2>What external ground truth did to this page</h2>
<p>Everything below used to be scored against our own expectations. It is now
scored against exact per-pixel ground truth — ray-cast mesh depth on 420
Tactile MNIST touches (<code>mnist_validation</code>) — and two of the three
defects we published moved:</p>
<table><tr><th>claim</th><th>status after per-pixel GT</th></tr>
<tr><td>Flat-topped indenters over-dome badly (centre/rim 1.23–1.42 where
1.0 is correct)</td>
<td class="bad"><b>retracted and re-measured.</b> Compliant gel wraps a flat
edge, so c/r &gt; 1 is <i>expected</i>: the true depth map of a pressed digit
has c/r <b>1.400</b> (gel surface 1.334) and we reconstruct 1.539–1.562
(<b>+10–12%</b>); on an enclosed plateau control whose truth is exactly 1.000
we measure <b>1.069</b> (<b>+7%</b>). Most of the 1.23–1.42 in the table
below is real curvature, not artefact.</td></tr>
<tr><td>Up to 22% of contact pixels land in unobserved LUT bins — a top
defect</td>
<td class="bad"><b>demoted to a minor factor.</b> On the GT set 13.8% / 16.9%
of contact pixels are unobserved, and their correlation with per-touch
Type-2 error is only <b>0.098 / 0.294</b>. Still worth showing (column 6),
no longer worth blaming.</td></tr>
<tr><td>The valid mask is halo-dominated</td>
<td class="good"><b>confirmed and quantified.</b> Against the true contact
region the <code>|dI| &gt; 8</code> mask scores IoU <b>0.614</b>, recall
<b>0.917</b>, over-segmentation <b>0.531</b> — it finds nearly all of the
contact and then adds half as much again in halo.</td></tr>
<tr><td>(new) the photometric table is the weak link</td>
<td class="good"><b>ruled out.</b> LUT gradient direction vs true gel
gradient is <b>24.4°</b> on the GT renders against <b>26.1°</b> for this
table on its own real sensor — the same statistic, no worse off-domain.</td>
</tr></table>

<h2>The real headline: accuracy is a function of press depth</h2>
<p>Same digit meshes, re-rendered at five penetrations, no per-frame fitting
of any kind (the photometric table is calibrated once on that sensor's own
sphere presses, the recipe we already use per sensor):</p>
<table><tr><th>press depth [mm]</th><th>0.30</th><th>0.60</th><th>1.00</th>
<th>1.50</th><th>2.25 (what the dataset ships)</th></tr>
<tr><td>MAE [µm]</td><td class="good"><b>11.2</b></td><td class="good">35.0</td>
<td>67.8</td><td>127.4</td><td class="bad">281.1</td></tr>
<tr><td>Type-2 error [µm]</td><td class="good"><b>96.5</b></td><td>186.3</td>
<td>308.6</td><td>514.6</td><td class="bad">961.8</td></tr>
<tr><td>peak ours / GT</td><td>1.00</td><td>0.97</td><td>0.77</td><td>0.68</td>
<td class="bad">0.55</td></tr></table>
<p>So the honest public claim is a <b>range</b>, not a number: at ≤0.6 mm this
reconstruction is accurate on non-spherical ground truth with zero fitting; by
2.25 mm it recovers barely half the peak. No accuracy figure on this site
should be quoted without the press depth it was measured at.</p>

<h2>Per-sample diagnostics</h2>
<p class="note">centre/rim is reported <b>descriptively</b> — read it against
the GT ratio for that geometry (1.33–1.40 for a compliant press), never
against 1.0.</p>
<table><tr><th>sample</th><th>peak [mm]</th><th>unobserved LUT</th><th>centre/rim<br><span class='note'>GT for a compliant press: 1.33–1.40</span></th><th>grad angle<br><span class='note'>chance 90°</span></th><th>profile RMS</th></tr><tr><td>round z=2.12mm F=4.4N</td><td>1.60</td><td>0%</td><td>1.46</td><td>6.8</td><td>69</td></tr><tr><td>round z=3.21mm F=9.4N</td><td>2.55</td><td>4%</td><td>1.43</td><td>5.8</td><td>35</td></tr><tr><td>round z=3.80mm F=14.8N</td><td>2.94</td><td>1%</td><td>1.44</td><td>5.1</td><td>105</td></tr><tr><td>star z=1.73mm F=3.0N</td><td>1.61</td><td>2%</td><td>1.44</td><td></td><td></td></tr><tr><td>star z=2.34mm F=8.0N</td><td>2.07</td><td>10%</td><td>1.33</td><td></td><td></td></tr><tr><td>star z=2.96mm F=11.0N</td><td>2.03</td><td>14%</td><td>1.36</td><td></td><td></td></tr><tr><td>star z=3.53mm F=16.0N</td><td>2.30</td><td>22%</td><td>1.35</td><td></td><td></td></tr><tr><td>triangle z=2.28mm F=4.9N</td><td>1.40</td><td>5%</td><td>1.42</td><td></td><td></td></tr><tr><td>triangle z=3.11mm F=9.7N</td><td>2.05</td><td>9%</td><td>1.31</td><td></td><td></td></tr><tr><td>triangle z=3.75mm F=14.7N</td><td>2.66</td><td>10%</td><td>1.32</td><td></td><td></td></tr><tr><td>quad z=2.16mm F=3.6N</td><td>1.19</td><td>4%</td><td>1.32</td><td></td><td></td></tr><tr><td>quad z=2.94mm F=9.2N</td><td>1.75</td><td>9%</td><td>1.24</td><td></td><td></td></tr><tr><td>quad z=3.52mm F=14.2N</td><td>2.32</td><td>10%</td><td>1.23</td><td></td><td></td></tr><tr><td>quad_small z=1.51mm F=3.9N</td><td>1.43</td><td>7%</td><td>1.32</td><td></td><td></td></tr><tr><td>quad_small z=2.55mm F=9.2N</td><td>2.51</td><td>6%</td><td>1.35</td><td></td><td></td></tr><tr><td>quad_small z=3.47mm F=13.7N</td><td>2.93</td><td>8%</td><td>1.35</td><td></td><td></td></tr><tr><td>quad_small z=3.97mm F=17.4N</td><td>2.66</td><td>12%</td><td>1.42</td><td></td><td></td></tr><tr><td>B z=2.91mm F=4.9N</td><td>1.96</td><td>7%</td><td>1.39</td><td></td><td></td></tr><tr><td>B z=4.04mm F=10.6N</td><td>2.83</td><td>6%</td><td>1.39</td><td></td><td></td></tr><tr><td>B z=4.48mm F=13.7N</td><td>2.87</td><td>5%</td><td>1.40</td><td></td><td></td></tr></table>
<p class="note">Grad angle and profile RMS are only defined where the indenter
is a sphere of known radius (the <code>round</code> family): the LUT gradient
sits 5.1–6.8° from the analytic sphere gradient and the radial profile
matches the cap to 35–105 µm, so on this sensor the table and the solver
are both sound. Every one of these frames is a deep press (1.5–4.5 mm) —
i.e. the regime the sweep above shows is our worst.</p>
<footer style="margin-top:30px;color:#6f7a8c;font-size:13px">
React force recovery · <a href="index.html" style="color:#ffd9a0">overview</a> ·
<a href="method.html" style="color:#ffd9a0">method</a> ·
<a href="results.html" style="color:#ffd9a0">results</a></footer>
<img src='assets/recon/glowtact_00.png' loading='lazy'><br><img src='assets/recon/glowtact_01.png' loading='lazy'><br><img src='assets/recon/glowtact_02.png' loading='lazy'><br><img src='assets/recon/glowtact_03.png' loading='lazy'><br><img src='assets/recon/glowtact_04.png' loading='lazy'><br><img src='assets/recon/glowtact_05.png' loading='lazy'><br><img src='assets/recon/glowtact_06.png' loading='lazy'><br><img src='assets/recon/glowtact_07.png' loading='lazy'><br><img src='assets/recon/glowtact_08.png' loading='lazy'><br><img src='assets/recon/glowtact_09.png' loading='lazy'><br><img src='assets/recon/glowtact_10.png' loading='lazy'><br><img src='assets/recon/glowtact_11.png' loading='lazy'><br><img src='assets/recon/glowtact_12.png' loading='lazy'><br><img src='assets/recon/glowtact_13.png' loading='lazy'><br><img src='assets/recon/glowtact_14.png' loading='lazy'><br><img src='assets/recon/glowtact_15.png' loading='lazy'><br><img src='assets/recon/glowtact_16.png' loading='lazy'><br><img src='assets/recon/glowtact_17.png' loading='lazy'><br><img src='assets/recon/glowtact_18.png' loading='lazy'><br><img src='assets/recon/glowtact_19.png' loading='lazy'><br>
</div></body></html>