Python实现已知相机位姿的稀疏重建

功能:
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.")

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值