1+ import pykitti
2+ import numpy as np
3+ import argparse
4+ import os
5+ import cv2
6+ # import matplotlib
7+ # matplotlib.use('agg')
8+ from matplotlib import pyplot as plt
9+ from cv_tools import *
10+ from scipy .spatial import cKDTree
11+ from GP_reg import GPR
12+ from joblib import delayed , Parallel
13+ import yaml
14+
15+ os .chdir (os .path .dirname (__file__ ))
16+
17+ def print_params (title :str = "" , params :dict = {}):
18+ print (title ,end = "" )
19+ for key , value in params .items ():
20+ print ("{}: {}" .format (key , value ),end = " " )
21+ print ()
22+
23+ def str2bool (s :str ) -> bool :
24+ if s .isdigit ():
25+ if float (s ) > 0 :
26+ return True
27+ else :
28+ return False
29+ if s .lower () == "false" :
30+ return False
31+ else :
32+ return True
33+
34+ def options ():
35+ parser = argparse .ArgumentParser ()
36+ kitti_parser = parser .add_argument_group ()
37+ kitti_parser .add_argument ("--base_dir" ,type = str ,default = "/data/DATA/data_odometry/dataset/" )
38+ kitti_parser .add_argument ("--seq" ,type = int ,default = 4 ,choices = [i for i in range (11 )])
39+
40+ io_parser = parser .add_argument_group ()
41+ io_parser .add_argument ("--KeyFrameDir" ,type = str ,default = "../KITTI-04/KeyFrames" )
42+ io_parser .add_argument ("--FrameIdFile" ,type = str ,default = "../KITTI-04/FrameId.yml" )
43+ io_parser .add_argument ("--MapFile" ,type = str ,default = "../KITTI-04/Map.yml" )
44+ io_parser .add_argument ("--KeyFrameIdKey" ,type = str ,default = "mnId" )
45+ io_parser .add_argument ("--FrameIdKey" ,type = str ,default = "mnFrameId" )
46+ io_parser .add_argument ("--KeyPointsKey" ,type = str ,default = "mvKeysUn" )
47+ io_parser .add_argument ("--MapPointKey" ,type = str ,default = "mvpMapPointsId" )
48+ io_parser .add_argument ("--CorrKey" ,type = str ,default = "mvpCorrKeyPointsId" )
49+ io_parser .add_argument ("--index_i" ,type = int ,default = 0 )
50+ io_parser .add_argument ("--index_j" ,type = int ,default = 1 )
51+ io_parser .add_argument ("--debug_log" ,type = str ,default = "" )
52+ io_parser .add_argument ("--extrinsic_file1" ,type = str ,default = "../KITTI-04/calib_res/he_rb_calib_04.txt" )
53+ io_parser .add_argument ("--extrinsic_file2" ,type = str ,default = "../KITTI-04/calib_res/iba_global_pl_04.txt" )
54+ io_parser .add_argument ("--Twc_file" ,type = str ,default = "../Twc.txt" )
55+ io_parser .add_argument ("--Twl_file" ,type = str ,default = "../Twl.txt" )
56+ io_parser .add_argument ("--save" ,type = str ,default = "../fig/04/cba_combine.png" )
57+ arg_parser = parser .add_argument_group ()
58+ arg_parser .add_argument ("--fps_sample" ,type = int ,default = 50 )
59+ arg_parser .add_argument ("--pixel_corr_dist" ,type = float ,default = 1.5 )
60+ arg_parser .add_argument ("--max_2d_nn" ,type = int , default = 10 )
61+ args = parser .parse_args ()
62+ args .seq_id = "%02d" % args .seq
63+ return args
64+
65+
66+ def get_fs_info (fs , keypt_nodename , mappt_nodename , corrkpt_nodename ):
67+ kptnode = fs .getNode (keypt_nodename )
68+ keypts = [[int (kptnode .at (i ).at (0 ).real ()), int (kptnode .at (i ).at (1 ).real ())] for i in range (kptnode .size ())]
69+ mapptnode = fs .getNode (mappt_nodename )
70+ mappt_indices = [int (mapptnode .at (i ).real ()) for i in range (mapptnode .size ())]
71+ corrkpt_node = fs .getNode (corrkpt_nodename )
72+ corr_keypt_indices = [int (corrkpt_node .at (i ).real ()) for i in range (corrkpt_node .size ())]
73+ return np .array (keypts ), mappt_indices , corr_keypt_indices
74+
75+ def getMatchedId (src_mappt_indices :list , tgt_mappt_indices :list , src_corrkpt_indices :list , tgt_corrkpt_indices :list ):
76+ src_matched_indices = []
77+ tgt_matched_indices = []
78+ for i in range (len (src_mappt_indices )):
79+ src_mappt_id = src_mappt_indices [i ]
80+ if src_mappt_id in tgt_mappt_indices :
81+ tgt_id = tgt_mappt_indices .index (src_mappt_id )
82+ src_matched_indices .append (src_corrkpt_indices [i ])
83+ tgt_matched_indices .append (tgt_corrkpt_indices [tgt_id ])
84+ return np .array (src_matched_indices ), np .array (tgt_matched_indices ) # Keypoint Indices
85+
86+
87+ if __name__ == "__main__" :
88+ np .random .seed (10 ) # color consistency
89+ args = options ()
90+ dataStruct = pykitti .odometry (args .base_dir , args .seq_id )
91+ calibStruct = dataStruct .calib
92+ extran1 = np .eye (4 )
93+ extran_raw1 = np .loadtxt (args .extrinsic_file1 )[:12 ]
94+ extran1 [:3 ,:] = extran_raw1 .reshape (3 ,4 )
95+ extran2 = np .eye (4 )
96+ extran_raw2 = np .loadtxt (args .extrinsic_file2 )[:12 ]
97+ extran2 [:3 ,:] = extran_raw2 .reshape (3 ,4 )
98+ KeyFramesFiles = list (sorted (os .listdir (args .KeyFrameDir )))
99+ KeyFramesFiles = [file for file in KeyFramesFiles if os .path .splitext (file )[1 ] == '.yml' ]
100+ FrameIdCfg = yaml .load (open (args .FrameIdFile ,'r' ), yaml .SafeLoader )
101+ mnIds :list = FrameIdCfg [args .KeyFrameIdKey ]
102+ mFrameIds :list = FrameIdCfg [args .FrameIdKey ]
103+ assert (args .index_i in mnIds and args .index_j in mnIds ), "{} and {} must be in mnIds" .format (args .index_i , args .index_j )
104+ src_kffile_index = mnIds .index (args .index_i )
105+ tgt_kffile_index = mnIds .index (args .index_j )
106+ src_file_index = mFrameIds [src_kffile_index ]
107+ tgt_file_index = mFrameIds [tgt_kffile_index ]
108+ src_KeyFrameFile = os .path .join (args .KeyFrameDir , KeyFramesFiles [src_kffile_index ])
109+ tgt_KeyFrameFile = os .path .join (args .KeyFrameDir , KeyFramesFiles [tgt_kffile_index ])
110+ src_fs = cv2 .FileStorage (src_KeyFrameFile , cv2 .FILE_STORAGE_READ )
111+ tgt_fs = cv2 .FileStorage (tgt_KeyFrameFile , cv2 .FILE_STORAGE_READ )
112+ src_keypts , src_mappt_indices , src_corrkpt_indices = get_fs_info (src_fs , args .KeyPointsKey , args .MapPointKey , args .CorrKey )
113+ tgt_keypts , tgt_mappt_indices , tgt_corrkpt_indices = get_fs_info (tgt_fs , args .KeyPointsKey , args .MapPointKey , args .CorrKey )
114+ intran = calibStruct .K_cam0
115+ src_matched_pts_idx , tgt_matched_pts_idx = getMatchedId (src_mappt_indices , tgt_mappt_indices , src_corrkpt_indices , tgt_corrkpt_indices )
116+ src_pcd_arr = dataStruct .get_velo (src_file_index )[:,:3 ] # [N, 3]
117+ tgt_pcd_arr = dataStruct .get_velo (tgt_file_index )[:,:3 ] # [N, 3]
118+ src_img = np .array (dataStruct .get_cam0 (src_file_index )) # [H, W, 3]
119+ tgt_img = np .array (dataStruct .get_cam0 (tgt_file_index )) # [H, W, 3]
120+ img_shape = src_img .shape [:2 ]
121+ src_pose = dataStruct .poses [src_file_index ]
122+ tgt_pose = dataStruct .poses [tgt_file_index ]
123+ camera_motion :np .ndarray = inv_pose (tgt_pose ) @ src_pose # Tc2w * Twc1
124+ src_matched_pts_raw = src_keypts [src_matched_pts_idx ]
125+ tgt_matched_pts_raw = tgt_keypts [tgt_matched_pts_idx ]
126+ print ("Keypoint-Keypoint Matched:{}" .format (len (src_matched_pts_raw )))
127+ src_pcd_camcoord = nptran (src_pcd_arr , extran1 )
128+ proj_src_pcd , src_rev = npproj (src_pcd_camcoord , np .eye (4 ), intran , src_img .shape )
129+ src_pcd_camcoord = src_pcd_camcoord [src_rev ]
130+ tgt_pcd_camcoord = nptran (src_pcd_camcoord , camera_motion )
131+ proj_tgt_pcd , tgt_rev = npproj (tgt_pcd_camcoord , np .eye (4 ), intran , tgt_img .shape )
132+ tgt_pcd_camcoord = tgt_pcd_camcoord [tgt_rev ]
133+ src_2d_kdtree = cKDTree (proj_src_pcd , leafsize = 10 )
134+ src_dist , src_pcd_query = src_2d_kdtree .query (src_matched_pts_raw , 1 , eps = 1e-4 , p = 2 , workers = - 1 )
135+ src_dist_rev = src_dist <= args .pixel_corr_dist ** 2
136+ src_matched_pts = src_matched_pts_raw [src_dist_rev ]
137+ tgt_matched_pts = tgt_matched_pts_raw [src_dist_rev ]
138+ src_pcd_query = src_pcd_query [src_dist_rev ]
139+ src_pcd_3d_query = np .arange (src_pcd_camcoord .shape [0 ])
140+ src_pcd_3d_query = src_pcd_3d_query [src_pcd_query ]
141+ sp_pts3d = src_pcd_camcoord [src_pcd_3d_query ]
142+ src_proj_pcd , _ = npproj (sp_pts3d , np .eye (4 ), intran , src_img .shape )
143+ tgt_pcd_arr = nptran (sp_pts3d , camera_motion )
144+ tgt_proj_pcd , tgt_proj_rev = npproj (tgt_pcd_arr , np .eye (4 ), intran , tgt_img .shape )
145+ src_matched_pts = src_matched_pts [tgt_proj_rev ]
146+ tgt_matched_pts = tgt_matched_pts [tgt_proj_rev ]
147+ err1 = np .mean (np .sqrt (np .sum ((tgt_matched_pts - tgt_proj_pcd )** 2 ,axis = 1 )))
148+ Nmatch1 = src_matched_pts .shape [0 ]
149+ if args .fps_sample > 0 :
150+ src_matched_pts , src_proj_pcd , fps_indices = fps_sample_corr_pts (src_matched_pts , src_proj_pcd , args .fps_sample , return_idx = True )
151+ tgt_matched_pts = tgt_matched_pts [fps_indices ,:]
152+ tgt_proj_pcd = tgt_proj_pcd [fps_indices ,:]
153+ draw_tgt_img1 , _ = draw4corrpoints (tgt_img , src_img ,
154+ * list (map (lambda arr : arr .astype (np .int32 ),[tgt_matched_pts , tgt_proj_pcd , src_matched_pts , src_proj_pcd ])),
155+ 5 ,8 )
156+
157+ src_pcd_camcoord = nptran (src_pcd_arr , extran2 )
158+ proj_src_pcd , src_rev = npproj (src_pcd_camcoord , np .eye (4 ), intran , src_img .shape )
159+ src_pcd_camcoord = src_pcd_camcoord [src_rev ]
160+ tgt_pcd_camcoord = nptran (src_pcd_camcoord , camera_motion )
161+ proj_tgt_pcd , tgt_rev = npproj (tgt_pcd_camcoord , np .eye (4 ), intran , tgt_img .shape )
162+ tgt_pcd_camcoord = tgt_pcd_camcoord [tgt_rev ]
163+ src_2d_kdtree = cKDTree (proj_src_pcd , leafsize = 10 )
164+ src_dist , src_pcd_query = src_2d_kdtree .query (src_matched_pts_raw , 1 , eps = 1e-4 , p = 2 , workers = - 1 )
165+ src_dist_rev = src_dist <= args .pixel_corr_dist ** 2
166+ src_matched_pts = src_matched_pts_raw [src_dist_rev ]
167+ tgt_matched_pts = tgt_matched_pts_raw [src_dist_rev ]
168+ src_pcd_query = src_pcd_query [src_dist_rev ]
169+ src_pcd_3d_query = np .arange (src_pcd_camcoord .shape [0 ])
170+ src_pcd_3d_query = src_pcd_3d_query [src_pcd_query ]
171+ sp_pts3d = src_pcd_camcoord [src_pcd_3d_query ]
172+ src_proj_pcd , _ = npproj (sp_pts3d , np .eye (4 ), intran , src_img .shape )
173+ tgt_pcd_arr = nptran (sp_pts3d , camera_motion )
174+ tgt_proj_pcd , tgt_proj_rev = npproj (tgt_pcd_arr , np .eye (4 ), intran , tgt_img .shape )
175+ src_matched_pts = src_matched_pts [tgt_proj_rev ]
176+ tgt_matched_pts = tgt_matched_pts [tgt_proj_rev ]
177+ err2 = np .mean (np .sqrt (np .sum ((tgt_matched_pts - tgt_proj_pcd )** 2 ,axis = 1 )))
178+ Nmatch2 = src_matched_pts .shape [0 ]
179+ if args .fps_sample > 0 :
180+ src_matched_pts , src_proj_pcd , fps_indices = fps_sample_corr_pts (src_matched_pts , src_proj_pcd , args .fps_sample , return_idx = True )
181+ tgt_matched_pts = tgt_matched_pts [fps_indices ,:]
182+ tgt_proj_pcd = tgt_proj_pcd [fps_indices ,:]
183+ draw_tgt_img2 , _ = draw4corrpoints (tgt_img , src_img ,
184+ * list (map (lambda arr : arr .astype (np .int32 ),[tgt_matched_pts , tgt_proj_pcd , src_matched_pts , src_proj_pcd ])),
185+ 5 ,8 )
186+
187+ plt .figure (dpi = 200 )
188+ plt .subplot (2 ,1 ,1 )
189+ plt .title ("Frame {} - {} | Matched:{} | Mean Error:{:0.2f}" .format (src_file_index + 1 , tgt_file_index + 1 , Nmatch1 ,err1 ))
190+ plt .imshow (draw_tgt_img1 )
191+ plt .axis ([0 ,img_shape [1 ],img_shape [0 ],0 ])
192+ plt .axis ('off' )
193+ plt .subplot (2 ,1 ,2 )
194+ plt .title ("Frame {} - {} | Matched:{} | Mean Error:{:0.2f}" .format (src_file_index + 1 , tgt_file_index + 1 , Nmatch2 ,err2 ))
195+ plt .imshow (draw_tgt_img2 )
196+ plt .axis ([0 ,img_shape [1 ],img_shape [0 ],0 ])
197+ plt .axis ('off' )
198+ plt .tight_layout (pad = 0.5 ,h_pad = 0 ,w_pad = 0 )
199+ plt .savefig (args .save )
200+
201+
0 commit comments