Skip to content

Commit 8bd466b

Browse files
authored
Add files via upload
1 parent 65e594e commit 8bd466b

File tree

5 files changed

+244
-4
lines changed

5 files changed

+244
-4
lines changed

script/check_corr.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@
1313
os.chdir(os.path.dirname(__file__))
1414

1515
def str2bool(s:str) -> bool:
16-
if s.lower == "false":
16+
if s.isdigit():
17+
if float(s) > 0:
18+
return True
19+
else:
20+
return False
21+
if s.lower() == "false":
1722
return False
1823
else:
1924
return True

script/demo_IBA.py

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import pykitti
2+
import numpy as np
3+
import argparse
4+
import os
5+
import cv2
6+
import open3d as o3d
7+
import copy
8+
# import matplotlib
9+
# matplotlib.use('agg')
10+
from matplotlib import pyplot as plt
11+
from tools import *
12+
from scipy.spatial.ckdtree import cKDTree
13+
from fps_v1 import FPS
14+
15+
16+
os.chdir(os.path.dirname(__file__))
17+
18+
def str2bool(s:str) -> bool:
19+
if s.isdigit():
20+
if float(s) > 0:
21+
return True
22+
else:
23+
return False
24+
if s.lower() == "false":
25+
return False
26+
else:
27+
return True
28+
29+
def options():
30+
parser = argparse.ArgumentParser()
31+
kitti_parser = parser.add_argument_group()
32+
kitti_parser.add_argument("--base_dir",type=str,default="/data/DATA/data_odometry/dataset/")
33+
kitti_parser.add_argument("--seq",type=int,default=0,choices=[i for i in range(11)])
34+
kitti_parser.add_argument("--index_i",type=int,default=0)
35+
kitti_parser.add_argument("--index_j",type=int,default=1)
36+
37+
io_parser = parser.add_argument_group()
38+
io_parser.add_argument("--Twc_file",type=str,default="../Twc.txt")
39+
io_parser.add_argument("--Twl_file",type=str,default="../Twl.txt")
40+
41+
arg_parser = parser.add_argument_group()
42+
arg_parser.add_argument("--tsl_perturb",type=float,nargs=3,default=[0.1,-0.15,0.1])
43+
arg_parser.add_argument("--rot_perturb",type=float,nargs=3,default=[0,0,0])
44+
arg_parser.add_argument("--fps_sample",type=int,default=-1)
45+
arg_parser.add_argument("--pixel_corr_dist",type=float,default=3)
46+
arg_parser.add_argument("--view",type=str2bool,default=True)
47+
args = parser.parse_args()
48+
args.seq_id = "%02d"%args.seq
49+
return args
50+
51+
52+
def drawcorrpoints(img1,img2,pts1,pts2):
53+
img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)
54+
img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR)
55+
for pt1,pt2 in zip(pts1,pts2):
56+
color = tuple(np.random.randint(0,255,3).tolist())
57+
img1 = cv2.circle(img1,tuple(pt1),5,color,-1)
58+
img2 = cv2.circle(img2,tuple(pt2),5,color,-1)
59+
return img1,img2
60+
61+
def draw3corrpoints(img1,img2,pts11,pts12,pts2):
62+
img1 = cv2.cvtColor(img1,cv2.COLOR_GRAY2BGR)
63+
img2 = cv2.cvtColor(img2,cv2.COLOR_GRAY2BGR)
64+
for pt11,pt12,pt2 in zip(pts11,pts12,pts2):
65+
color = tuple(np.random.randint(0,255,3).tolist())
66+
img1 = cv2.circle(img1,tuple(pt11),5,color,1)
67+
img1 = cv2.circle(img1,tuple(pt12),5,color,1)
68+
img2 = cv2.circle(img2,tuple(pt2),5,color,1)
69+
return img1,img2
70+
71+
def compute_orb_desc(img:np.ndarray):
72+
"""compute orb descriptors
73+
74+
Args:
75+
img (np.ndarray): HxW
76+
77+
Returns:
78+
_type_: keypoints, descriptors
79+
"""
80+
if len(img.shape) == 3:
81+
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
82+
orb = cv2.ORB_create(nfeatures=1000)
83+
kp, desc = orb.detectAndCompute(img, None)
84+
return kp, desc
85+
86+
if __name__ == "__main__":
87+
args = options()
88+
augT = toMat(args.rot_perturb, args.tsl_perturb)
89+
print("augT:\n{}".format(augT))
90+
dataStruct = pykitti.odometry(args.base_dir, args.seq_id)
91+
calibStruct = dataStruct.calib
92+
extran = calibStruct.T_cam0_velo # [4,4]
93+
print("GT TCL:\n{}".format(extran))
94+
print("GT TCL Rvec:{}\ntvec:{}".format(*toVec(extran)))
95+
aug_extran = augT @ extran
96+
intran = calibStruct.K_cam0
97+
src_pcd_arr = dataStruct.get_velo(args.index_i)[:,:3] # [N, 3]
98+
tgt_pcd_arr = dataStruct.get_velo(args.index_j)[:,:3] # [N, 3]
99+
src_img = np.array(dataStruct.get_cam0(args.index_i)) # [H, W, 3]
100+
tgt_img = np.array(dataStruct.get_cam0(args.index_j)) # [H, W, 3]
101+
src_pose = dataStruct.poses[args.index_i]
102+
tgt_pose = dataStruct.poses[args.index_j]
103+
camera_motion:np.ndarray = tgt_pose@ inv_pose(src_pose)
104+
orb = cv2.ORB_create(nfeatures=1000)
105+
src_kp, src_desc = compute_orb_desc(src_img)
106+
tgt_kp, tgt_desc = compute_orb_desc(tgt_img)
107+
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
108+
matches = bf.match(src_desc,tgt_desc)
109+
src_matched_pts = []
110+
tgt_matched_pts = []
111+
for match in matches:
112+
src_matched_pts.append(src_kp[match.queryIdx].pt)
113+
tgt_matched_pts.append(tgt_kp[match.trainIdx].pt)
114+
115+
src_matched_pts = np.array(src_matched_pts) # [N, 2]
116+
tgt_matched_pts = np.array(tgt_matched_pts)
117+
118+
src_pcd_camcoord = nptran(src_pcd_arr, extran)
119+
proj_src_pcd, src_rev = npproj(src_pcd_camcoord, np.eye(4), intran, src_img.shape)
120+
src_2d_kdtree = cKDTree(proj_src_pcd, leafsize=30)
121+
src_dist, src_pcd_query = src_2d_kdtree.query(src_matched_pts, 1, eps=1e-4, p=1)
122+
123+
src_dist_rev = src_dist < args.pixel_corr_dist
124+
src_matched_pts = src_matched_pts[src_dist_rev]
125+
tgt_matched_pts = tgt_matched_pts[src_dist_rev]
126+
src_pcd_query = src_pcd_query[src_dist_rev]
127+
128+
src2tgt_pcd_arr = nptran(src_pcd_camcoord[src_rev][src_pcd_query], camera_motion)
129+
src2tgt_proj_pcd, src2tgt_proj_rev = npproj(src2tgt_pcd_arr, np.eye(4), intran, tgt_img.shape)
130+
src_matched_pts = src_matched_pts[src2tgt_proj_rev]
131+
tgt_matched_pts = tgt_matched_pts[src2tgt_proj_rev]
132+
tgt_matched_pts, src2tgt_proj_pcd, src_matched_pts = list(map(lambda arr: arr.astype(np.int32),[tgt_matched_pts, src2tgt_proj_pcd, src_matched_pts]))
133+
if(args.fps_sample > 0):
134+
fps = FPS(tgt_matched_pts, n_samples=args.fps_sample)
135+
_, fps_idx = fps.fit(True)
136+
else:
137+
fps_idx = np.arange(tgt_matched_pts.shape[0])
138+
draw_src_img, draw_tgt_img = drawcorrpoints(src_img, tgt_img, src_matched_pts[fps_idx], tgt_matched_pts[fps_idx])
139+
# draw_tgt_img, draw_src_img = draw3corrpoints(tgt_img, src_img, tgt_matched_pts[fps_idx], src2tgt_proj_pcd[fps_idx], src_matched_pts[fps_idx])
140+
plt.subplot(2,1,1)
141+
plt.imshow(draw_src_img)
142+
plt.subplot(2,1,2)
143+
plt.imshow(draw_tgt_img)
144+
plt.show()
145+

script/demo_epipolar.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@
1313
os.chdir(os.path.dirname(__file__))
1414

1515
def str2bool(s:str) -> bool:
16-
if s.lower == "false":
16+
if s.isdigit():
17+
if float(s) > 0:
18+
return True
19+
else:
20+
return False
21+
if s.lower() == "false":
1722
return False
1823
else:
1924
return True
20-
2125
def options():
2226
parser = argparse.ArgumentParser()
2327
kitti_parser = parser.add_argument_group()

script/demo_project.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import pykitti
2+
import numpy as np
3+
import argparse
4+
import os
5+
import cv2
6+
import open3d as o3d
7+
import copy
8+
# import matplotlib
9+
# matplotlib.use('agg')
10+
from matplotlib import pyplot as plt
11+
from tools import *
12+
13+
14+
os.chdir(os.path.dirname(__file__))
15+
16+
def str2bool(s:str) -> bool:
17+
if s.isdigit():
18+
if float(s) > 0:
19+
return True
20+
else:
21+
return False
22+
if s.lower() == "false":
23+
return False
24+
else:
25+
return True
26+
def options():
27+
parser = argparse.ArgumentParser()
28+
kitti_parser = parser.add_argument_group()
29+
kitti_parser.add_argument("--base_dir",type=str,default="/data/DATA/data_odometry/dataset/")
30+
kitti_parser.add_argument("--seq",type=int,default=0,choices=[i for i in range(11)])
31+
kitti_parser.add_argument("--index_i",type=int,default=0)
32+
kitti_parser.add_argument("--index_j",type=int,default=1)
33+
34+
io_parser = parser.add_argument_group()
35+
io_parser.add_argument("--index_file",type=str,default="../KITTI-00/FrameId.yml")
36+
io_parser.add_argument("--Twc_file",type=str,default="../KITTI-00/Twc.txt")
37+
io_parser.add_argument("--Twl_file",type=str,default="../KITTI-00/floam_isam_00.txt")
38+
io_parser.add_argument("--TCL_file",type=str,default="../KITTI-00/icp_calib_00.txt")
39+
40+
arg_parser = parser.add_argument_group()
41+
arg_parser.add_argument("--view",type=str2bool,default=True)
42+
args = parser.parse_args()
43+
args.seq_id = "%02d"%args.seq
44+
return args
45+
46+
if __name__ == "__main__":
47+
args = options()
48+
dataStruct = pykitti.odometry(args.base_dir, args.seq_id)
49+
calibStruct = dataStruct.calib
50+
extran_raw = np.loadtxt(args.TCL_file)
51+
extran = np.eye(4)
52+
extran[:3,:] = extran_raw[:12].reshape(3,4)
53+
scale = extran_raw[-1]
54+
src_pcd_arr = dataStruct.get_velo(args.index_i)[:,:3] # [N, 3]
55+
tgt_pcd_arr = dataStruct.get_velo(args.index_j)[:,:3] # [N, 3]
56+
src_img = np.array(dataStruct.get_cam2(args.index_i)) # [H, W, 3]
57+
tgt_img = np.array(dataStruct.get_cam2(args.index_j)) # [H, W, 3]
58+
# src_img = np.flip(src_img,axis=2) # BGR to RGB
59+
# tgt_img = np.flip(tgt_img,axis=2)
60+
img_shape = src_img.shape[:2]
61+
intran = calibStruct.K_cam0
62+
proj_src, src_rev_idx = npproj(src_pcd_arr, extran, intran, img_shape)
63+
range_src = nptran(src_pcd_arr, extran)[:,-1][src_rev_idx]
64+
proj_tgt, tgt_rev_idx = npproj(src_pcd_arr, extran, intran, img_shape)
65+
range_tgt = nptran(tgt_pcd_arr, extran)[:,-1][tgt_rev_idx]
66+
tgt_in_src = np.isin(tgt_rev_idx,src_rev_idx)
67+
src_in_tgt = np.isin(src_rev_idx,tgt_rev_idx)
68+
proj_src = proj_src[tgt_in_src]
69+
range_src = range_src[tgt_in_src]
70+
proj_tgt = proj_tgt[src_in_tgt]
71+
range_tgt = range_tgt[src_in_tgt]
72+
plt.subplot(2,1,1)
73+
plt.imshow(src_img)
74+
plt.scatter(proj_src[:,0],proj_src[:,1],c=range_src,cmap='rainbow_r',alpha=0.4,s=1)
75+
plt.subplot(2,1,2)
76+
plt.imshow(tgt_img)
77+
plt.scatter(proj_tgt[:,0],proj_tgt[:,1],c=range_tgt,cmap='rainbow_r',alpha=0.4,s=1)
78+
plt.show()
79+
80+
81+

script/epipolar_jacobian.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515

1616

1717
def str2bool(s:str) -> bool:
18-
if s.lower == "false":
18+
if s.isdigit():
19+
if float(s) > 0:
20+
return True
21+
else:
22+
return False
23+
if s.lower() == "false":
1924
return False
2025
else:
2126
return True

0 commit comments

Comments
 (0)