Spaces:
Running
Running
| <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 > 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| > 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> |