十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

用 Rerun 可视化 COLMAP 稀疏重建:相机位姿、针孔投影与点云的时序日志方案

用 Rerun 可视化 COLMAP 稀疏重建:相机位姿、针孔投影与点云的时序日志方案 用 Rerun 可视化 COLMAP 稀疏重建相机位姿、针孔投影与点云的时序日志方案【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun本文以 Rerun 官方示例structure_from_motion为核心讲解如何将 COLMAPStructure-from-Motion / MVS 通用管线离线处理一段短视频后产出的稀疏重建结果——包括相机帧、估计位姿外参、针孔内参、重投影误差与随时间累积的三维点云——逐帧写入 Rerun 进行三维可视化与调试。读完本文你将掌握Pinhole、Transform3D、Points2D/Points3D、Scalars、Image等核心 archetype 的搭配用法并理解 Rerun 中实体路径 时间线 子实体层级的日志组织方式可直接迁移到自己的 SLAM、多视图几何或重建可视化任务中。示例背景从视频到稀疏重建COLMAP 是通用的 Structure-from-MotionSfM与 Multi-View StereoMVS管线同时提供图形界面和命令行接口。在本示例中一段短视频片段已通过 COLMAP 管线离线完成处理COLMAP 对视频帧提取特征、匹配特征点、估计每帧相机位姿并通过三角化生成场景的三维稀疏点云。处理得到的稀疏模型随后通过 Rerun 逐帧可视化从而在同一视图中呈现相机帧画面、估计的相机位姿以及随时间累积的点云。该示例在仓库中被归类于 3D 重建与建模类别见 examples/manifest.toml 中3d-reconstruction分类structure_from_motion排在该类别的首位展示其元数据声明为 Visualize a sparse 3D reconstruction from COLMAP: camera frames, estimated poses, and an accumulating point cloud见 examples/python/structure_from_motion/README.md。用到的 Rerun 数据类型本示例覆盖了 Rerun 中一组极具代表性的 archetype恰好构成2D/3D 视觉数据 时序标量 文档的完整组合Archetype用途在本示例中的实体Points2D图像平面上的二维关键点camera/image/keypointsPoints3D三维稀疏点云pointsTransform3D相机外参世界系到相机系的位姿变换cameraSeriesLines时序曲线的样式颜色等plot/avg_reproj_errScalars时序标量平均重投影误差plot/avg_reproj_errPinhole相机内参针孔投影模型camera/imageImage相机帧图像camera/imageTextDocumentMarkdown 说明文档description数据流水线与日志时序完整的数据流整个示例的执行逻辑位于 examples/python/structure_from_motion/structure_from_motion/main.py 的read_and_log_sparse_reconstruction()函数中核心链路如下读取 COLMAP 稀疏模型调用read_model(dataset_path / sparse, ext.bin)读取cameras、images、points3D三类数据源码见 read_write_model.py。该文件是从 COLMAP 官方read_write_model.py适配而来支持.bin二进制与.txt文本两种格式的读写。可选降噪filter_output开启时丢弃 RGB 全零无有效颜色或关联图像数量少于 4 张的噪声三维点main.py#L98-L100。记录静态数据将说明文档、坐标系约定、曲线样式等一次性写入staticTrue。逐帧迭代按文件名排序遍历每张图像从文件名中解析出原始视频帧号frame_idxCOLMAP 内部 image id 与视频帧号不一致随后在同一帧号下写入位姿、内参、图像、关键点、重投影误差与三维点。时间线TimelinesRerun 中所有日志数据都可以挂接到一条或多条时间线上。本例所有逐帧数据都关联到具体的视频帧号rr.set_time(frame, sequenceframe_idx)在源码中帧号从图像文件名中提取idx_match re.search(r\d, image.name)即从如000001.png这类文件名中解析出数字作为frame时间线的 sequence 值main.py#L113-L116。这样在 Rerun Viewer 中拖动时间轴时就能看到相机位置、点云与画面随帧同步变化。静态static数据不随时间变化的数据以staticTrue写入包括rr.log(description, rr.TextDocument(DESCRIPTION, media_typerr.MediaType.MARKDOWN), staticTrue) rr.log(/, rr.ViewCoordinates.RIGHT_HAND_Y_DOWN, staticTrue) rr.log(plot/avg_reproj_err, rr.SeriesLines(colors[240, 45, 58]), staticTrue)其中description实体承载 Markdown 格式的示例说明文档对应默认蓝图中的 README 面板根实体/声明了场景的世界坐标系为右手系、Y 轴向下RIGHT_HAND_Y_DOWN与后续相机的 RDF 坐标系形成层级坐标系链SeriesLines为时序曲线预先指定颜色[240, 45, 58]红色使后续逐帧写入的Scalars直接继承该样式。图像的日志方式相机画面通过Imagearchetype 写入camera/image实体。默认未启用 resize时直接以编码图像形式记录原始文件启用--resize时则用 OpenCV 读取并按目标分辨率缩放后再记录rr.log(camera/image, rr.Image(bgr, color_modelBGR).compress(jpeg_quality75)).compress(jpeg_quality75)将图像以 JPEG 质量 75 压缩后传输在保证画面可读性的同时显著降低带宽与存储占用适合逐帧视频流场景。注意 OpenCV 读入的是 BGR 顺序需显式指定color_modelBGRmain.py#L168-L173。相机内外参Pinhole 与 Transform3D 的搭配视频帧来自位于三维世界中的针孔相机。要在三维空间中正确显示这些画面必须同时记录两部分信息内参intrinsics由Pinhole描述定义了如何从三维相机坐标系投影到二维图像平面外参extrinsics由Transform3D描述定义了相机在世界坐标系中的位姿。外参Transform3DCOLMAP 输出的变换是camera from world世界系到相机系而 Rerun 的Transform3D默认采用层级父子关系ChildFromParent两者语义一致可直接使用rr.log( camera, rr.Transform3D( translationimage.tvec, rotationrr.Quaternion(xyzwquat_xyzw), relationrr.TransformRelation.ChildFromParent, ), )源码中有一个关键细节COLMAP 使用 wxyz 顺序的四元数而 Rerun 的rr.Quaternion需要 xyzw 顺序因此做了重排quat_xyzw image.qvec[[1, 2, 3, 0]] # COLMAP uses wxyz quaternions同时相机实体还被声明为 RDF 坐标系X右、Y下、Z前这是计算机视觉领域图像坐标的惯用约定rr.log(camera, rr.ViewCoordinates.RDF, staticTrue) # XRight, YDown, ZForward内参PinholePinhole日志到camera/image实体与图像位于同一实体路径上Rerun 会自动将二者关联图像作为针孔相机前方的一个平面被投影到三维世界中rr.log( camera/image, rr.Pinhole( resolution[camera.width, camera.height], focal_lengthcamera.params[:2], principal_pointcamera.params[2:], ), )这里假设 COLMAP 的相机模型为PINHOLE源码中通过assert camera.model PINHOLE强校验其参数params按[focal_length_x, focal_length_y, principal_point_x, principal_point_y]顺序排列恰好与Pinhole的focal_length前两维和principal_point后两维一一对应main.py#L157-L166。内参随图像缩放当使用--resize选项时内参必须与图像一起等比缩放否则投影会错位。scale_camera()函数实现了这一逻辑scale_factor np.array([new_width / camera.width, new_height / camera.height]) new_params np.append(camera.params[:2] * scale_factor, camera.params[2:] * scale_factor)焦距与主点均按(新宽/原宽, 新高/原高)比例缩放main.py#L45-L55对应的二维关键点坐标也乘上同一scale_factormain.py#L133-L134。重投影误差的可视化对每张图像将可见三维点的重投影误差取平均后以Scalars写入plot/avg_reproj_err实体rr.log(plot/avg_reproj_err, rr.Scalars(np.mean(point_errors)))结合前面静态写入的SeriesLines样式Rerun 会在时间序列面板中自动绘制出一条随帧变化的误差曲线。point_errors来自 COLMAP 每个三维点记录的error字段即该点在各视角下的平均重投影误差从read_model读出的Point3D结构中获得read_write_model.py#L48这为评估重建质量提供了直观的量化指标。二维关键点子实体层级的使用用于三角化三维点的二维图像关键点以Points2D写入camera/image/keypointsrr.log(camera/image/keypoints, rr.Points2D(visible_xys, colors[34, 138, 167]))关键点实体是camera/image的子实体路径层级为camera → camera/image → camera/image/keypoints。Rerun 的变换与投影继承机制使得keypoints自动继承camera/image的Pinhole内参因此这些二维点会精确叠加在图像平面上而camera/image又继承camera的Transform3D外参从而整个相机-图像-关键点子层级被正确放置到三维世界中。指定颜色[34, 138, 167]青色使关键点在画面上清晰可辨。三维点云随时间累积的稀疏重建带颜色的三维点以Points3D写入points实体并将每个点的重投影误差作为任意附加属性AnyValues一并记录rr.log(points, rr.Points3D(points, colorspoint_colors), rr.AnyValues(errorpoint_errors))point_colors直接取自 COLMAP 三维点的rgb字段因此点云呈现场景的真实纹理颜色。由于每个点都在对应帧的时间线上写入播放时间轴时可以看到点云随帧逐步累积生长的过程——这正是该示例最直观的稀疏重建随时间演化效果main.py#L138-L144。默认蓝图与坐标系示例通过rr.script_setup()传入自定义默认蓝图将四个面板组织为上方 3D 视图 下方三栏README 文档 / 相机 2D 视图 / 时间序列曲线的布局blueprint rrb.Vertical( rrb.Spatial3DView( name3D, origin/, line_gridFalse, # Theres no clearly defined ground plane. ), rrb.Horizontal( rrb.TextDocumentView(nameREADME, origin/description), rrb.Spatial2DView(nameCamera, origin/camera/image), rrb.TimeSeriesView(origin/plot), ), row_shares[3, 2], )注意Spatial3DView关闭了line_grid地面网格因为稀疏重建场景没有明确的水平地面作为参考。三维视图的原点设为/相机 2D 视图锚定/camera/image时间序列面板锚定/plotplot/avg_reproj_err是其子实体会被自动包含。运行示例环境准备首先确保安装最新版 Rerun SDK 并检出与 SDK 版本匹配的仓库代码pip install --upgrade rerun-sdk # install the latest Rerun SDK git clone gitgithub.com:rerun-io/rerun.git # Clone the repository cd rerun git checkout latest # Check out the commit matching the latest SDK release然后以可编辑模式安装示例及其依赖依赖定义见 examples/python/structure_from_motion/pyproject.toml包括opencv-python4.6、numpy、requests2.31,3、rerun-sdk、tqdmpip install -e examples/python/structure_from_motion运行与命令行参数直接运行主脚本python -m structure_from_motion # run the example首次运行时会自动从官方数据集地址下载colmap_rusty_car数据集zip 解压到examples/python/structure_from_motion/dataset/目录见main.py#L39-L40 的DATASET_DIR与DATASET_URL_BASE常量因此需要网络连接下载与解压均带 tqdm 进度条。该脚本还提供了完整的 CLI 选项main.py#L178-L193参数默认值说明--unfiltered关闭若设置则不过滤任何噪声数据默认会丢弃 RGB 全零或关联图像数少于 4 的三维点并跳过可见点少于 500 个的帧FILTER_MIN_VISIBLE 500--datasetcolmap_rusty_car选择数据集可选colmap_rusty_car或colmap_fiatREADME 元数据中 CI 构建示例即使用--datasetcolmap_fiat --resize800x600--resize无目标分辨率格式如800x600会同步缩放图像、内参与二维关键点其余参数—rr.script_add_args(args)追加的 Rerun 通用脚本参数如--serve、--connect等查看完整帮助python -m structure_from_motion --help其他运行方式由于 pyproject.toml 声明了structure_from_motion structure_from_motion.__main__:main控制台脚本入口安装后也可以直接用structure_from_motion命令运行效果等价于python -m structure_from_motion。源码导读与迁移要点如果你想把这套方案复用到自己的 SLAM / 重建结果可视化中以下是关键的可复用资产COLMAP 模型解析器read_write_model.py 完整实现了 COLMAP 稀疏模型cameras.bin/.txt、images.bin/.txt、points3D.bin/.txt的读写支持 11 种相机模型PINHOLE、OPENCV、FISHEYE系列等见文件中的CAMERA_MODELS表并附带qvec2rotmat/rotmat2qvec四元数与旋转矩阵互转工具可直接移植。日志模板main.py 中静态数据 逐帧set_time 层级实体写入的骨架是 Rerun 时序三维可视化的标准写法。坐标系一致性COLMAP 的 wxyz 四元数 → Rerun 的 xyzwCOLMAP 的 camera from world → Rerun 的ChildFromParent世界系RIGHT_HAND_Y_DOWN→ 相机系RDF。这三处转换是本例正确显示的关键也是迁移到其他重建管线时最容易出错的地方。仓库中相关的 Rust 侧实现可进一步参考crates/store/re_sdk_types中对应 archetype 的定义以及 docs/content/concepts 下关于时间线、实体路径、坐标变换等概念的文档帮助你理解本文所述 API 背后的数据模型。【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表