From 447daefcd5fba2c6c081a43bdd940d5510a4d768 Mon Sep 17 00:00:00 2001 From: Floris Erich Date: Mon, 22 May 2023 14:46:33 +0900 Subject: [PATCH 1/5] If there are multiple camera intrinsics available, set the specific camera intrinsics per frame --- scripts/colmap2nerf.py | 178 ++++++++++++++++++++++++----------------- 1 file changed, 105 insertions(+), 73 deletions(-) diff --git a/scripts/colmap2nerf.py b/scripts/colmap2nerf.py index 064f7e10d..0b5d9126f 100755 --- a/scripts/colmap2nerf.py +++ b/scripts/colmap2nerf.py @@ -202,6 +202,7 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays TEXT_FOLDER = args.text OUT_PATH = args.out print(f"outputting to {OUT_PATH}...") + cameras = {} with open(os.path.join(TEXT_FOLDER,"cameras.txt"), "r") as f: angle_x = math.pi / 2 for line in f: @@ -211,95 +212,109 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays if line[0] == "#": continue els = line.split(" ") - w = float(els[2]) - h = float(els[3]) - fl_x = float(els[4]) - fl_y = float(els[4]) - k1 = 0 - k2 = 0 - k3 = 0 - k4 = 0 - p1 = 0 - p2 = 0 - cx = w / 2 - cy = h / 2 - is_fisheye = False + camera = {} + camera_id = int(els[0]) + camera['w'] = float(els[2]) + camera['h'] = float(els[3]) + camera['fl_x'] = float(els[4]) + camera['fl_y'] = float(els[4]) + camera['k1'] = 0 + camera['k2'] = 0 + camera['k3'] = 0 + camera['k4'] = 0 + camera['p1'] = 0 + camera['p2'] = 0 + camera['cx'] = camera['w'] / 2 + camera['cy'] = camera['h'] / 2 + camera['is_fisheye'] = False if els[1] == "SIMPLE_PINHOLE": - cx = float(els[5]) - cy = float(els[6]) + camera['cx'] = float(els[5]) + camera['cy'] = float(els[6]) elif els[1] == "PINHOLE": - fl_y = float(els[5]) - cx = float(els[6]) - cy = float(els[7]) + camera['fl_y'] = float(els[5]) + camera['cx'] = float(els[6]) + camera['cy'] = float(els[7]) elif els[1] == "SIMPLE_RADIAL": - cx = float(els[5]) - cy = float(els[6]) - k1 = float(els[7]) + camera['cx'] = float(els[5]) + camera['cy'] = float(els[6]) + camera['k1'] = float(els[7]) elif els[1] == "RADIAL": - cx = float(els[5]) - cy = float(els[6]) - k1 = float(els[7]) - k2 = float(els[8]) + camera['cx'] = float(els[5]) + camera['cy'] = float(els[6]) + camera['k1'] = float(els[7]) + camera['k2'] = float(els[8]) elif els[1] == "OPENCV": - fl_y = float(els[5]) - cx = float(els[6]) - cy = float(els[7]) - k1 = float(els[8]) - k2 = float(els[9]) - p1 = float(els[10]) - p2 = float(els[11]) + camera['fl_y'] = float(els[5]) + camera['cx'] = float(els[6]) + camera['cy'] = float(els[7]) + camera['k1'] = float(els[8]) + camera['k2'] = float(els[9]) + camera['p1'] = float(els[10]) + camera['p2'] = float(els[11]) elif els[1] == "SIMPLE_RADIAL_FISHEYE": - is_fisheye = True - cx = float(els[5]) - cy = float(els[6]) - k1 = float(els[7]) + camera['is_fisheye'] = True + camera['cx'] = float(els[5]) + camera['cy'] = float(els[6]) + camera['k1'] = float(els[7]) elif els[1] == "RADIAL_FISHEYE": - is_fisheye = True - cx = float(els[5]) - cy = float(els[6]) - k1 = float(els[7]) - k2 = float(els[8]) + camera['is_fisheye'] = True + camera['cx'] = float(els[5]) + camera['cy'] = float(els[6]) + camera['k1'] = float(els[7]) + camera['k2'] = float(els[8]) elif els[1] == "OPENCV_FISHEYE": - is_fisheye = True - fl_y = float(els[5]) - cx = float(els[6]) - cy = float(els[7]) - k1 = float(els[8]) - k2 = float(els[9]) - k3 = float(els[10]) - k4 = float(els[11]) + camera['is_fisheye'] = True + camera['fl_y'] = float(els[5]) + camera['cx'] = float(els[6]) + camera['cy'] = float(els[7]) + camera['k1'] = float(els[8]) + camera['k2'] = float(els[9]) + camera['k3'] = float(els[10]) + camera['k4'] = float(els[11]) else: print("Unknown camera model ", els[1]) # fl = 0.5 * w / tan(0.5 * angle_x); - angle_x = math.atan(w / (fl_x * 2)) * 2 - angle_y = math.atan(h / (fl_y * 2)) * 2 - fovx = angle_x * 180 / math.pi - fovy = angle_y * 180 / math.pi + camera['angle_x'] = math.atan(camera['w'] / (camera['fl_x'] * 2)) * 2 + camera['angle_y'] = math.atan(camera['h'] / (camera['fl_y'] * 2)) * 2 + camera['fovx'] = camera['angle_x'] * 180 / math.pi + camera['fovy'] = camera['angle_y'] * 180 / math.pi - print(f"camera:\n\tres={w,h}\n\tcenter={cx,cy}\n\tfocal={fl_x,fl_y}\n\tfov={fovx,fovy}\n\tk={k1,k2} p={p1,p2} ") + print(f"camera {camera_id}:\n\tres={camera['w'],camera['h']}\n\tcenter={camera['cx'],camera['cy']}\n\tfocal={camera['fl_x'],camera['fl_y']}\n\tfov={camera['fovx'],camera['fovy']}\n\tk={camera['k1'],camera['k2']} p={camera['p1'],camera['p2']} ") + cameras[camera_id] = camera + + if len(cameras) == 0: + print("No cameras found!") + sys.exit(1) with open(os.path.join(TEXT_FOLDER,"images.txt"), "r") as f: i = 0 bottom = np.array([0.0, 0.0, 0.0, 1.0]).reshape([1, 4]) - out = { - "camera_angle_x": angle_x, - "camera_angle_y": angle_y, - "fl_x": fl_x, - "fl_y": fl_y, - "k1": k1, - "k2": k2, - "k3": k3, - "k4": k4, - "p1": p1, - "p2": p2, - "is_fisheye": is_fisheye, - "cx": cx, - "cy": cy, - "w": w, - "h": h, - "aabb_scale": AABB_SCALE, - "frames": [], - } + if len(cameras) == 1: + camera = cameras[camera_id] + out = { + "camera_angle_x": camera["angle_x"], + "camera_angle_y": camera["angle_y"], + "fl_x": camera["fl_x"], + "fl_y": camera["fl_y"], + "k1": camera["k1"], + "k2": camera["k2"], + "k3": camera["k3"], + "k4": camera["k4"], + "p1": camera["p1"], + "p2": camera["p2"], + "is_fisheye": camera["is_fisheye"], + "cx": camera["cx"], + "cy": camera["cy"], + "w": camera["w"], + "h": camera["h"], + "aabb_scale": AABB_SCALE, + "frames": [], + } + else: + out = { + "frames": [], + "aabb_scale": AABB_SCALE + } up = np.zeros(3) for line in f: @@ -333,6 +348,23 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays up += c2w[0:3,1] frame = {"file_path":name,"sharpness":b,"transform_matrix": c2w} + if len(cameras) != 1: + camera_id = int(elems[8]) + frame["camera_angle_x"] = cameras[camera_id]["angle_x"] + frame["camera_angle_y"] = cameras[camera_id]["angle_y"] + frame["fl_x"] = cameras[camera_id]["fl_x"] + frame["fl_y"] = cameras[camera_id]["fl_y"] + frame["k1"] = cameras[camera_id]["k1"] + frame["k2"] = cameras[camera_id]["k2"] + frame["k3"] = cameras[camera_id]["k3"] + frame["k4"] = cameras[camera_id]["k4"] + frame["p1"] = cameras[camera_id]["p1"] + frame["p2"] = cameras[camera_id]["p2"] + frame["is_fisheye"] = cameras[camera_id]["is_fisheye"] + frame["cx"] = cameras[camera_id]["cx"] + frame["cy"] = cameras[camera_id]["cy"] + frame["w"] = cameras[camera_id]["w"] + frame["h"] = cameras[camera_id]["h"] out["frames"].append(frame) nframes = len(out["frames"]) From c7733ff012ced22d48e9cc837e18973677f41b77 Mon Sep 17 00:00:00 2001 From: Floris Erich Date: Mon, 22 May 2023 14:49:48 +0900 Subject: [PATCH 2/5] Slight simplication --- scripts/colmap2nerf.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/scripts/colmap2nerf.py b/scripts/colmap2nerf.py index 0b5d9126f..ab2bd9f66 100755 --- a/scripts/colmap2nerf.py +++ b/scripts/colmap2nerf.py @@ -349,22 +349,22 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays frame = {"file_path":name,"sharpness":b,"transform_matrix": c2w} if len(cameras) != 1: - camera_id = int(elems[8]) - frame["camera_angle_x"] = cameras[camera_id]["angle_x"] - frame["camera_angle_y"] = cameras[camera_id]["angle_y"] - frame["fl_x"] = cameras[camera_id]["fl_x"] - frame["fl_y"] = cameras[camera_id]["fl_y"] - frame["k1"] = cameras[camera_id]["k1"] - frame["k2"] = cameras[camera_id]["k2"] - frame["k3"] = cameras[camera_id]["k3"] - frame["k4"] = cameras[camera_id]["k4"] - frame["p1"] = cameras[camera_id]["p1"] - frame["p2"] = cameras[camera_id]["p2"] - frame["is_fisheye"] = cameras[camera_id]["is_fisheye"] - frame["cx"] = cameras[camera_id]["cx"] - frame["cy"] = cameras[camera_id]["cy"] - frame["w"] = cameras[camera_id]["w"] - frame["h"] = cameras[camera_id]["h"] + camera = camera[int(elems[8])] + frame["camera_angle_x"] = camera["angle_x"] + frame["camera_angle_y"] = camera["angle_y"] + frame["fl_x"] = camera["fl_x"] + frame["fl_y"] = camera["fl_y"] + frame["k1"] = camera["k1"] + frame["k2"] = camera["k2"] + frame["k3"] = camera["k3"] + frame["k4"] = camera["k4"] + frame["p1"] = camera["p1"] + frame["p2"] = camera["p2"] + frame["is_fisheye"] = camera["is_fisheye"] + frame["cx"] = camera["cx"] + frame["cy"] = camera["cy"] + frame["w"] = camera["w"] + frame["h"] = camera["h"] out["frames"].append(frame) nframes = len(out["frames"]) From d0b268c0d22d57b8d1199932ae22bb20759b2f53 Mon Sep 17 00:00:00 2001 From: Floris Erich Date: Mon, 22 May 2023 14:56:50 +0900 Subject: [PATCH 3/5] Typo --- scripts/colmap2nerf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/colmap2nerf.py b/scripts/colmap2nerf.py index ab2bd9f66..0911f5bf4 100755 --- a/scripts/colmap2nerf.py +++ b/scripts/colmap2nerf.py @@ -349,7 +349,7 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays frame = {"file_path":name,"sharpness":b,"transform_matrix": c2w} if len(cameras) != 1: - camera = camera[int(elems[8])] + camera = cameras[int(elems[8])] frame["camera_angle_x"] = camera["angle_x"] frame["camera_angle_y"] = camera["angle_y"] frame["fl_x"] = camera["fl_x"] From b91d973494e585a61e56ba12a85111e7407b176b Mon Sep 17 00:00:00 2001 From: Floris Erich Date: Mon, 5 Jun 2023 16:07:08 +0900 Subject: [PATCH 4/5] Code style changes --- scripts/colmap2nerf.py | 145 ++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 80 deletions(-) diff --git a/scripts/colmap2nerf.py b/scripts/colmap2nerf.py index 0911f5bf4..a7c95fc67 100755 --- a/scripts/colmap2nerf.py +++ b/scripts/colmap2nerf.py @@ -37,7 +37,7 @@ def parse_args(): parser.add_argument("--colmap_camera_params", default="", help="Intrinsic parameters, depending on the chosen model. Format: fx,fy,cx,cy,dist") parser.add_argument("--images", default="images", help="Input path to the images.") parser.add_argument("--text", default="colmap_text", help="Input path to the colmap text files (set automatically if --run_colmap is used).") - parser.add_argument("--aabb_scale", default=32, choices=["1", "2", "4", "8", "16", "32", "64", "128"], help="Large scene scale factor. 1=scene fits in unit cube; power of 2 up to 128") + parser.add_argument("--aabb_scale", default=64, choices=["1", "2", "4", "8", "16", "32", "64", "128"], help="Large scene scale factor. 1=scene fits in unit cube; power of 2 up to 128") parser.add_argument("--skip_early", default=0, help="Skip this many images from the start.") parser.add_argument("--keep_colmap_coords", action="store_true", help="Keep transforms.json in COLMAP's original frame of reference (this will avoid reorienting and repositioning the scene for preview and rendering).") parser.add_argument("--out", default="transforms.json", help="Output path.") @@ -204,7 +204,7 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays print(f"outputting to {OUT_PATH}...") cameras = {} with open(os.path.join(TEXT_FOLDER,"cameras.txt"), "r") as f: - angle_x = math.pi / 2 + camera_angle_x = math.pi / 2 for line in f: # 1 SIMPLE_RADIAL 2048 1536 1580.46 1024 768 0.0045691 # 1 OPENCV 3840 2160 3178.27 3182.09 1920 1080 0.159668 -0.231286 -0.00123982 0.00272224 @@ -214,70 +214,70 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays els = line.split(" ") camera = {} camera_id = int(els[0]) - camera['w'] = float(els[2]) - camera['h'] = float(els[3]) - camera['fl_x'] = float(els[4]) - camera['fl_y'] = float(els[4]) - camera['k1'] = 0 - camera['k2'] = 0 - camera['k3'] = 0 - camera['k4'] = 0 - camera['p1'] = 0 - camera['p2'] = 0 - camera['cx'] = camera['w'] / 2 - camera['cy'] = camera['h'] / 2 - camera['is_fisheye'] = False + camera["w"] = float(els[2]) + camera["h"] = float(els[3]) + camera["fl_x"] = float(els[4]) + camera["fl_y"] = float(els[4]) + camera["k1"] = 0 + camera["k2"] = 0 + camera["k3"] = 0 + camera["k4"] = 0 + camera["p1"] = 0 + camera["p2"] = 0 + camera["cx"] = camera["w"] / 2 + camera["cy"] = camera["h"] / 2 + camera["is_fisheye"] = False if els[1] == "SIMPLE_PINHOLE": - camera['cx'] = float(els[5]) - camera['cy'] = float(els[6]) + camera["cx"] = float(els[5]) + camera["cy"] = float(els[6]) elif els[1] == "PINHOLE": - camera['fl_y'] = float(els[5]) - camera['cx'] = float(els[6]) - camera['cy'] = float(els[7]) + camera["fl_y"] = float(els[5]) + camera["cx"] = float(els[6]) + camera["cy"] = float(els[7]) elif els[1] == "SIMPLE_RADIAL": - camera['cx'] = float(els[5]) - camera['cy'] = float(els[6]) - camera['k1'] = float(els[7]) + camera["cx"] = float(els[5]) + camera["cy"] = float(els[6]) + camera["k1"] = float(els[7]) elif els[1] == "RADIAL": - camera['cx'] = float(els[5]) - camera['cy'] = float(els[6]) - camera['k1'] = float(els[7]) - camera['k2'] = float(els[8]) + camera["cx"] = float(els[5]) + camera["cy"] = float(els[6]) + camera["k1"] = float(els[7]) + camera["k2"] = float(els[8]) elif els[1] == "OPENCV": - camera['fl_y'] = float(els[5]) - camera['cx'] = float(els[6]) - camera['cy'] = float(els[7]) - camera['k1'] = float(els[8]) - camera['k2'] = float(els[9]) - camera['p1'] = float(els[10]) - camera['p2'] = float(els[11]) + camera["fl_y"] = float(els[5]) + camera["cx"] = float(els[6]) + camera["cy"] = float(els[7]) + camera["k1"] = float(els[8]) + camera["k2"] = float(els[9]) + camera["p1"] = float(els[10]) + camera["p2"] = float(els[11]) elif els[1] == "SIMPLE_RADIAL_FISHEYE": - camera['is_fisheye'] = True - camera['cx'] = float(els[5]) - camera['cy'] = float(els[6]) - camera['k1'] = float(els[7]) + camera["is_fisheye"] = True + camera["cx"] = float(els[5]) + camera["cy"] = float(els[6]) + camera["k1"] = float(els[7]) elif els[1] == "RADIAL_FISHEYE": - camera['is_fisheye'] = True - camera['cx'] = float(els[5]) - camera['cy'] = float(els[6]) - camera['k1'] = float(els[7]) - camera['k2'] = float(els[8]) + camera["is_fisheye"] = True + camera["cx"] = float(els[5]) + camera["cy"] = float(els[6]) + camera["k1"] = float(els[7]) + camera["k2"] = float(els[8]) elif els[1] == "OPENCV_FISHEYE": - camera['is_fisheye'] = True - camera['fl_y'] = float(els[5]) - camera['cx'] = float(els[6]) - camera['cy'] = float(els[7]) - camera['k1'] = float(els[8]) - camera['k2'] = float(els[9]) - camera['k3'] = float(els[10]) - camera['k4'] = float(els[11]) + camera["is_fisheye"] = True + camera["fl_y"] = float(els[5]) + camera["cx"] = float(els[6]) + camera["cy"] = float(els[7]) + camera["k1"] = float(els[8]) + camera["k2"] = float(els[9]) + camera["k3"] = float(els[10]) + camera["k4"] = float(els[11]) else: print("Unknown camera model ", els[1]) # fl = 0.5 * w / tan(0.5 * angle_x); - camera['angle_x'] = math.atan(camera['w'] / (camera['fl_x'] * 2)) * 2 - camera['angle_y'] = math.atan(camera['h'] / (camera['fl_y'] * 2)) * 2 - camera['fovx'] = camera['angle_x'] * 180 / math.pi - camera['fovy'] = camera['angle_y'] * 180 / math.pi + camera["camera_angle_x"] = math.atan(camera["w"] / (camera["fl_x"] * 2)) * 2 + camera["camera_angle_y"] = math.atan(camera["h"] / (camera["fl_y"] * 2)) * 2 + camera["fovx"] = camera["camera_angle_x"] * 180 / math.pi + camera["fovy"] = camera["camera_angle_y"] * 180 / math.pi print(f"camera {camera_id}:\n\tres={camera['w'],camera['h']}\n\tcenter={camera['cx'],camera['cy']}\n\tfocal={camera['fl_x'],camera['fl_y']}\n\tfov={camera['fovx'],camera['fovy']}\n\tk={camera['k1'],camera['k2']} p={camera['p1'],camera['p2']} ") cameras[camera_id] = camera @@ -292,8 +292,8 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays if len(cameras) == 1: camera = cameras[camera_id] out = { - "camera_angle_x": camera["angle_x"], - "camera_angle_y": camera["angle_y"], + "camera_angle_x": camera["camera_angle_x"], + "camera_angle_y": camera["camera_angle_y"], "fl_x": camera["fl_x"], "fl_y": camera["fl_y"], "k1": camera["k1"], @@ -349,22 +349,7 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays frame = {"file_path":name,"sharpness":b,"transform_matrix": c2w} if len(cameras) != 1: - camera = cameras[int(elems[8])] - frame["camera_angle_x"] = camera["angle_x"] - frame["camera_angle_y"] = camera["angle_y"] - frame["fl_x"] = camera["fl_x"] - frame["fl_y"] = camera["fl_y"] - frame["k1"] = camera["k1"] - frame["k2"] = camera["k2"] - frame["k3"] = camera["k3"] - frame["k4"] = camera["k4"] - frame["p1"] = camera["p1"] - frame["p2"] = camera["p2"] - frame["is_fisheye"] = camera["is_fisheye"] - frame["cx"] = camera["cx"] - frame["cy"] = camera["cy"] - frame["w"] = camera["w"] - frame["h"] = camera["h"] + frame |= cameras[int(elems[8])] out["frames"].append(frame) nframes = len(out["frames"]) @@ -457,16 +442,16 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml") predictor = DefaultPredictor(cfg) - for frame in out['frames']: - img = cv2.imread(frame['file_path']) + for frame in out["frames"]: + img = cv2.imread(frame["file_path"]) outputs = predictor(img) output_mask = np.zeros((img.shape[0], img.shape[1])) - for i in range(len(outputs['instances'])): - if outputs['instances'][i].pred_classes.cpu().numpy()[0] in mask_ids: - pred_mask = outputs['instances'][i].pred_masks.cpu().numpy()[0] + for i in range(len(outputs["instances"])): + if outputs["instances"][i].pred_classes.cpu().numpy()[0] in mask_ids: + pred_mask = outputs["instances"][i].pred_masks.cpu().numpy()[0] output_mask = np.logical_or(output_mask, pred_mask) - rgb_path = Path(frame['file_path']) - mask_name = str(rgb_path.parents[0] / Path('dynamic_mask_' + rgb_path.name.replace('.jpg', '.png'))) + rgb_path = Path(frame["file_path"]) + mask_name = str(rgb_path.parents[0] / Path("dynamic_mask_" + rgb_path.name.replace(".jpg", ".png"))) cv2.imwrite(mask_name, (output_mask*255).astype(np.uint8)) From eb143986d279aa4883ead3990276bd63771a748d Mon Sep 17 00:00:00 2001 From: Floris Erich Date: Tue, 6 Jun 2023 07:52:48 +0900 Subject: [PATCH 5/5] Undid accidently change to aabb_scale, replaced spaces with tabs, update() instead of |- --- scripts/colmap2nerf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/colmap2nerf.py b/scripts/colmap2nerf.py index a7c95fc67..613ac9f0d 100755 --- a/scripts/colmap2nerf.py +++ b/scripts/colmap2nerf.py @@ -37,7 +37,7 @@ def parse_args(): parser.add_argument("--colmap_camera_params", default="", help="Intrinsic parameters, depending on the chosen model. Format: fx,fy,cx,cy,dist") parser.add_argument("--images", default="images", help="Input path to the images.") parser.add_argument("--text", default="colmap_text", help="Input path to the colmap text files (set automatically if --run_colmap is used).") - parser.add_argument("--aabb_scale", default=64, choices=["1", "2", "4", "8", "16", "32", "64", "128"], help="Large scene scale factor. 1=scene fits in unit cube; power of 2 up to 128") + parser.add_argument("--aabb_scale", default=32, choices=["1", "2", "4", "8", "16", "32", "64", "128"], help="Large scene scale factor. 1=scene fits in unit cube; power of 2 up to 128") parser.add_argument("--skip_early", default=0, help="Skip this many images from the start.") parser.add_argument("--keep_colmap_coords", action="store_true", help="Keep transforms.json in COLMAP's original frame of reference (this will avoid reorienting and repositioning the scene for preview and rendering).") parser.add_argument("--out", default="transforms.json", help="Output path.") @@ -349,7 +349,7 @@ def closest_point_2_lines(oa, da, ob, db): # returns point closest to both rays frame = {"file_path":name,"sharpness":b,"transform_matrix": c2w} if len(cameras) != 1: - frame |= cameras[int(elems[8])] + frame.update(cameras[int(elems[8])]) out["frames"].append(frame) nframes = len(out["frames"])