1111
1212# Built-in/Generic Imports
1313import struct
14+ import pathlib as path
1415
1516# Libs
1617import numpy as np
17- import pathlib as path
1818
1919# Own
2020from colmap_wrapper .colmap .camera import (CAMERA_MODEL_IDS , Camera , ImageInformation , Point3D )
@@ -33,32 +33,6 @@ def read_next_bytes(fid, num_bytes, format_char_sequence, endian_character="<"):
3333 return struct .unpack (endian_character + format_char_sequence , data )
3434
3535
36- def write_cameras_binary (a ):
37- """
38- void Reconstruction::WriteCamerasBinary(const std::string& path) const {
39- std::ofstream file(path, std::ios::trunc | std::ios::binary);
40- CHECK(file.is_open()) << path;
41-
42- WriteBinaryLittleEndian<uint64_t>(&file, cameras_.size());
43-
44- for (const auto& camera : cameras_) {
45- WriteBinaryLittleEndian<camera_t>(&file, camera.first);
46- WriteBinaryLittleEndian<int>(&file, camera.second.ModelId());
47- WriteBinaryLittleEndian<uint64_t>(&file, camera.second.Width());
48- WriteBinaryLittleEndian<uint64_t>(&file, camera.second.Height());
49- for (const double param : camera.second.Params()) {
50- WriteBinaryLittleEndian<double>(&file, param);
51- }
52- }
53- }
54-
55- @param a:
56- @return:
57- """
58- pass
59- return
60-
61-
6236def read_cameras_binary (path_to_model_file ):
6337 """
6438 Original C++ Code can be found here: https://github.com/colmap/colmap/blob/dev/src/base/reconstruction.cc
@@ -69,7 +43,7 @@ def read_cameras_binary(path_to_model_file):
6943 with open (path_to_model_file , "rb" ) as fid :
7044 # First 8 bits contain information about the quantity of different camera models
7145 num_cameras = read_next_bytes (fid , 8 , "Q" )[0 ]
72- for _ in range (num_cameras ): # camera_line_index
46+ for _ in range (num_cameras ): # camera_line_index
7347 # Afterwards the 64 bits contain information about a specific camera
7448 camera_properties = read_next_bytes (fid , num_bytes = 24 , format_char_sequence = "iiQQ" )
7549 camera_id = camera_properties [0 ]
@@ -100,7 +74,7 @@ def read_images_binary(path_to_model_file):
10074 with open (path_to_model_file , "rb" ) as fid :
10175 # First 8 bits contain information about the quantity of different registrated camera models
10276 num_reg_images = read_next_bytes (fid , 8 , "Q" )[0 ]
103- for _ in range (num_reg_images ): # image_index
77+ for _ in range (num_reg_images ): # image_index
10478 # Image properties: (image_id, qvec, tvec, camera_id)
10579 binary_image_properties = read_next_bytes (
10680 fid , num_bytes = 64 , format_char_sequence = "idddddddi" )
@@ -138,13 +112,13 @@ def read_images_binary(path_to_model_file):
138112 pt3did_to_kpidx [ptid ] = kpidx
139113
140114 images [image_id ] = ImageInformation (image_id = image_id ,
141- qvec = qvec ,
142- tvec = tvec ,
143- camera_id = camera_id ,
144- image_name = image_name ,
145- xys = xys ,
146- point3D_ids = point3D_ids ,
147- point3DiD_to_kpidx = pt3did_to_kpidx )
115+ qvec = qvec ,
116+ tvec = tvec ,
117+ camera_id = camera_id ,
118+ image_name = image_name ,
119+ xys = xys ,
120+ point3D_ids = point3D_ids ,
121+ point3DiD_to_kpidx = pt3did_to_kpidx )
148122 return images
149123
150124
@@ -183,13 +157,13 @@ def read_images_text(path):
183157 pt3did_to_kpidx [ptid ] = kpidx
184158
185159 images [image_id ] = ImageInformation (image_id = image_id ,
186- qvec = qvec ,
187- tvec = tvec ,
188- camera_id = camera_id ,
189- image_name = image_name ,
190- xys = xys ,
191- point3D_ids = point3D_ids ,
192- point3DiD_to_kpidx = pt3did_to_kpidx )
160+ qvec = qvec ,
161+ tvec = tvec ,
162+ camera_id = camera_id ,
163+ image_name = image_name ,
164+ xys = xys ,
165+ point3D_ids = point3D_ids ,
166+ point3DiD_to_kpidx = pt3did_to_kpidx )
193167 return images
194168
195169
@@ -203,7 +177,7 @@ def read_points3d_binary(path_to_model_file):
203177 with open (path_to_model_file , "rb" ) as fid :
204178 # Number of points in sparse model
205179 num_points = read_next_bytes (fid , 8 , "Q" )[0 ]
206- for _ in range (num_points ): # point_line_index
180+ for _ in range (num_points ): # point_line_index
207181 binary_point_line_properties = read_next_bytes (
208182 fid , num_bytes = 43 , format_char_sequence = "QdddBBBd" )
209183 # Point ID
@@ -311,6 +285,7 @@ def read_cameras_text(path, int_id=True):
311285 params = params )
312286 return cameras
313287
288+
314289def read_array (path ):
315290 with open (path , "rb" ) as fid :
316291 width , height , channels = np .genfromtxt (fid , delimiter = "&" , max_rows = 1 ,
@@ -326,4 +301,74 @@ def read_array(path):
326301 byte = fid .read (1 )
327302 array = np .fromfile (fid , np .float32 )
328303 array = array .reshape ((width , height , channels ), order = "F" )
329- return np .transpose (array , (1 , 0 , 2 )).squeeze ()
304+ return np .transpose (array , (1 , 0 , 2 )).squeeze ()
305+
306+
307+ def write_cameras_text (cameras , path ):
308+ """
309+ see: src/base/reconstruction.cc
310+ void Reconstruction::WriteCamerasText(const std::string& path)
311+ void Reconstruction::ReadCamerasText(const std::string& path)
312+ """
313+ HEADER = "# Camera list with one line of data per camera:\n " + \
314+ "# CAMERA_ID, MODEL, WIDTH, HEIGHT, PARAMS[]\n " + \
315+ "# Number of cameras: {}\n " .format (len (cameras ))
316+ with open (path , "w" ) as fid :
317+ fid .write (HEADER )
318+ for _ , cam in cameras .items ():
319+ to_write = [cam .id , cam .model , cam .width , cam .height , * cam .params ]
320+ line = " " .join ([str (elem ) for elem in to_write ])
321+ fid .write (line + "\n " )
322+
323+
324+ def write_images_text (images , path ):
325+ """
326+ see: src/base/reconstruction.cc
327+ void Reconstruction::ReadImagesText(const std::string& path)
328+ void Reconstruction::WriteImagesText(const std::string& path)
329+ """
330+ if len (images ) == 0 :
331+ mean_observations = 0
332+ else :
333+ mean_observations = sum ((len (img .point3D_ids ) for _ , img in images .items ())) / len (images )
334+ HEADER = "# Image list with two lines of data per image:\n " + \
335+ "# IMAGE_ID, QW, QX, QY, QZ, TX, TY, TZ, CAMERA_ID, NAME\n " + \
336+ "# POINTS2D[] as (X, Y, POINT3D_ID)\n " + \
337+ "# Number of images: {}, mean observations per image: {}\n " .format (len (images ), mean_observations )
338+
339+ with open (path , "w" ) as fid :
340+ fid .write (HEADER )
341+ for _ , img in images .items ():
342+ image_header = [img .id , * img .qvec , * img .tvec , img .camera_id , img .name ]
343+ first_line = " " .join (map (str , image_header ))
344+ fid .write (first_line + "\n " )
345+
346+ points_strings = []
347+ for xy , point3D_id in zip (img .xys , img .point3D_ids ):
348+ points_strings .append (" " .join (map (str , [* xy , point3D_id ])))
349+ fid .write (" " .join (points_strings ) + "\n " )
350+
351+
352+ def write_points3D_text (points3D , path ):
353+ """
354+ see: src/base/reconstruction.cc
355+ void Reconstruction::ReadPoints3DText(const std::string& path)
356+ void Reconstruction::WritePoints3DText(const std::string& path)
357+ """
358+ if len (points3D ) == 0 :
359+ mean_track_length = 0
360+ else :
361+ mean_track_length = sum ((len (pt .image_ids ) for _ , pt in points3D .items ())) / len (points3D )
362+ HEADER = "# 3D point list with one line of data per point:\n " + \
363+ "# POINT3D_ID, X, Y, Z, R, G, B, ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX)\n " + \
364+ "# Number of points: {}, mean track length: {}\n " .format (len (points3D ), mean_track_length )
365+
366+ with open (path , "w" ) as fid :
367+ fid .write (HEADER )
368+ for _ , pt in points3D .items ():
369+ point_header = [pt .id , * pt .xyz , * pt .rgb , pt .error ]
370+ fid .write (" " .join (map (str , point_header )) + " " )
371+ track_strings = []
372+ for image_id , point2D in zip (pt .image_ids , pt .point2D_idxs ):
373+ track_strings .append (" " .join (map (str , [image_id , point2D ])))
374+ fid .write (" " .join (track_strings ) + "\n " )
0 commit comments