This commit is contained in:
otthorn 2021-06-10 18:17:59 +02:00
parent 48f59c2557
commit adf7d25d37

View file

@ -7,108 +7,104 @@ from normalize_cam_dict import normalize_cam_dict
# Note: configure the colmap_bin to the colmap executable on your machine # Note: configure the colmap_bin to the colmap executable on your machine
######################################################################### #########################################################################
def bash_run(cmd): def bash_run(cmd):
colmap_bin = "/usr/local/bin/colmap" colmap_bin = "/usr/local/bin/colmap"
cmd = colmap_bin + ' ' + cmd cmd = colmap_bin + " " + cmd
print('\nRunning cmd: ', cmd) print("\nRunning cmd: ", cmd)
subprocess.check_call(['/bin/bash', '-c', cmd]) subprocess.check_call(["/bin/bash", "-c", cmd])
gpu_index = '-1' gpu_index = "-1"
def run_sift_matching(img_dir, db_file, remove_exist=False): def run_sift_matching(img_dir, db_file, remove_exist=False):
print('Running sift matching...') print("Running sift matching...")
if remove_exist and os.path.exists(db_file): if remove_exist and os.path.exists(db_file):
os.remove(db_file) # otherwise colmap will skip sift matching os.remove(db_file) # otherwise colmap will skip sift matching
# feature extraction # feature extraction
# if there's no attached display, cannot use feature extractor with GPU # if there's no attached display, cannot use feature extractor with GPU
cmd = ' feature_extractor --database_path {} \ cmd = f" feature_extractor --database_path {db_file}"\
--image_path {} \ f" --image_path {img_dir}"\
--ImageReader.single_camera 1 \ f" --ImageReader.single_camera 1"\
--ImageReader.camera_model SIMPLE_RADIAL \ f" --ImageReader.camera_model SIMPLE_RADIAL"\
--SiftExtraction.max_image_size 5000 \ f" --SiftExtraction.max_image_size 5000 "\
--SiftExtraction.estimate_affine_shape 0 \ f" --SiftExtraction.estimate_affine_shape 0"\
--SiftExtraction.domain_size_pooling 1 \ f" --SiftExtraction.domain_size_pooling 1"\
--SiftExtraction.use_gpu 1 \ f" --SiftExtraction.use_gpu 1"\
--SiftExtraction.max_num_features 16384 \ f" --SiftExtraction.max_num_features 16384"\
--SiftExtraction.gpu_index {}'.format(db_file, img_dir, gpu_index) f" --SiftExtraction.gpu_index {gpu_index}"
bash_run(cmd) bash_run(cmd)
# feature matching # feature matching
cmd = ' exhaustive_matcher --database_path {} \ cmd = f" exhaustive_matcher --database_path {db_file}"\
--SiftMatching.guided_matching 1 \ f" --SiftMatching.guided_matching 1"\
--SiftMatching.use_gpu 1 \ f" --SiftMatching.use_gpu 1"\
--SiftMatching.max_num_matches 65536 \ f" --SiftMatching.max_num_matches 65536"\
--SiftMatching.max_error 3 \ f" --SiftMatching.max_error 3"\
--SiftMatching.gpu_index {}'.format(db_file, gpu_index) f" --SiftMatching.gpu_index {gpu_index}"
bash_run(cmd) bash_run(cmd)
def run_sfm(img_dir, db_file, out_dir): def run_sfm(img_dir, db_file, out_dir):
print('Running SfM...') print("Running SfM...")
cmd = ' mapper \
--database_path {} \
--image_path {} \
--output_path {} \
--Mapper.tri_min_angle 3.0 \
--Mapper.filter_min_tri_angle 3.0'.format(db_file, img_dir, out_dir)
cmd = f" mapper"\
f" --database_path {db_file}"\
f" --image_path {img_dir}"\
f" --output_path {out_dir}"\
f" --Mapper.tri_min_angle 3.0"\
f" --Mapper.filter_min_tri_angle 3.0"
bash_run(cmd) bash_run(cmd)
def prepare_mvs(img_dir, sparse_dir, mvs_dir): def prepare_mvs(img_dir, sparse_dir, mvs_dir):
print('Preparing for MVS...') print("Preparing for MVS...")
cmd = ' image_undistorter \
--image_path {} \
--input_path {} \
--output_path {} \
--output_type COLMAP \
--max_image_size 2000'.format(img_dir, sparse_dir, mvs_dir)
cmd = f" image_undistorter"\
f" --image_path {img_dir}"\
f" --input_path {sparse_dir}"\
f" --output_path {mvs_dir}"\
f" --output_type COLMAP"\
f" --max_image_size 2000"
bash_run(cmd) bash_run(cmd)
def run_photometric_mvs(mvs_dir, window_radius): def run_photometric_mvs(mvs_dir, window_radius):
print('Running photometric MVS...') print("Running photometric MVS...")
cmd = ' patch_match_stereo --workspace_path {} \
--PatchMatchStereo.window_radius {} \
--PatchMatchStereo.min_triangulation_angle 3.0 \
--PatchMatchStereo.filter 1 \
--PatchMatchStereo.geom_consistency 1 \
--PatchMatchStereo.gpu_index={} \
--PatchMatchStereo.num_samples 15 \
--PatchMatchStereo.num_iterations 12'.format(mvs_dir,
window_radius, gpu_index)
cmd = f" patch_match_stereo --workspace_path {mvs_dir}"\
f" --PatchMatchStereo.window_radius {window_radius}"\
f" --PatchMatchStereo.min_triangulation_angle 3.0"\
f" --PatchMatchStereo.filter 1"\
f" --PatchMatchStereo.geom_consistency 1"\
f" --PatchMatchStereo.gpu_index={gpu_index}"\
f" --PatchMatchStereo.num_samples 15"\
f" --PatchMatchStereo.num_iterations 12"
bash_run(cmd) bash_run(cmd)
def run_fuse(mvs_dir, out_ply): def run_fuse(mvs_dir, out_ply):
print('Running depth fusion...')
cmd = ' stereo_fusion --workspace_path {} \ print("Running depth fusion...")
--output_path {} \
--input_type geometric'.format(mvs_dir, out_ply)
cmd = f"stereo_fusion"\
f" --workspace_path {mvs_dir}"\
f" --output_path {out_ply}"\
f" --input_type geometric"
bash_run(cmd) bash_run(cmd)
def run_possion_mesher(in_ply, out_ply, trim): def run_possion_mesher(in_ply, out_ply, trim):
print('Running possion mesher...') print("Running possion mesher...")
cmd = ' poisson_mesher \
--input_path {} \
--output_path {} \
--PoissonMeshing.trim {}'.format(in_ply, out_ply, trim)
cmd = f" poisson_mesher"\
f" --input_path {in_ply}"\
f" --output_path {out_ply}"\
f" --PoissonMeshing.trim {trim}"
bash_run(cmd) bash_run(cmd)
@ -116,53 +112,57 @@ def main(img_dir, out_dir, run_mvs=False):
os.makedirs(out_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True)
#### run sfm #### run sfm
sfm_dir = os.path.join(out_dir, 'sfm') sfm_dir = os.path.join(out_dir, "sfm")
os.makedirs(sfm_dir, exist_ok=True) os.makedirs(sfm_dir, exist_ok=True)
img_dir_link = os.path.join(sfm_dir, 'images') img_dir_link = os.path.join(sfm_dir, "images")
if os.path.exists(img_dir_link): if os.path.exists(img_dir_link):
os.remove(img_dir_link) os.remove(img_dir_link)
os.symlink(img_dir, img_dir_link) os.symlink(img_dir, img_dir_link)
db_file = os.path.join(sfm_dir, 'database.db') db_file = os.path.join(sfm_dir, "database.db")
run_sift_matching(img_dir, db_file, remove_exist=False) run_sift_matching(img_dir, db_file, remove_exist=False)
sparse_dir = os.path.join(sfm_dir, 'sparse') sparse_dir = os.path.join(sfm_dir, "sparse/0")
os.makedirs(sparse_dir, exist_ok=True) os.makedirs(sparse_dir, exist_ok=True)
run_sfm(img_dir, db_file, sparse_dir) run_sfm(img_dir, db_file, sparse_dir)
# undistort images # undistort images
mvs_dir = os.path.join(out_dir, 'mvs') mvs_dir = os.path.join(out_dir, "mvs")
os.makedirs(mvs_dir, exist_ok=True) os.makedirs(mvs_dir, exist_ok=True)
prepare_mvs(img_dir, sparse_dir, mvs_dir) prepare_mvs(img_dir, sparse_dir, mvs_dir)
# extract camera parameters and undistorted images # extract camera parameters and undistorted images
os.makedirs(os.path.join(out_dir, 'posed_images'), exist_ok=True) os.makedirs(os.path.join(out_dir, "posed_images"), exist_ok=True)
extract_all_to_dir(os.path.join(mvs_dir, 'sparse'), os.path.join(out_dir, 'posed_images')) extract_all_to_dir(
undistorted_img_dir = os.path.join(mvs_dir, 'images') os.path.join(mvs_dir, "sparse"), os.path.join(out_dir, "posed_images")
posed_img_dir_link = os.path.join(out_dir, 'posed_images/images') )
undistorted_img_dir = os.path.join(mvs_dir, "images")
posed_img_dir_link = os.path.join(out_dir, "posed_images/images")
if os.path.exists(posed_img_dir_link): if os.path.exists(posed_img_dir_link):
os.remove(posed_img_dir_link) os.remove(posed_img_dir_link)
os.symlink(undistorted_img_dir, posed_img_dir_link) os.symlink(undistorted_img_dir, posed_img_dir_link)
# normalize average camera center to origin, and put all cameras inside the unit sphere # normalize average camera center to origin, and put all cameras inside the unit sphere
normalize_cam_dict(os.path.join(out_dir, 'posed_images/kai_cameras.json'), normalize_cam_dict(
os.path.join(out_dir, 'posed_images/kai_cameras_normalized.json')) os.path.join(out_dir, "posed_images/kai_cameras.json"),
os.path.join(out_dir, "posed_images/kai_cameras_normalized.json"),
)
if run_mvs: if run_mvs:
# run mvs # run mvs
run_photometric_mvs(mvs_dir, window_radius=7) run_photometric_mvs(mvs_dir, window_radius=7)
out_ply = os.path.join(out_dir, 'mvs/fused.ply') out_ply = os.path.join(out_dir, "mvs/fused.ply")
run_fuse(mvs_dir, out_ply) run_fuse(mvs_dir, out_ply)
out_mesh_ply = os.path.join(out_dir, 'mvs/meshed_trim_3.ply') out_mesh_ply = os.path.join(out_dir, "mvs/meshed_trim_3.ply")
run_possion_mesher(out_ply, out_mesh_ply, trim=3) run_possion_mesher(out_ply, out_mesh_ply, trim=3)
if __name__ == '__main__': if __name__ == "__main__":
### note: this script is intended for the case where all images are taken by the same camera, i.e., intrinisics are shared. ### note: this script is intended for the case where all images are taken by the same camera, i.e., intrinisics are shared.
img_dir = '' # CHANGE THIS TWO PATHS
out_dir = '' img_dir = "~/code/my_awesome_dataset/"
out_dir = "~/home/code/nerfplusplus/outdir/"
run_mvs = False run_mvs = False
main(img_dir, out_dir, run_mvs=run_mvs) main(img_dir, out_dir, run_mvs=run_mvs)