功能:
1.用Python实现已知相机位姿的稀疏重建
2.重建过程中裁剪照片大小并重命名
- 重点在于导入影像内参和外参
- 内参从camera.txt读入然后根据裁剪后的影像大小重新计算并保存
- 外参从images.txt读入然后按照官方教程格式保存
def reconstruct_sparse_model_from_known_camera_poses(image_dir: Path,
colmap_dir: Path,
pose_dir: Path,
out_image_dir:Path,
camera_model: CameraModel,
gpu: bool = True,
verbose: bool = False,
matching_method: Literal["vocab_tree", "exhaustive", "sequential"] = "vocab_tree",
colmap_cmd: str = "colmap", ):
#解析cameras.txt文件
cameras = colmap_utils.read_cameras_text(pose_dir / "cameras.txt")
# 解析images.txt文件
images_pose = colmap_utils.read_images_text(pose_dir / "images.txt")
#新建空的point3D文件
new_point3d = open(colmap_dir / "sparse" / "0" / "points3D.txt", "w")
new_point3d.close()
# 计算最小图像尺寸
min_width, min_height = np.inf, np.inf
for cam_id, cam in cameras.items():
min_width = min(min_width, cam.width)
min_height = min(min_height, cam.height)
#裁剪并保存图像
image_paths = sorted([p for p in image_dir.glob("[!.]*")])
images = [Image.open(filename) for filename in image_paths]
resized_images = [image.resize((min_width, min_height)) for image in images]
for idx, image in enumerate(resized_images):
filename = image_paths[idx]
filename = out_image_dir/ f"frame_{idx+1:08d}{filename.suffix}"
image.save(filename)
# 保存裁剪后的相机内参数
camera_output_path = colmap_dir/ "sparse" / "0" / "cameras.txt"
with open(camera_output_path, 'w') as f:
for cam_id, cam in cameras.items():
fx = cam.params[0] * min_width / cam.width
fy = cam.params[1] * min_height / cam.height
cx = cam.params[2] * min_width / cam.width
cy = cam.params[3] * min_height / cam.height
params = [fx, fy, cx, cy] + list(cam.params[4:])
f.write('%d %s %s %s %s\n' % (cam_id, cam.model,min_width,min_height, ' '.join(map(str, params))))
# 保存相机位姿参数
images_output_path = colmap_dir/ "sparse" / "0" / "images.txt"
with open(images_output_path, 'w') as f:
for img_id, img in sorted(images_pose.items()):
qw, qx, qy, qz = img.qvec
tx, ty, tz = img.tvec
camera_id = img.camera_id
name = f"frame_{img_id:08d}{Path(img.name).suffix}"
f.write(
'%d %.6f %.6f %.6f %.6f %.6f %.6f %.6f %d %s\n\n' % (img_id, qw, qx, qy, qz, tx, ty, tz, camera_id, name))
# Feature extraction
feature_extractor_cmd = [
f"{colmap_cmd} feature_extractor",
f"--database_path {colmap_dir / 'database.db'}",
f"--image_path {out_image_dir}",
f"--ImageReader.camera_model {camera_model.value}",
f"--SiftExtraction.use_gpu {int(gpu)}",
]
feature_extractor_cmd = " ".join(feature_extractor_cmd)
with status(msg="[bold yellow]Running COLMAP feature extractor...", spinner="moon", verbose=verbose):
run_command(feature_extractor_cmd, verbose=verbose)
CONSOLE.log("[bold green]:tada: Done extracting COLMAP features.")
# Feature matching
feature_matcher_cmd = [
f"{colmap_cmd} {matching_method}_matcher",
f"--database_path {colmap_dir / 'database.db'}",
f"--SiftMatching.use_gpu {int(gpu)}",
]
if matching_method == "vocab_tree":
vocab_tree_filename = get_vocab_tree()
feature_matcher_cmd.append(f"--VocabTreeMatching.vocab_tree_path {vocab_tree_filename}")
feature_matcher_cmd = " ".join(feature_matcher_cmd)
with status(msg="[bold yellow]Running COLMAP feature matcher...", spinner="runner", verbose=verbose):
run_command(feature_matcher_cmd, verbose=verbose)
CONSOLE.log("[bold green]:tada: Done matching COLMAP features.")
# point triangulator
model_path=colmap_dir/ "sparse" / "0"
point_triangulator_cmd = [
f"{colmap_cmd} point_triangulator",
f"--database_path {colmap_dir / 'database.db'}",
f"--image_path {out_image_dir}",
f"--input_path {model_path}",
f"--output_path {model_path}",
]
point_triangulator_cmd = " ".join(point_triangulator_cmd)
with status(msg="[bold yellow]Running COLMAP point triangulator...", spinner="dqpb", verbose=verbose):
run_command(point_triangulator_cmd, verbose=verbose)
CONSOLE.log("[bold green]:tada: Done COLMAP point triangulator..")
# convert bin totxt
model_converter_cmd = [
f"{colmap_cmd} model_converter",
f"--input_path {model_path}",
f"--output_path {model_path}",
f"--output_type TXT",
]
model_converter_cmd = " ".join(model_converter_cmd)
with status(msg="[bold yellow]Running model convert...", spinner="runner", verbose=verbose):
run_command(model_converter_cmd, verbose=verbose)
CONSOLE.log("[bold green]:tada: Done model convert.")