Download build_3view_csv.py from Tri1/t2m-gpt-vsl-code: direct link, hf CLI and curl.
- Browser
- Download file 4.42 kB
-
https://huggingface.co/Tri1/t2m-gpt-vsl-code/resolve/main/build_3view_csv.py
- Command line
-
hf download hf://Tri1/t2m-gpt-vsl-code/build_3view_csv.py
-
curl -L -o build_3view_csv.py https://huggingface.co/Tri1/t2m-gpt-vsl-code/resolve/main/build_3view_csv.py
4.42 kB
| #!/usr/bin/env python3 | |
| """Build a 3-view (front/left/right) Full_TriVis CSV that `prepare_vsl_data.py` can pack. | |
| `Full_TriVis/split_lab_front.csv` covers only the front view: 24,151 clips. | |
| `Full_TriVis/Label/Dataset_full_lab.csv` is the master label file and holds all three | |
| views of the same sentences -- 72,453 rows = 24,151 x 3, scene `lab` throughout -- which | |
| matches the 72,453 lab `.npz` files under `Full_TriVis/skeleton/` exactly. | |
| The split is INHERITED, not redrawn. `splits.json` used `split_key = Sign_sentence`, so | |
| assigning each master row the split of its `Sign_sentence` keeps every view of a sentence | |
| in the same split. That preserves the text-disjoint property (a sentence never spans | |
| splits), and it keeps the new test set a strict superset of the old one, so front-only | |
| results stay directly comparable -- the front subset of the new test split IS the old test | |
| split. | |
| npz path = "Full_TriVis/skeleton/" + Sentence_video_path with .mp4 -> .npz. | |
| """ | |
| import argparse | |
| import collections | |
| import csv | |
| import os | |
| REPO = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..') | |
| COLS = ['split', 'npz_path', 'Sentence', 'Sign_sentence', 'Category', 'group', 'view', | |
| 'scene', 'ID_sentence', 'Sentence_video_path'] | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument('--front-csv', default=os.path.join(REPO, 'Full_TriVis', | |
| 'split_lab_front.csv')) | |
| ap.add_argument('--master-csv', default=os.path.join(REPO, 'Full_TriVis', 'Label', | |
| 'Dataset_full_lab.csv')) | |
| ap.add_argument('--skeleton-root', default='Full_TriVis/skeleton') | |
| ap.add_argument('--repo-root', default=REPO) | |
| ap.add_argument('--views', default='front,left,right') | |
| ap.add_argument('--out', default=os.path.join(REPO, 'Full_TriVis', | |
| 'split_lab_3view.csv')) | |
| ap.add_argument('--check-exists', action='store_true', | |
| help='stat every npz and drop the missing ones (slow but safe)') | |
| args = ap.parse_args() | |
| want = set(args.views.split(',')) | |
| with open(args.front_csv, newline='', encoding='utf-8') as f: | |
| front = list(csv.DictReader(f)) | |
| split_of = {r['Sign_sentence']: r['split'] for r in front} | |
| print(f'{len(front)} front rows -> {len(split_of)} distinct Sign_sentence with a split') | |
| with open(args.master_csv, newline='', encoding='utf-8') as f: | |
| master = list(csv.DictReader(f)) | |
| print(f'{len(master)} master rows, views {sorted({r["view"] for r in master})}') | |
| rows, missing_split, missing_file = [], 0, 0 | |
| for r in master: | |
| if r['view'] not in want: | |
| continue | |
| sp = split_of.get(r['Sign_sentence']) | |
| if sp is None: | |
| missing_split += 1 | |
| continue | |
| npz = os.path.join(args.skeleton_root, | |
| r['Sentence_video_path'].replace('.mp4', '.npz')) | |
| if args.check_exists and not os.path.exists(os.path.join(args.repo_root, npz)): | |
| missing_file += 1 | |
| continue | |
| rows.append({'split': sp, 'npz_path': npz, 'Sentence': r['Sentence'], | |
| 'Sign_sentence': r['Sign_sentence'], 'Category': r['Category'], | |
| 'group': r['group'], 'view': r['view'], 'scene': r['scene'], | |
| 'ID_sentence': r['ID_sentence'], | |
| 'Sentence_video_path': r['Sentence_video_path']}) | |
| with open(args.out, 'w', newline='', encoding='utf-8') as f: | |
| w = csv.DictWriter(f, fieldnames=COLS) | |
| w.writeheader() | |
| w.writerows(rows) | |
| print(f'wrote {args.out}: {len(rows)} rows ' | |
| f'(no split {missing_split}, missing npz {missing_file})') | |
| print(' split x view:') | |
| c = collections.Counter((r['split'], r['view']) for r in rows) | |
| for sp in ('train', 'val', 'test'): | |
| line = ' '.join(f'{v} {c[(sp, v)]}' for v in sorted(want)) | |
| print(f' {sp:<6} {line} total {sum(c[(sp, v)] for v in want)}') | |
| # leak check, the same one splits.json reports | |
| by = collections.defaultdict(set) | |
| for r in rows: | |
| by[r['Sign_sentence']].add(r['split']) | |
| span = sum(1 for v in by.values() if len(v) > 1) | |
| print(f' leakage_check: {"PASS" if span == 0 else "FAIL"}: {span} Sign_sentence ' | |
| f'values span multiple splits') | |
| if __name__ == '__main__': | |
| main() | |