62 lines
2.6 KiB
Python
62 lines
2.6 KiB
Python
|
|
"""Cluster the worst-stretched edges by REST position to name the digit region."""
|
||
|
|
import sys, os, math
|
||
|
|
|
||
|
|
def load_obj(path):
|
||
|
|
vs, faces = [], []
|
||
|
|
with open(path) as f:
|
||
|
|
for line in f:
|
||
|
|
if line.startswith('v '):
|
||
|
|
p = line.split()
|
||
|
|
vs.append((float(p[1]), float(p[2]), float(p[3])))
|
||
|
|
elif line.startswith('f '):
|
||
|
|
idx = [int(tok.split('/')[0]) - 1 for tok in line.split()[1:]]
|
||
|
|
for i in range(1, len(idx) - 1):
|
||
|
|
faces.append((idx[0], idx[i], idx[i + 1]))
|
||
|
|
return vs, faces
|
||
|
|
|
||
|
|
def edge_set(faces):
|
||
|
|
es = set()
|
||
|
|
for a, b, c in faces:
|
||
|
|
for u, v in ((a, b), (b, c), (c, a)):
|
||
|
|
es.add((u, v) if u < v else (v, u))
|
||
|
|
return sorted(es)
|
||
|
|
|
||
|
|
def dist(p, q):
|
||
|
|
return math.sqrt(sum((p[i]-q[i])**2 for i in range(3)))
|
||
|
|
|
||
|
|
d = sys.argv[1]
|
||
|
|
for hand in ('l', 'r'):
|
||
|
|
rest_v, rest_f = load_obj(os.path.join(d, f'rest_hand_{hand}.obj'))
|
||
|
|
edges = edge_set(rest_f)
|
||
|
|
xs = sorted(v[0] for v in rest_v)
|
||
|
|
print(f'hand_{hand}: rest x range {xs[0]*100:.1f}..{xs[-1]*100:.1f} cm, '
|
||
|
|
f'y range {min(v[1] for v in rest_v)*100:.1f}..{max(v[1] for v in rest_v)*100:.1f}, '
|
||
|
|
f'z range {min(v[2] for v in rest_v)*100:.1f}..{max(v[2] for v in rest_v)*100:.1f}')
|
||
|
|
for pose in ('fist', 'grip'):
|
||
|
|
v, _ = load_obj(os.path.join(d, f'{pose}_hand_{hand}.obj'))
|
||
|
|
bad = []
|
||
|
|
for a, b in edges:
|
||
|
|
rl = dist(rest_v[a], rest_v[b])
|
||
|
|
if rl <= 1e-9:
|
||
|
|
continue
|
||
|
|
r = dist(v[a], v[b]) / rl
|
||
|
|
if r > 5:
|
||
|
|
bad.append((r, a))
|
||
|
|
# bounding box of bad verts in rest space
|
||
|
|
pts = [rest_v[a] for _, a in bad]
|
||
|
|
if not pts:
|
||
|
|
print(f' {pose}: no >5x edges')
|
||
|
|
continue
|
||
|
|
bx = (min(p[0] for p in pts)*100, max(p[0] for p in pts)*100)
|
||
|
|
by = (min(p[1] for p in pts)*100, max(p[1] for p in pts)*100)
|
||
|
|
bz = (min(p[2] for p in pts)*100, max(p[2] for p in pts)*100)
|
||
|
|
cx = sum(p[0] for p in pts)/len(pts)*100
|
||
|
|
cy = sum(p[1] for p in pts)/len(pts)*100
|
||
|
|
cz = sum(p[2] for p in pts)/len(pts)*100
|
||
|
|
print(f' {pose}: {len(bad)} edges>5x rest-bbox x[{bx[0]:.1f},{bx[1]:.1f}] '
|
||
|
|
f'y[{by[0]:.1f},{by[1]:.1f}] z[{bz[0]:.1f},{bz[1]:.1f}] centroid ({cx:.1f},{cy:.1f},{cz:.1f}) cm')
|
||
|
|
# z-histogram (palm axis?) to see if it's one digit or spread
|
||
|
|
zs = sorted(p[2]*100 for p in pts)
|
||
|
|
q = lambda f: zs[int(f*(len(zs)-1))]
|
||
|
|
print(f' rest z quartiles: {q(0):.1f} / {q(0.25):.1f} / {q(0.5):.1f} / {q(0.75):.1f} / {q(1):.1f}')
|