Files
DeeJanuz--frametop/hands/tools/cut_sets.py
T
DeeJanuzandClaude Opus 5.5 50c14545ed Hands: pick the cameras by the light, and detect grips
ft-hands tracks with the mono IR cameras in dim light and with every
camera (or the colour pair, HANDS_BRIGHT) in bright light, going by the
colour frames' mean brightness with hysteresis and a 2 s hold
(HANDS_CAMERAS=auto, the default; mono, color and all fix it). Colour
frames are placed on the mono cameras' clock by their dequeue time, and a
view in a camera a step lacks waits for that camera's next frame.

A grip (a closed hand) is a second gesture next to the pinch, in version 2
of the gestures file: every fingertip curled toward the wrist, beginning
only on a hand seen open within a second and held up in front. On the
2026-09-30 lit recording that leaves 6 false grips of 14, all with the
hands on the desk; pinch counts are unchanged. ft-handreplay logs grips
and finger curl, watch_gestures.py shows them, and tools/cut_sets.py
copies a few sets out of a recording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:31:17 -06:00

52 lines
1.6 KiB
Python

"""Copy a few frame sets out of a recording (ft-hands --record) into a small one, to look at
or check elsewhere without moving gigabytes. Plain Python, so it runs on the Frame's host.
usage: python3 tools/cut_sets.py REC_DIR OUT_DIR [--sets N] (8, spread evenly) | [--at I,J,...]
"""
import argparse
import os
import struct
HDR = struct.Struct('<8sII')
def offsets(path):
offs, size = [], os.path.getsize(path)
with open(path, 'rb') as f:
off = 0
while off + HDR.size <= size:
f.seek(off)
magic, _, nbytes = HDR.unpack(f.read(HDR.size))
if magic[:7] != b'FHSET01' or off + nbytes > size:
break
offs.append((off, nbytes))
off += nbytes
return offs
def main():
ap = argparse.ArgumentParser()
ap.add_argument('rec')
ap.add_argument('out')
ap.add_argument('--sets', type=int, default=8)
ap.add_argument('--at', default='')
a = ap.parse_args()
src = os.path.join(a.rec, 'sets.bin')
offs = offsets(src)
if a.at:
pick = [int(i) for i in a.at.split(',')]
else:
n = max(1, min(a.sets, len(offs)))
pick = [round(i * (len(offs) - 1) / max(n - 1, 1)) for i in range(n)]
os.makedirs(a.out, exist_ok=True)
with open(src, 'rb') as f, open(os.path.join(a.out, 'sets.bin'), 'wb') as out:
for i in pick:
off, nbytes = offs[i]
f.seek(off)
out.write(f.read(nbytes))
print('%d of %d sets (%s) -> %s' % (len(pick), len(offs), ','.join(map(str, pick)), a.out))
if __name__ == '__main__':
main()