19f1d218f4b3a.png

1. 项目速览:把三维重建从“重装备”变成“手持工具”

这个项目面向室内环境三维重建,目标很直接:让用户只需手持 Astra Pro RGB-D 相机 与 Zora P1 嵌入式开发板,就能完成室内空间扫描、位姿估计、点云融合与模型可视化。它不是把所有计算硬塞进一块板子里“硬扛”,而是采用轻量化、松耦合的系统设计:采集端保持灵活,计算端按能力分工,通信端由 ROS 串起来。这样一来,设备轻了,部署活了,重建链路也更容易扩展。🚀

项目要素 内容
项目名称 轻量化松耦合的手持 RGB-D 室内环境实时重建系统
来源 第一届 3D 视觉创新应用竞赛,陈钧涛
主要传感器 Astra Pro RGB-D 相机
嵌入式设备 Zora P1 开发板
核心软件栈 ROS、PCL、OctoMap、G2O、Eigen3、OpenCV、Qt5、OpenMP
主要能力 RGB-D 采集、位姿估计、TSDF 融合、网格生成、在线/离线可视化

| 源代码 | 3DReconstruction_Handheld-reconstruction|

一句话概括:它把“相机采集、位姿估计、三维融合、模型显示”拆成可以独立协作的模块,让手持扫描不再被单机算力和设备体积绑住手脚。

2. 系统架构:三端协作,轻装上阵 🧩

19f1d24548d81.png

系统整体可以理解为“三端协作”:

端侧 主要职责 典型组件
采集端 采集 RGB 图像、深度图、相机内参,并通过 ROS 发布数据 Astra Pro、Zora P1、astra_camera
服务端 进行较重的位姿估计与全局优化,并将优化后的相机位姿返回 BundleFusion、GPU 工作站
在线端 在 PC 上完成一站式实时重建、图优化与可视化 RGBD-SLAM v2、PCL、OctoMap、G2O

这种设计的关键不在于“模块越多越热闹”,而在于每个模块都做自己最擅长的事情:嵌入式端负责轻便采集与局部融合,服务器负责高负载优化,PC 在线端负责交互式重建和展示。系统通过 ROS 消息连接,模块之间保持低耦合,后续替换相机、调整算法或升级计算端都更从容。

3. 两条重建路线:一条偏手持交互,一条偏在线显示

19f1d2cffede6.png

项目实现了两套互补流程:

模式 数据流 适用场景 技术重点
嵌入式/服务端协同模式 Zora P1 采集 RGB-D → 服务器估计位姿 → 开发板融合与渲染 手持扫描、轻量端交互、服务器远程辅助 ROS 通信、BundleFusion 位姿优化、FastFusion 融合
PC 在线重建模式 Zora P1 采集 RGB-D → PC 端直接估计位姿、建图与显示 桌面端快速验证、可视化调试、在线建图 RGBD-SLAM、ORB 特征、RANSAC、G2O、OctoMap

前者像是“轻便扫描枪 + 远程大脑”,后者像是“PC 工作站一站式重建台”。两者都围绕同一个目标:让室内场景以较低成本被实时捕获、配准并重建出来。

4. ROS 通信:让相机、开发板、服务器像一个系统一样说话 📡

19f1d3048e676.png

项目里专门定义了 topic_demo 消息包,用于在 ROS 网络中传输相机位姿与 RGB-D 图像。这个设计非常重要:它把“位姿”和“图像帧”打包成同一个消息,开发板收到消息后就能直接把对应帧融合进模型,避免时间戳错位造成的建图抖动。

# topic_demo/msg/pose.msg
int32 time

float32 translation1
float32 translation2
float32 translation3

float32 q1
float32 q2
float32 q3
float32 q4

string depthname
string rgbname

sensor_msgs/Image colorImage
sensor_msgs/Image depthImage

跨设备运行时,需要让不同主机共享同一个 ROS Master。项目说明中给出了典型 IP 配置:

# 主机端,例如 192.168.2.51
export ROS_HOSTNAME=192.168.2.51
export ROS_MASTER_URI=http://192.168.2.53:11311

# 开发板端,例如 192.168.2.53
export ROS_HOSTNAME=192.168.2.53
export ROS_MASTER_URI=http://192.168.2.53:11311

# 开发板启动 Astra Pro
roslaunch astra_camera astrapro.launch

这套通信方式的好处是:相机必须接在开发板上,但重建算法不必都跑在开发板上。只要网络打通,服务端和在线端就能订阅数据、发布位姿、完成融合,系统部署弹性明显增强。

5. 服务器端:BundleFusion 负责“把相机走过的路算准” 🧠

19f1d34e9f591.png

在嵌入式/服务端协同模式中,服务器端运行 BundleFusion 相关节点。它订阅开发板发布的 RGB 图像和深度图,计算当前帧的相机位姿,然后把平移、四元数、RGB 图像和深度图一起发布到 pose_info。

核心发布逻辑可以概括为:

// bundlefusion_ros: 订阅 RGB-D 图像,并发布优化后的位姿消息
validTransform = g_depthSensingBundler->getCurrentIntegrationFrame(
    transformation, frameIdx, bGlobalTrackingLost
);

vec3f translation_vector = transformation.getTranslation();
Eigen::Quaternionf q(rotation_matrix_eigen);

topic_demo::pose msg;
msg.time = frameIdx;
msg.translation1 = translation_vector[0];
msg.translation2 = translation_vector[1];
msg.translation3 = translation_vector[2];
msg.q1 = -q.coeffs().transpose()[0];
msg.q2 = -q.coeffs().transpose()[1];
msg.q3 = -q.coeffs().transpose()[2];
msg.q4 =  q.coeffs().transpose()[3];

cv_bridge::CvImage(...).toImageMsg(msg.colorImage);
cv_bridge::CvImage(...).toImageMsg(msg.depthImage);
pub.publish(msg);

从算法角度看,BundleFusion 的优势在于它不是只看“上一帧到下一帧”的短距离匹配,而是通过全局联合优化减少累积漂移。项目技术文档中提到的层次式思路可以理解为:

优化层级 作用 为什么重要
帧间跟踪 估计相邻 RGB-D 帧之间的相对运动 提供连续运动线索
分段优化 将视频流切成片段,片段内做局部一致性约束 降低长序列直接优化的复杂度
关键帧优化 以片段关键帧为节点做全局约束 控制长时间扫描中的漂移
回环约束 当相机回到旧区域时修正历史轨迹 让房间“闭合”得更自然

因此,服务端就像系统里的“位姿审稿人”:它不只问“这一帧像不像上一帧”,还会回头检查整个轨迹是否自洽。

6. 嵌入式端:FastFusion 用八叉树 TSDF 把深度帧熔成模型 🔧

19f1d3776a0bb.png

开发板端接收 pose_info 后,会把位姿、RGB 图和深度图转换成 FastFusion 所需的数据结构,并调用 fusion->addMap() 进行融合,再用 fusion->updateMeshes() 更新网格。

// fastfusion_ros: 接收服务器发布的 pose_info,并执行融合
void addMapCallback(const topic_demo::pose::ConstPtr& msg, ...) {
    Eigen::Quaterniond q(msg->q4, msg->q1, msg->q2, msg->q3);
    Eigen::Vector3d t(msg->translation1, msg->translation2, msg->translation3);

    CameraInfo pose(kinectPoseFromEigen1({ q.toRotationMatrix(), t },
                                         fx, fy, cx, cy));

    cv::Mat rgbimage =
        cv_bridge::toCvCopy(msg->colorImage, msg->colorImage.encoding)->image;
    cv::Mat depthimage =
        cv_bridge::toCvCopy(msg->depthImage, msg->depthImage.encoding)->image;

    fusion->addMap(depthimage, pose, rgbimage,
                   1.0f / imageDepthScale, maxCamDistance);
    *newMesh = fusion->updateMeshes();
}

这里的关键技术是 TSDF(Truncated Signed Distance Function,截断符号距离函数)融合。它会把每一帧深度图投影到三维空间,把表面附近的体素距离不断加权平均。八叉树结构则让空间管理更聪明:有几何细节的地方细分得更密,空旷区域不浪费内存。

伪代码:八叉树 TSDF 融合流程

for each depth pixel:
    point_3d = back_project(pixel, depth, camera_intrinsics)
    point_world = transform(point_3d, camera_pose)

    brick = octree.find_or_create_brick(point_world)
    for each voxel near projected surface:
        sdf = compute_signed_distance(voxel, depth_surface)
        tsdf = clamp(sdf / truncation_distance, -1, 1)

        voxel.tsdf  = weighted_average(voxel.tsdf, tsdf)
        voxel.color = weighted_average(voxel.color, rgb_pixel)
        voxel.weight += observation_weight

mark_updated_bricks_for_incremental_meshing()
update_mesh_by_marching_cubes()

从工程实现看,fastfusion_ros 中的 FusionMipMapCPU 封装了地图融合、网格更新和队列管理等接口:

// fastfusion_ros/src/fusion/geometryfusion_mipmap_cpu.hpp
class FusionMipMapCPU : public Fusion_AoS {
public:
    void addMap(const cv::Mat& imageDepth,
                const CameraInfo& info,
                const cv::Mat& imageColor,
                float depthScaleFactor,
                float maxCamDistance);

    MeshSeparate getMeshSeparateMarchingCubes();
    boost::shared_ptr<MeshInterleaved> updateMeshes();
    void pushLeafQueueForMeshing(MapTreeNode* leaf);
};

这套方案的亮点是:它没有要求开发板实时跑完整的高负载全局优化,而是让开发板专注于接收优化位姿后的融合与渲染。算力分配更合理,系统也更接近真实可用的手持扫描流程。

7. 在线端:RGBD-SLAM 让 PC 直接“边看边建图” 🖥️

19f1d38b7ab98.png

在线端主要基于 RGBD-SLAM v2。它直接订阅开发板发布的 RGB 图、深度图和相机内参,在 PC 上完成特征提取、位姿估计、图优化和可视化。项目中的 rgbdslam_orbbec.launch 已经把 Astra Pro 的话题接入配置好:

<!-- rgbdslam/launch/rgbdslam_orbbec.launch -->
<param name="config/topic_image_mono"
       value="/camera/rgb/image_rect_color"/>
<param name="config/topic_image_depth"
       value="/camera/depth/image_rect"/>
<param name="config/topic_cam_info"
       value="/camera/depth/camera_info"/>

<param name="config/feature_extractor_type" value="ORB"/>
<param name="config/feature_detector_type" value="ORB"/>
<param name="config/max_keypoints" value="600"/>
<param name="config/max_matches" value="300"/>
<param name="config/ransac_iterations" value="100"/>
<param name="config/backend_solver" value="pcg"/>

在线重建链路可以拆成四步:

阶段 输入 处理方法 输出
特征提取 RGB 图像 ORB 特征检测与描述 稀疏特征点
位姿估计 特征匹配、深度信息 RANSAC 筛除误匹配 帧间相对位姿
图优化 位姿节点与约束边 G2O 后端优化 全局一致轨迹
地图生成 深度点云与优化位姿 PCL/OctoMap 融合 点云或八叉树地图

其中,ORB 是一个工程上很务实的选择:它速度快、适合 CPU 实时运行,能在室内纹理较丰富的办公桌、墙面边缘、设备轮廓上提取稳定特征。配合 RANSAC 和 G2O,系统可以在噪声和局部遮挡中保持较稳健的轨迹估计。

8. 相机标定:内参不准,模型就会“长歪” 📐

19f1d3ad898cb.png

Astra Pro 的 RGB 与深度数据要想可靠融合,内参标定必须先过关。项目技术文档中采用棋盘格分别标定 RGB 相机与红外相机,示例流程如下:

% 相机标定核心流程示意
images = imageDatastore('color/');
[imagePoints, boardSize] = detectCheckerboardPoints(images.Files);

squareSize = 30; % mm
worldPoints = generateCheckerboardPoints(boardSize, squareSize);

I = readimage(images, 1);
imageSize = [size(I, 1), size(I, 2)];

cameraParams = estimateCameraParameters(imagePoints, worldPoints, ...
    'ImageSize', imageSize);

标定后的内参会影响反投影、点云生成、TSDF 融合和位姿估计。换句话说,内参不是“配置表里随便填的数字”,而是整个系统从二维图像走向三维空间的尺子。

9. 工程部署:依赖多,但脉络很清楚

19f1d3c6fa7a2.png

项目源码主要包含四个 ROS 包:

ROS 包 角色 说明
topic_demo 消息定义 定义包含位姿与 RGB-D 图像的 pose 消息
bundlefusion_ros 服务端优化 将 BundleFusion 接入 ROS,用于位姿估计与全局优化
fastfusion_ros 嵌入式融合 接收优化位姿与图像,执行 TSDF 融合和网格更新
rgbdslam 在线重建 基于 RGBD-SLAM v2 完成 PC 端在线建图与显示

环境依赖可以按端侧理解:

端侧 关键依赖 作用
开发板端 ROS、OpenCV、Boost、Eigen3、Astra 驱动 采集 RGB-D 数据,运行轻量融合与显示
服务端 ROS Melodic、CUDA、OpenGL、GLEW、Eigen3、OpenCV 运行 BundleFusion 与 GPU 相关优化
在线端 ROS Melodic、PCL 1.8、OctoMap 1.6、G2O、Qt5、OpenMP、Eigen3、OpenCV 运行 RGBD-SLAM、点云/八叉树地图与 GUI

典型编译方式与普通 ROS 工作空间一致:

cd ~/catkin_ws/src
# 将 bundlefusion_ros、fastfusion_ros、rgbdslam、topic_demo 放入 src
cd ~/catkin_ws
catkin_make
source devel/setup.bash

需要注意的是,bundlefusion_ros 依赖较大的外部库目录,项目 README 中提示需要额外下载并放入指定位置;此外,部分旧依赖涉及 OpenCV、CUDA、GLEW、GTK 和编译器版本,部署时应尽量按项目文档的版本组合进行复现。

10. 重建效果与性能:轻量设备也能认真干活 📊

19f1d40bcc61c.png

项目技术文档中展示了约 10 平方米室内区域的重建结果,包括桌面细节、开放式桌面区域,以及三工位、四工位等办公场景。整体表现说明系统可以恢复桌椅相对位置、桌面结构和主要室内布局,适合室内扫描、空间数字化、机器人环境建模等场景。

性能数据如下,已整理为适合飞书粘贴阅读的表格:

运行端 测试内容 速度
开发板离线端 数据集融合 11.6 fps
开发板离线端 数据集渲染 2.3 fps
开发板离线端 实时读取 ROS 数据并融合 8.6 fps
开发板离线端 实时读取 ROS 数据并渲染 2.8 fps
GPU 服务端 数据集重建 2.6 fps
GPU 服务端 实时读取 ROS 数据并重建 8.6 fps
CPU 在线端 数据集重建与渲染 7.6 fps
CPU 在线端 实时读取 ROS 数据并重建渲染 8.4 fps

从数据可以看出,系统的实时性不是靠单点爆发,而是靠任务拆分实现平衡:服务端负责重位姿计算,开发板负责融合显示,在线端负责 PC 一体化重建。这样的架构对低成本设备更友好,也便于后续扩展更强算力或更高分辨率传感器。

11. 技术亮点:轻、准、活,三件事都要 ✨

技术亮点 具体体现 工程价值
轻量化手持采集 Astra Pro 与 Zora P1 体积小、重量低 降低室内扫描门槛
松耦合系统架构 ROS 网络连接采集端、服务端、在线端 便于调试、替换和扩展
八叉树 TSDF 融合 按空间复杂度管理体素与网格更新 节省内存,提高融合效率
全局位姿优化 BundleFusion 进行层次式联合优化 减少轨迹漂移,提高模型一致性
在线 SLAM 可视化 RGBD-SLAM 支持实时轨迹和地图展示 方便实验验证与现场演示

不过,项目也暴露出很真实的工程边界:Zora P1 的内存和 CPU 资源有限,若把所有重建任务都压在开发板上,容易出现卡顿甚至崩溃。因此,项目最后采用“位姿优化外包、开发板融合显示”的策略,本质上是在有限硬件条件下做了一次很务实的系统工程取舍。

12. 可优化方向:下一版可以更丝滑 🛠️

19f1d42915dac.png
优化方向 可行做法 预期收益
降低通信延迟 压缩 RGB-D 数据、同步时间戳、优化 ROS 队列 提升实时扫描稳定性
提高嵌入式端性能 使用更高效的 TSDF 数据结构或 GPU/NPU 加速 提升融合与渲染帧率
增强弱纹理鲁棒性 引入 IMU、平面约束或语义特征 减少白墙、走廊场景漂移
改善模型质量 加入深度滤波、法向一致性约束、后处理网格优化 降低噪声,提升表面平滑度
简化部署 容器化依赖、统一启动脚本、可视化配置面板 降低复现实验和现场演示成本

13. 总结:这不是“一个算法”,而是一套会协作的重建系统

这套轻量化松耦合手持 RGB-D 室内实时重建系统的价值,不只在于能生成室内三维模型,更在于它把复杂重建任务拆解成了清晰的系统链路:Astra Pro 负责看见世界,Zora P1 负责轻便采集与交互,服务器负责算准位姿,PC 在线端负责快速验证和展示。

它的路线并不花哨,却很工程化:用 ROS 做通信胶水,用 BundleFusion 解决精确位姿,用 FastFusion 完成高效融合,用 RGBD-SLAM 支撑在线重建。对于低成本 RGB-D 设备、嵌入式视觉和室内数字化应用来说,这是一套很有参考价值的系统范例。换个更轻快的说法:拿起相机走一圈,空间数据就开始认真排队建模了。 🎯

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注