Spaces:
Runtime error
Runtime error
| import sys | |
| sys.path.append('droid_slam') | |
| from tqdm import tqdm | |
| import numpy as np | |
| import torch | |
| import lietorch | |
| import cv2 | |
| import os | |
| import glob | |
| import time | |
| import argparse | |
| from torch.multiprocessing import Process | |
| from droid import Droid | |
| from pycocotools import mask as masktool | |
| import torch.nn.functional as F | |
| def show_image(image): | |
| image = image.permute(1, 2, 0).cpu().numpy() | |
| cv2.imshow('image', image / 255.0) | |
| cv2.waitKey(1) | |
| def image_stream(imagedir, calib, stride): | |
| """ image generator """ | |
| # calib = np.loadtxt(calib, delimiter=" ") | |
| fx, fy, cx, cy = calib[:4] | |
| K = np.eye(3) | |
| K[0,0] = fx | |
| K[0,2] = cx | |
| K[1,1] = fy | |
| K[1,2] = cy | |
| image_list = sorted(glob.glob(f'{imagedir}/*.jpg')) | |
| image_list = image_list[::stride] | |
| for t, imfile in enumerate(image_list): | |
| image = cv2.imread(imfile) | |
| if len(calib) > 4: | |
| image = cv2.undistort(image, K, calib[4:]) | |
| h0, w0, _ = image.shape | |
| h1 = int(h0 * np.sqrt((384 * 512) / (h0 * w0))) | |
| w1 = int(w0 * np.sqrt((384 * 512) / (h0 * w0))) | |
| image = cv2.resize(image, (w1, h1)) | |
| image = image[:h1-h1%8, :w1-w1%8] | |
| image = torch.as_tensor(image).permute(2, 0, 1) | |
| intrinsics = torch.as_tensor([fx, fy, cx, cy]) | |
| intrinsics[0::2] *= (w1 / w0) | |
| intrinsics[1::2] *= (h1 / h0) | |
| yield t, image[None], intrinsics | |
| def save_reconstruction(droid, reconstruction_path): | |
| from pathlib import Path | |
| import random | |
| import string | |
| t = droid.video.counter.value | |
| tstamps = droid.video.tstamp[:t].cpu().numpy() | |
| images = droid.video.images[:t].cpu().numpy() | |
| disps = droid.video.disps_up[:t].cpu().numpy() | |
| poses = droid.video.poses[:t].cpu().numpy() | |
| intrinsics = droid.video.intrinsics[:t].cpu().numpy() | |
| Path("reconstructions/{}".format(reconstruction_path)).mkdir(parents=True, exist_ok=True) | |
| np.save("reconstructions/{}/tstamps.npy".format(reconstruction_path), tstamps) | |
| np.save("reconstructions/{}/images.npy".format(reconstruction_path), images) | |
| np.save("reconstructions/{}/disps.npy".format(reconstruction_path), disps) | |
| np.save("reconstructions/{}/poses.npy".format(reconstruction_path), poses) | |
| np.save("reconstructions/{}/intrinsics.npy".format(reconstruction_path), intrinsics) | |
| if __name__ == '__main__': | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--imagedir", type=str, help="path to image directory") | |
| parser.add_argument("--calib", type=str, help="path to calibration file") | |
| parser.add_argument("--t0", default=0, type=int, help="starting frame") | |
| parser.add_argument("--stride", default=3, type=int, help="frame stride") | |
| parser.add_argument("--weights", default="droid.pth") | |
| parser.add_argument("--buffer", type=int, default=512) | |
| parser.add_argument("--image_size", default=[240, 320]) | |
| parser.add_argument("--disable_vis", action="store_true") | |
| parser.add_argument("--beta", type=float, default=0.3, help="weight for translation / rotation components of flow") | |
| parser.add_argument("--filter_thresh", type=float, default=2.4, help="how much motion before considering new keyframe") | |
| parser.add_argument("--warmup", type=int, default=8, help="number of warmup frames") | |
| parser.add_argument("--keyframe_thresh", type=float, default=4.0, help="threshold to create a new keyframe") | |
| parser.add_argument("--frontend_thresh", type=float, default=16.0, help="add edges between frames whithin this distance") | |
| parser.add_argument("--frontend_window", type=int, default=25, help="frontend optimization window") | |
| parser.add_argument("--frontend_radius", type=int, default=2, help="force edges between frames within radius") | |
| parser.add_argument("--frontend_nms", type=int, default=1, help="non-maximal supression of edges") | |
| parser.add_argument("--backend_thresh", type=float, default=22.0) | |
| parser.add_argument("--backend_radius", type=int, default=2) | |
| parser.add_argument("--backend_nms", type=int, default=3) | |
| parser.add_argument("--upsample", action="store_true") | |
| parser.add_argument("--reconstruction_path", help="path to saved reconstruction") | |
| args = parser.parse_args() | |
| args.stereo = False | |
| torch.multiprocessing.set_start_method('spawn') | |
| droid = None | |
| # need high resolution depths | |
| if args.reconstruction_path is not None: | |
| args.upsample = True | |
| tstamps = [] | |
| for (t, image, intrinsics) in tqdm(image_stream(args.imagedir, args.calib, args.stride)): | |
| if t < args.t0: | |
| continue | |
| if not args.disable_vis: | |
| show_image(image[0]) | |
| if droid is None: | |
| args.image_size = [image.shape[2], image.shape[3]] | |
| droid = Droid(args) | |
| droid.track(t, image, intrinsics=intrinsics) | |
| if args.reconstruction_path is not None: | |
| save_reconstruction(droid, args.reconstruction_path) | |
| traj_est = droid.terminate(image_stream(args.imagedir, args.calib, args.stride)) | |