7e4ef6f98b
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
187 lines
5.6 KiB
Python
187 lines
5.6 KiB
Python
import os
|
|
import glob
|
|
import json
|
|
import numpy as np
|
|
|
|
import subprocess
|
|
from concurrent import futures
|
|
import multiprocessing as mp
|
|
|
|
from preproc.datasets import update_args
|
|
|
|
|
|
SRC_DIR = os.path.abspath(f"{__file__}/../")
|
|
|
|
|
|
def isimage(path):
|
|
ext = os.path.splitext(path)[-1].lower()
|
|
return ext == ".png" or ext == ".jpg" or ext == ".jpeg"
|
|
|
|
|
|
def split_frames_equal(img_dir, seq_len=-1):
|
|
"""
|
|
split the sequence into subsequences of seq_len
|
|
returns start and end indices for each subsequence
|
|
"""
|
|
if seq_len == -1: # don't split
|
|
return [(0, -1)]
|
|
|
|
image_list = sorted(list(filter(isimage, os.listdir(img_dir))))
|
|
num_imgs = len(image_list)
|
|
splits = list(range(0, num_imgs, seq_len))
|
|
splits[-1] = num_imgs # add remainder to last subseq
|
|
return list(zip(splits[:-1], splits[1:]))
|
|
|
|
|
|
def split_frames_shots(img_dir, shot_path, pad_shot=0, min_len=0):
|
|
"""
|
|
split the sequence into subsequences according by shots in the video
|
|
returns start and end indices for each subsequence
|
|
"""
|
|
if shot_path is None or not os.path.isfile(shot_path):
|
|
print(f"{shot_path} DOES NOT EXIST, USING WHOLE SEQUENCE")
|
|
return [(0, -1)], [0]
|
|
|
|
image_list = sorted(list(filter(isimage, os.listdir(img_dir))))#[:500]
|
|
num_frames = len(image_list)
|
|
|
|
with open(shot_path, "r") as f:
|
|
shot_dict = json.load(f)
|
|
|
|
# print(shot_dict.keys())
|
|
shot_idcs = np.array([shot_dict[name] for name in image_list])
|
|
subseqs = []
|
|
for i in np.unique(shot_idcs):
|
|
idcs = np.where(shot_idcs == i)[0]
|
|
start, end = idcs.min(), idcs.max() + 1
|
|
if pad_shot > 0:
|
|
if start > 0:
|
|
start = start + pad_shot
|
|
if end < num_frames:
|
|
end = end - pad_shot
|
|
if (end - start) < min_len: # this shot is too short
|
|
continue
|
|
subseqs.append((start, end))
|
|
return subseqs, np.unique(shot_idcs)
|
|
|
|
|
|
def split_sequence(args, img_dir, seq):
|
|
subseqs = split_frames_equal(img_dir, args.seq_len)
|
|
return subseqs, [None for _ in subseqs]
|
|
|
|
|
|
def get_out_dir(args, seq, shot_idx=None, start=0, end=-1):
|
|
if "egobody" in args.type or "3dpw" in args.type:
|
|
if args.use_intrins:
|
|
out_name = "cameras_intrins"
|
|
else:
|
|
out_name = "cameras_default"
|
|
else:
|
|
out_name = "cameras"
|
|
|
|
if args.seq_len > 0:
|
|
out_name = f"{out_name}_split"
|
|
|
|
out_dir = f"{args.root}/slahmr/{args.split}/{out_name}/{seq}"
|
|
|
|
if args.seq_len > 0:
|
|
return f"{out_dir}/{start}-{end}"
|
|
|
|
if args.type == "posetrack" and shot_idx is not None:
|
|
return f"{out_dir}/shot-{shot_idx}"
|
|
|
|
return out_dir
|
|
|
|
|
|
def get_intrins_path(data_type, data_root, seq):
|
|
raise NotImplementedError
|
|
|
|
|
|
def get_command(img_dir, out_dir, start=0, end=-1, intrins_path=None, overwrite=False):
|
|
cmd_args = [
|
|
f"python {SRC_DIR}/run_slam.py",
|
|
"-i",
|
|
img_dir,
|
|
"--map_dir",
|
|
out_dir,
|
|
"--disable_vis",
|
|
]
|
|
if start != 0:
|
|
cmd_args += ["--start", str(start)]
|
|
if end != -1:
|
|
cmd_args += ["--end", str(end)]
|
|
|
|
if intrins_path is not None:
|
|
cmd_args += ["--intrins_path", intrins_path]
|
|
|
|
if overwrite:
|
|
cmd_args.append("--overwrite")
|
|
|
|
cmd = " ".join(cmd_args)
|
|
return cmd
|
|
|
|
|
|
def check_intrins(data_type, data_root, intrins_path, img_dir):
|
|
assert intrins_path is not None
|
|
out_name = intrins_path.split(data_root)[1].strip("/").split("/")[0]
|
|
out_root = f"{data_root}/{out_name}"
|
|
return intrins_path
|
|
|
|
|
|
def get_slam_command(args, img_dir, seq, shot_idx=None, start=0, end=-1):
|
|
out_dir = get_out_dir(args, seq, shot_idx, start, end)
|
|
intrins_path = None
|
|
if args.use_intrins:
|
|
intrins_path = get_intrins_path(args.type, args.root, seq)
|
|
if intrins_path is not None:
|
|
intrins_path = check_intrins(args.type, args.root, intrins_path, img_dir)
|
|
return get_command(
|
|
img_dir,
|
|
out_dir,
|
|
start=start,
|
|
end=end,
|
|
intrins_path=intrins_path,
|
|
overwrite=args.overwrite,
|
|
)
|
|
|
|
|
|
def launch_job(gpus, cmd):
|
|
cur_proc = mp.current_process()
|
|
print(cur_proc.name, cur_proc._identity)
|
|
worker_id = cur_proc._identity[0] - 1
|
|
gpu = gpus[worker_id % len(gpus)]
|
|
cmd = f"CUDA_VISIBLE_DEVICES={gpu} {cmd}"
|
|
print(cmd)
|
|
subprocess.call(cmd, shell=True)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--type", default="posetrack", help="dataset to process")
|
|
parser.add_argument(
|
|
"--root", default=None, help="root of data to process, default None"
|
|
)
|
|
parser.add_argument(
|
|
"--split", default="val", help="split of dataset to process, default val"
|
|
)
|
|
parser.add_argument("--gpus", nargs="*", default=[0])
|
|
parser.add_argument("--seqs", nargs="*", default=None)
|
|
parser.add_argument("--seq_len", type=int, default=-1)
|
|
parser.add_argument(
|
|
"--use_intrins", action="store_true", help="use GT intrinsics if available"
|
|
)
|
|
parser.add_argument("-y", "--overwrite", action="store_true")
|
|
args = parser.parse_args()
|
|
args = update_args(args)
|
|
|
|
print(f"Running SLAM on {len(args.seqs)} sequences")
|
|
with futures.ProcessPoolExecutor(max_workers=len(args.gpus)) as ex:
|
|
for img_dir, seq in zip(args.img_dirs, args.seqs):
|
|
subseqs, shot_idcs = split_sequence(args, img_dir, seq)
|
|
for shot, (start, end) in zip(shot_idcs, subseqs):
|
|
cmd = get_slam_command(args, img_dir, seq, shot, start, end)
|
|
print(cmd)
|
|
ex.submit(launch_job, args.gpus, cmd)
|