66import open3d as o3d
77from pathlib import Path
88from scipy .spatial .transform import Rotation as R
9+ from tools .save_cali import load_ex , save_ex , load_in , save_in
10+ from tools .visualizer import visualizer as vis
911
1012def pc_relative (pc0 ,pc1 ):
1113 #get relative translation and rotation from pc0 to pc1
@@ -25,28 +27,14 @@ def pc_relative(pc0,pc1):
2527 print ("Transformation Matrix:\n " , reg_result .transformation )
2628 return (reg_result .transformation )
2729
28- def r_from_vector (direction ):
29- direction = np .array (direction )
30- direction = direction / np .linalg .norm (direction )
31- target = np .array ([0 , 1 , 0 ])
32- rotation_axis = np .cross (direction , target )
33- if np .allclose (rotation_axis , 0 ):
34- return R .from_quat ([0 , 0 , 0 , 1 ])
35- else :
36- angle = np .arccos (np .clip (np .dot (direction , target ), - 1.0 , 1.0 ))
37- rotation_axis = rotation_axis / np .linalg .norm (rotation_axis )
38- r = R .from_rotvec (angle * rotation_axis )
39- return r
40-
41- #%%
42- # img_dir = root + "/data/calib1/img"
43- img_dir = root + "/data/test"
30+ #%%
31+ img_dir = root + "/data/calib1/img"
32+ # img_dir = root + "/data/test"
4433output_dir = root + '/GEMstack/offboard/calibration/output'
45-
4634output_path = Path (output_dir )
4735output_path .mkdir (exist_ok = True , parents = True )
4836
49- # 1. Feature extraction
37+ # 1. Feature extraction. google 'sift' to know what it does.
5038extract_options = pycolmap .SiftExtractionOptions ()
5139extract_options .num_threads = 2
5240pycolmap .extract_features (
@@ -57,9 +45,10 @@ def r_from_vector(direction):
5745 # device=pycolmap._core.Device.cuda
5846)
5947
60- # 2. Feature matching
48+ # 2. Feature matching. match_sequential tries matching only on pairs close in filename ordering
6149match_options = pycolmap .SequentialMatchingOptions ()
62- match_options .overlap = 3
50+ match_options .overlap = 3 # how many subsequent images should be tried matching.
51+ # 3 is too small actually. do larger if you figured out pycolmap+cuda
6352pycolmap .match_sequential (
6453 database_path = output_path / "database.db" ,
6554 matching_options = match_options
@@ -71,7 +60,7 @@ def r_from_vector(direction):
7160# matching_options=match_options
7261# )
7362
74- # 3. Sparse reconstruction
63+ # 3. Sparse reconstruction. ba_refine = 0 so it don't mess with the intrinsics we got in feature extraction stage.
7564mapper_options = pycolmap .IncrementalPipelineOptions ()
7665mapper_options .ba_refine_focal_length = 0
7766mapper_options .ba_refine_principal_point = 0
@@ -84,22 +73,26 @@ def r_from_vector(direction):
8473)
8574
8675#%%
87- dense_dir = output_path
88- dense_dir .mkdir (exist_ok = True )
76+ #%%
77+ # this part tries 3d reconstruction with stereo depth given the images registered in the previous part.
78+ # but patch_match_stereo needs cuda and compiling pycolmap from source so haven't managed to run it.
8979
90- pycolmap .patch_math_stereo (
91- input_path = output_path ,
92- output_path = dense_dir ,
93- output_type = "TXT" ,
94- )
80+ # dense_dir = output_path
81+ # dense_dir.mkdir(exist_ok=True)
9582
96- pycolmap .stereo_fusion (
97- output_path = dense_dir ,
98- workspace_path = dense_dir ,
99- workspace_format = "COLMAP" ,
100- # max_image_size=2000,
101- # gpu_index="0",
102- )
83+ # pycolmap.patch_match_stereo(
84+ # input_path=output_path,
85+ # output_path=dense_dir,
86+ # output_type="TXT",
87+ # )
88+
89+ # pycolmap.stereo_fusion(
90+ # output_path=dense_dir,
91+ # workspace_path=dense_dir,
92+ # workspace_format="COLMAP",
93+ # max_image_size=2000,
94+ # gpu_index="0",
95+ # )
10396
10497# 4. Depth Map Fusion (Global Registration)
10598# fused_pc = pycolmap.dense_fusion(
@@ -110,34 +103,52 @@ def r_from_vector(direction):
110103# )
111104
112105#%%
106+ #%%
107+ # get correspondence between image registrations and filenames,
108+ # and find image142 is from oak
113109[(id ,reconstructions [0 ].image (id ).name ) for id in reconstructions [0 ].reg_image_ids ()]
114110
115111#%%
112+ #make a copy because I was in jupyter lab trying to test different stuff with it
116113rec = reconstructions [0 ].__copy__ ()
114+
117115#%%
116+ # anchor the coordination system to image #142
117+ # because I found #142 is the first registered images from the front camera
118118trans = rec .image (142 ).cam_from_world
119119rec .transform (pycolmap .Sim3d (rotation = trans .rotation ,translation = trans .translation ))
120- rec .transform (pycolmap .Sim3d (rotation = np .array (R .from_euler ('yx' ,(np .pi / 2 ,- np .pi / 2 )).as_quat ())))
121- rec .image (142 ).viewing_direction ()
120+ print (rec .image (142 ).viewing_direction ()) # shoud be a trivial direction
121+
122+ #%%
123+ #%%
124+ pc = np .array ([p .xyz for p in rec .points3D .values ()])
125+ ##################################################################################
126+ #so far we have got pointcloud reconstructed from camera images
127+ #################################################################################
128+ # tranform to vehicle coordination just for visualization
129+ camera_ex = load_ex (root + "/GEMstack/knowledge/calibration/gem_e4_oak.yaml" ,mode = 'matrix' )
130+ pc = np .pad (pc ,((0 ,0 ),(0 ,1 )),constant_values = 1 ) @ camera_ex .T [:,:3 ]
131+
122132#%%
123133def load_scene (path ):
124134 sc = np .load (path )['arr_0' ]
125135 sc = sc [~ np .all (sc == 0 , axis = 1 )] # remove (0,0,0)'s
126136 return sc
127137
128138#%%
129- # import re
130- # ind = re.match("oak(\d+)\.png$",base).group(1)
131- ind = 1
132- sc = load_scene (f"/mnt/GEMstack/data/calib1/pc/ouster{ ind } .npz" )
133-
139+ #%%
140+ # get lidar pointcloud
141+ from save_cali import load_ex
142+ sc = load_scene (root + f"/data/calib1/pc/ouster1.npz" )
143+ lidar_ex = load_ex (root + "/GEMstack/knowledge/calibration/gem_e4_ouster.yaml" ,mode = 'matrix' )
144+ sc = np .pad (sc ,((0 ,0 ),(0 ,1 )),constant_values = 1 ) @ lidar_ex .T [:,:3 ]
134145
135146#%%
136147pc = np .array ([p .xyz for p in rec .points3D .values ()])
137148#%%
138149from visualizer import visualizer as vis
139- import os
140- os .environ ['DISPLAY' ] = ':0'
150+ # import os
151+ # os.environ['DISPLAY'] = ':0'
141152#%%
142153v = vis ()
143154v .add_pc (pc ,color = 'red' )
0 commit comments