@@ -74,7 +74,9 @@ def load_colmap_project_file(self, project_file=None, image_path=None):
7474 pass
7575
7676 if self .image_path is None :
77- logger = logging .getLogger (f"{ self .__class__ .__module__ } .{ self .__class__ .__name__ } " )
77+ logger = logging .getLogger (
78+ f"{ self .__class__ .__module__ } .{ self .__class__ .__name__ } "
79+ )
7880 logger .debug ("Warning: image_path not found for reconstruction" )
7981 elif not self .image_path .endswith ("/" ):
8082 self .image_path += "/"
@@ -123,7 +125,9 @@ def _load_cameras_txt(self, input_file):
123125
124126 data = line .split ()
125127 camera_id = int (data [0 ])
126- self .cameras [camera_id ] = Camera (data [1 ], int (data [2 ]), int (data [3 ]), map (float , data [4 :]))
128+ self .cameras [camera_id ] = Camera (
129+ data [1 ], int (data [2 ]), int (data [3 ]), map (float , data [4 :])
130+ )
127131 self .last_camera_id = max (self .last_camera_id , camera_id )
128132
129133 # ---------------------------------------------------------------------------
@@ -169,7 +173,9 @@ def _load_images_bin(self, input_file):
169173
170174 ids_array = array .array ("Q" )
171175 ids_array .frombytes (points_elements [:, 2 ].tobytes ())
172- image .point3D_ids = np .array (ids_array , dtype = np .uint64 ).reshape ((num_points2D ,))
176+ image .point3D_ids = np .array (ids_array , dtype = np .uint64 ).reshape (
177+ (num_points2D ,)
178+ )
173179
174180 # automatically remove points without an associated 3D point
175181 # mask = (image.point3D_ids != SceneManager.INVALID_POINT3D)
@@ -184,42 +190,29 @@ def _load_images_bin(self, input_file):
184190 def _load_images_txt (self , input_file ):
185191 self .images = OrderedDict ()
186192
187- with open (input_file , "r" ) as f :
188- is_camera_description_line = False
189-
190- for line in iter (lambda : f .readline ().strip (), "" ):
191- if not line or line .startswith ("#" ):
192- continue
193-
194- is_camera_description_line = not is_camera_description_line
195-
196- data = line .split ()
197-
198- if is_camera_description_line :
199- read_quat = np .array (list (map (float , data [1 :5 ])))
200- read_pos = np .array (list (map (float , data [5 :8 ])))
201- image_id = int (data [0 ])
202- image = Image (
203- data [- 1 ],
204- int (data [- 2 ]),
205- Quaternion (read_quat ),
206- read_pos ,
193+ with open (input_file , "r" ) as fid :
194+ while True :
195+ line = fid .readline ()
196+ if not line :
197+ break
198+ line = line .strip ()
199+ if len (line ) > 0 and line [0 ] != "#" :
200+ elems = line .split ()
201+ image_id = int (elems [0 ])
202+ qvec = np .array (list (map (float , elems [1 :5 ])))
203+ tvec = np .array (list (map (float , elems [5 :8 ])))
204+ camera_id = int (elems [8 ])
205+ image_name = elems [9 ]
206+ elems = fid .readline ().split ()
207+ xys = np .column_stack (
208+ [tuple (map (float , elems [0 ::3 ])), tuple (map (float , elems [1 ::3 ]))]
207209 )
208- else :
209- points_2d_x = [float (x ) for x in data [::3 ]]
210- points_2d_y = [float (y ) for y in data [1 ::3 ]]
211- point3d_ids = [np .uint64 (pid ) for pid in data [2 ::3 ]]
212- image .points2D = np .array ([points_2d_x , points_2d_y ]).T
213- image .point3D_ids = np .array (point3d_ids , dtype = np .uint64 )
214-
215- # automatically remove points without an associated 3D point
216- # mask = (image.point3D_ids != SceneManager.INVALID_POINT3D)
217- # image.points2D = image.points2D[mask]
218- # image.point3D_ids = image.point3D_ids[mask]
219-
220- self .images [image_id ] = image
221- self .name_to_image_id [image .name ] = image_id
222-
210+ point3D_ids = np .array (tuple (map (int , elems [2 ::3 ])))
211+ self .images [image_id ] = Image (
212+ image_name , camera_id , Quaternion (qvec ), tvec
213+ )
214+ self .images [image_id ].points2D = xys
215+ self .images [image_id ].point3D_ids = point3D_ids
223216 self .last_image_id = max (self .last_image_id , image_id )
224217
225218 # ---------------------------------------------------------------------------
@@ -261,7 +254,9 @@ def _load_points3D_bin(self, input_file):
261254
262255 data = struct .unpack (f"{ 2 * track_len } I" , f .read (2 * track_len * 4 ))
263256
264- self .point3D_id_to_images [self .point3D_ids [i ]] = np .array (data , dtype = np .uint32 ).reshape (track_len , 2 )
257+ self .point3D_id_to_images [self .point3D_ids [i ]] = np .array (
258+ data , dtype = np .uint32
259+ ).reshape (track_len , 2 )
265260
266261 def _load_points3D_txt (self , input_file ):
267262 self .points3D = []
@@ -328,7 +323,11 @@ def _save_cameras_bin(self, output_file):
328323 camera_struct = struct .Struct ("IiLL" )
329324
330325 for camera_id , camera in sorted (self .cameras .items ()):
331- fid .write (camera_struct .pack (camera_id , camera .camera_type , camera .width , camera .height ))
326+ fid .write (
327+ camera_struct .pack (
328+ camera_id , camera .camera_type , camera .width , camera .height
329+ )
330+ )
332331 # TODO (True): should move this into the Camera class
333332 fid .write (camera .get_params ().tobytes ())
334333
@@ -368,7 +367,9 @@ def _save_images_bin(self, output_file):
368367 fid .write (struct .pack ("I" , image .camera_id ))
369368 fid .write ((image .name + "\0 " ).encode ("utf-8" ))
370369 fid .write (struct .pack ("L" , len (image .points2D )))
371- data = np .rec .fromarrays ((image .points2D [:, 0 ], image .points2D [:, 1 ], image .point3D_ids ))
370+ data = np .rec .fromarrays (
371+ (image .points2D [:, 0 ], image .points2D [:, 1 ], image .point3D_ids )
372+ )
372373 fid .write (data .tobytes ())
373374
374375 def _save_images_txt (self , output_file ):
@@ -386,7 +387,11 @@ def _save_images_txt(self, output_file):
386387 print >> fid , image .camera_id , image .name
387388
388389 data = np .rec .fromarrays (
389- (image .points2D [:, 0 ], image .points2D [:, 1 ], image .point3D_ids .astype (np .int64 ))
390+ (
391+ image .points2D [:, 0 ],
392+ image .points2D [:, 1 ],
393+ image .point3D_ids .astype (np .int64 ),
394+ )
390395 )
391396 if len (data ) > 0 :
392397 np .savetxt (fid , data , "%.2f %.2f %d" , newline = " " )
@@ -411,7 +416,9 @@ def save_points3D(self, output_folder, output_file=None, binary=True):
411416
412417 def _save_points3D_bin (self , output_file ):
413418 num_valid_points3D = sum (
414- 1 for point3D_idx in self .point3D_id_to_point3D_idx .values () if point3D_idx != SceneManager .INVALID_POINT3D
419+ 1
420+ for point3D_idx in self .point3D_id_to_point3D_idx .values ()
421+ if point3D_idx != SceneManager .INVALID_POINT3D
415422 )
416423
417424 iter_point3D_id_to_point3D_idx = self .point3D_id_to_point3D_idx .items ()
@@ -432,7 +439,9 @@ def _save_points3D_bin(self, output_file):
432439
433440 def _save_points3D_txt (self , output_file ):
434441 num_valid_points3D = sum (
435- 1 for point3D_idx in self .point3D_id_to_point3D_idx .values () if point3D_idx != SceneManager .INVALID_POINT3D
442+ 1
443+ for point3D_idx in self .point3D_id_to_point3D_idx .values ()
444+ if point3D_idx != SceneManager .INVALID_POINT3D
436445 )
437446
438447 array_to_string = lambda arr : " " .join (str (x ) for x in arr )
@@ -454,7 +463,9 @@ def _save_points3D_txt(self, output_file):
454463 print >> fid , array_to_string (self .points3D [point3D_idx ]),
455464 print >> fid , array_to_string (self .point3D_colors [point3D_idx ]),
456465 print >> fid , self .point3D_errors [point3D_idx ],
457- print >> fid , array_to_string (self .point3D_id_to_images [point3D_id ].flat )
466+ print >> fid , array_to_string (
467+ self .point3D_id_to_images [point3D_id ].flat
468+ )
458469
459470 # ---------------------------------------------------------------------------
460471
@@ -475,7 +486,12 @@ def get_points3D(self, image_id, return_points2D=True, return_colors=False):
475486
476487 mask = image .point3D_ids != SceneManager .INVALID_POINT3D
477488
478- point3D_idxs = np .array ([self .point3D_id_to_point3D_idx [point3D_id ] for point3D_id in image .point3D_ids [mask ]])
489+ point3D_idxs = np .array (
490+ [
491+ self .point3D_id_to_point3D_idx [point3D_id ]
492+ for point3D_id in image .point3D_ids [mask ]
493+ ]
494+ )
479495 # detect filtered points
480496 filter_mask = point3D_idxs != SceneManager .INVALID_POINT3D
481497 point3D_idxs = point3D_idxs [filter_mask ]
@@ -492,12 +508,18 @@ def get_points3D(self, image_id, return_points2D=True, return_colors=False):
492508 # ---------------------------------------------------------------------------
493509
494510 def point3D_valid (self , point3D_id ):
495- return self .point3D_id_to_point3D_idx [point3D_id ] != SceneManager .INVALID_POINT3D
511+ return (
512+ self .point3D_id_to_point3D_idx [point3D_id ] != SceneManager .INVALID_POINT3D
513+ )
496514
497515 # ---------------------------------------------------------------------------
498516
499517 def get_filtered_points3D (self , return_colors = False ):
500- point3D_idxs = [idx for idx in self .point3D_id_to_point3D_idx .values () if idx != SceneManager .INVALID_POINT3D ]
518+ point3D_idxs = [
519+ idx
520+ for idx in self .point3D_id_to_point3D_idx .values ()
521+ if idx != SceneManager .INVALID_POINT3D
522+ ]
501523 result = [self .points3D [point3D_idxs , :]]
502524
503525 if return_colors :
@@ -509,10 +531,14 @@ def get_filtered_points3D(self, return_colors=False):
509531
510532 # return 3D points shared by two images
511533 def get_shared_points3D (self , image_id1 , image_id2 ):
512- point3D_ids = set (self .images [image_id1 ].point3D_ids ) & set (self .images [image_id2 ].point3D_ids )
534+ point3D_ids = set (self .images [image_id1 ].point3D_ids ) & set (
535+ self .images [image_id2 ].point3D_ids
536+ )
513537 point3D_ids .discard (SceneManager .INVALID_POINT3D )
514538
515- point3D_idxs = np .array ([self .point3D_id_to_point3D_idx [point3D_id ] for point3D_id in point3D_ids ])
539+ point3D_idxs = np .array (
540+ [self .point3D_id_to_point3D_idx [point3D_id ] for point3D_id in point3D_ids ]
541+ )
516542
517543 return self .points3D [point3D_idxs , :]
518544
@@ -581,17 +607,33 @@ def delete_images(self, image_list):
581607 if point3D_idx == SceneManager .INVALID_POINT3D :
582608 continue
583609
584- mask = np .array ([image_id in keep_set for image_id in self .point3D_id_to_images [point3D_id ][:, 0 ]])
610+ mask = np .array (
611+ [
612+ image_id in keep_set
613+ for image_id in self .point3D_id_to_images [point3D_id ][:, 0 ]
614+ ]
615+ )
585616 if np .any (mask ):
586- self .point3D_id_to_images [point3D_id ] = self .point3D_id_to_images [point3D_id ][mask ]
617+ self .point3D_id_to_images [point3D_id ] = self .point3D_id_to_images [
618+ point3D_id
619+ ][mask ]
587620 else :
588- self .point3D_id_to_point3D_idx [point3D_id ] = SceneManager .INVALID_POINT3D
621+ self .point3D_id_to_point3D_idx [point3D_id ] = (
622+ SceneManager .INVALID_POINT3D
623+ )
589624
590625 # ---------------------------------------------------------------------------
591626
592627 # camera_list: set of cameras whose points we'd like to keep
593628 # min/max triangulation angle: in degrees
594- def filter_points3D (self , min_track_len = 0 , max_error = np .inf , min_tri_angle = 0 , max_tri_angle = 180 , image_set = set ()):
629+ def filter_points3D (
630+ self ,
631+ min_track_len = 0 ,
632+ max_error = np .inf ,
633+ min_tri_angle = 0 ,
634+ max_tri_angle = 180 ,
635+ image_set = set (),
636+ ):
595637
596638 image_set = set (image_set )
597639
@@ -619,12 +661,16 @@ def filter_points3D(self, min_track_len=0, max_error=np.inf, min_tri_angle=0, ma
619661 or image_set
620662 and image_set .isdisjoint (image_ids )
621663 ):
622- self .point3D_id_to_point3D_idx [point3D_id ] = SceneManager .INVALID_POINT3D
664+ self .point3D_id_to_point3D_idx [point3D_id ] = (
665+ SceneManager .INVALID_POINT3D
666+ )
623667
624668 # find dot product between all camera viewing rays
625669 elif check_triangulation_angles :
626670 xyz = self .points3D [point3D_idx , :]
627- tvecs = np .array ([(self .images [image_id ].tvec - xyz ) for image_id in image_ids ])
671+ tvecs = np .array (
672+ [(self .images [image_id ].tvec - xyz ) for image_id in image_ids ]
673+ )
628674 tvecs /= np .linalg .norm (tvecs , axis = - 1 )[:, np .newaxis ]
629675
630676 cos_theta = np .array ([u .dot (v ) for u , v in combinations (tvecs , 2 )])
@@ -633,13 +679,16 @@ def filter_points3D(self, min_track_len=0, max_error=np.inf, min_tri_angle=0, ma
633679 # if maximum viewing angle is too small or too large,
634680 # don't add this point
635681 if np .min (cos_theta ) > max_tri_prod or np .max (cos_theta ) < min_tri_prod :
636- self .point3D_id_to_point3D_idx [point3D_id ] = SceneManager .INVALID_POINT3D
682+ self .point3D_id_to_point3D_idx [point3D_id ] = (
683+ SceneManager .INVALID_POINT3D
684+ )
637685
638686 # apply the filters to the image point3D_ids
639687 for image in self .images .itervalues ():
640688 mask = np .array (
641689 [
642- self .point3D_id_to_point3D_idx .get (point3D_id , 0 ) == SceneManager .INVALID_POINT3D
690+ self .point3D_id_to_point3D_idx .get (point3D_id , 0 )
691+ == SceneManager .INVALID_POINT3D
643692 for point3D_id in image .point3D_ids
644693 ]
645694 )
0 commit comments