Spaces:
Sleeping
Sleeping
import pickle | |
import numpy as np | |
import cv2 | |
from skimage.io import imread | |
def save_pickle(data, pkl_path): | |
# os.system('mkdir -p {}'.format(os.path.dirname(pkl_path))) | |
with open(pkl_path, 'wb') as f: | |
pickle.dump(data, f) | |
def read_pickle(pkl_path): | |
with open(pkl_path, 'rb') as f: | |
return pickle.load(f) | |
def draw_epipolar_line(F, img0, img1, pt0, color): | |
h1,w1=img1.shape[:2] | |
hpt = np.asarray([pt0[0], pt0[1], 1], dtype=np.float32)[:, None] | |
l = F @ hpt | |
l = l[:, 0] | |
a, b, c = l[0], l[1], l[2] | |
pt1 = np.asarray([0, -c / b]).astype(np.int32) | |
pt2 = np.asarray([w1, (-a * w1 - c) / b]).astype(np.int32) | |
img0 = cv2.circle(img0, tuple(pt0.astype(np.int32)), 5, color, 2) | |
img1 = cv2.line(img1, tuple(pt1), tuple(pt2), color, 2) | |
return img0, img1 | |
def draw_epipolar_lines(F, img0, img1,num=20): | |
img0,img1=img0.copy(),img1.copy() | |
h0, w0, _ = img0.shape | |
h1, w1, _ = img1.shape | |
for k in range(num): | |
color = np.random.randint(0, 255, [3], dtype=np.int32) | |
color = [int(c) for c in color] | |
pt = np.random.uniform(0, 1, 2) | |
pt[0] *= w0 | |
pt[1] *= h0 | |
pt = pt.astype(np.int32) | |
img0, img1 = draw_epipolar_line(F, img0, img1, pt, color) | |
return img0, img1 | |
def compute_F(K1, K2, Rt0, Rt1=None): | |
if Rt1 is None: | |
R, t = Rt0[:,:3], Rt0[:,3:] | |
else: | |
Rt = compute_dR_dt(Rt0,Rt1) | |
R, t = Rt[:,:3], Rt[:,3:] | |
A = K1 @ R.T @ t # [3,1] | |
C = np.asarray([[0,-A[2,0],A[1,0]], | |
[A[2,0],0,-A[0,0]], | |
[-A[1,0],A[0,0],0]]) | |
F = (np.linalg.inv(K2)).T @ R @ K1.T @ C | |
return F | |
def compute_dR_dt(Rt0, Rt1): | |
R0, t0 = Rt0[:,:3], Rt0[:,3:] | |
R1, t1 = Rt1[:,:3], Rt1[:,3:] | |
dR = np.dot(R1, R0.T) | |
dt = t1 - np.dot(dR, t0) | |
return np.concatenate([dR, dt], -1) | |
def concat_images(img0,img1,vert=False): | |
if not vert: | |
h0,h1=img0.shape[0],img1.shape[0], | |
if h0<h1: img0=cv2.copyMakeBorder(img0,0,h1-h0,0,0,borderType=cv2.BORDER_CONSTANT,value=0) | |
if h1<h0: img1=cv2.copyMakeBorder(img1,0,h0-h1,0,0,borderType=cv2.BORDER_CONSTANT,value=0) | |
img = np.concatenate([img0, img1], axis=1) | |
else: | |
w0,w1=img0.shape[1],img1.shape[1] | |
if w0<w1: img0=cv2.copyMakeBorder(img0,0,0,0,w1-w0,borderType=cv2.BORDER_CONSTANT,value=0) | |
if w1<w0: img1=cv2.copyMakeBorder(img1,0,0,0,w0-w1,borderType=cv2.BORDER_CONSTANT,value=0) | |
img = np.concatenate([img0, img1], axis=0) | |
return img | |
def concat_images_list(*args,vert=False): | |
if len(args)==1: return args[0] | |
img_out=args[0] | |
for img in args[1:]: | |
img_out=concat_images(img_out,img,vert) | |
return img_out | |
def pose_inverse(pose): | |
R = pose[:,:3].T | |
t = - R @ pose[:,3:] | |
return np.concatenate([R,t],-1) | |
def project_points(pts,RT,K): | |
pts = np.matmul(pts,RT[:,:3].transpose())+RT[:,3:].transpose() | |
pts = np.matmul(pts,K.transpose()) | |
dpt = pts[:,2] | |
mask0 = (np.abs(dpt)<1e-4) & (np.abs(dpt)>0) | |
if np.sum(mask0)>0: dpt[mask0]=1e-4 | |
mask1=(np.abs(dpt) > -1e-4) & (np.abs(dpt) < 0) | |
if np.sum(mask1)>0: dpt[mask1]=-1e-4 | |
pts2d = pts[:,:2]/dpt[:,None] | |
return pts2d, dpt | |
def draw_keypoints(img, kps, colors=None, radius=2): | |
out_img=img.copy() | |
for pi, pt in enumerate(kps): | |
pt = np.round(pt).astype(np.int32) | |
if colors is not None: | |
color=[int(c) for c in colors[pi]] | |
cv2.circle(out_img, tuple(pt), radius, color, -1) | |
else: | |
cv2.circle(out_img, tuple(pt), radius, (0,255,0), -1) | |
return out_img | |
def output_points(fn,pts,colors=None): | |
with open(fn, 'w') as f: | |
for pi, pt in enumerate(pts): | |
f.write(f'{pt[0]:.6f} {pt[1]:.6f} {pt[2]:.6f} ') | |
if colors is not None: | |
f.write(f'{int(colors[pi,0])} {int(colors[pi,1])} {int(colors[pi,2])}') | |
f.write('\n') | |
DEPTH_MAX, DEPTH_MIN = 2.4, 0.6 | |
DEPTH_VALID_MAX, DEPTH_VALID_MIN = 2.37, 0.63 | |
def read_depth_objaverse(depth_fn): | |
depth = imread(depth_fn) | |
depth = depth.astype(np.float32) / 65535 * (DEPTH_MAX-DEPTH_MIN) + DEPTH_MIN | |
mask = (depth > DEPTH_VALID_MIN) & (depth < DEPTH_VALID_MAX) | |
return depth, mask | |
def mask_depth_to_pts(mask,depth,K,rgb=None): | |
hs,ws=np.nonzero(mask) | |
depth=depth[hs,ws] | |
pts=np.asarray([ws,hs,depth],np.float32).transpose() | |
pts[:,:2]*=pts[:,2:] | |
if rgb is not None: | |
return np.dot(pts, np.linalg.inv(K).transpose()), rgb[hs,ws] | |
else: | |
return np.dot(pts, np.linalg.inv(K).transpose()) | |
def transform_points_pose(pts, pose): | |
R, t = pose[:, :3], pose[:, 3] | |
if len(pts.shape)==1: | |
return (R @ pts[:,None] + t[:,None])[:,0] | |
return pts @ R.T + t[None,:] | |
def pose_apply(pose,pts): | |
return transform_points_pose(pts, pose) | |
def downsample_gaussian_blur(img, ratio): | |
sigma = (1 / ratio) / 3 | |
# ksize=np.ceil(2*sigma) | |
ksize = int(np.ceil(((sigma - 0.8) / 0.3 + 1) * 2 + 1)) | |
ksize = ksize + 1 if ksize % 2 == 0 else ksize | |
img = cv2.GaussianBlur(img, (ksize, ksize), sigma, borderType=cv2.BORDER_REFLECT101) | |
return img |