open3d 处理rgb-d深度图

  1. 创建环境
scss 复制代码
conda create -n tsdf python=3.10 -y
conda activate tsdf
# 2.1 升级打包工具
python -m pip install --upgrade pip setuptools wheel

# 2.2 安装核心库(建议直接用 pip 安装到当前 conda 环境)
pip install open3d opencv-python numpy scikit-image numba tqdm

# 2.3 快速自检:打印各库版本
python -c "import open3d as o3d, cv2, numpy as np, skimage, numba, tqdm; print('open3d:', o3d.__version__); print('opencv:', cv2.__version__); print('numpy:', np.__version__); print('skimage:', skimage.__version__); print('numba:', numba.__version__); print('tqdm ok')"
  1. 下载测试包,带相机参数的深度图 链接 下载后可以看到color里面是正常的照片,depth里面是深度图,其他文件是相机内参等。
  2. 用官方小样数据跑一个 TSDF 重建
python 复制代码
import os, glob, json
import numpy as np
import open3d as o3d

# === 1) 指定你的数据目录(你已经解压到这里) ===
DATA_DIR = r".\tsdf_demo\redwood_data"

color_paths = sorted(glob.glob(os.path.join(DATA_DIR, "color", "*.jpg")))
depth_paths = sorted(glob.glob(os.path.join(DATA_DIR, "depth", "*.png")))
assert len(color_paths) == len(depth_paths) and len(color_paths) > 0, "color/depth 数量不匹配或为空"
print(f"[INFO] 找到 {len(color_paths)} 对 RGB-D 图像")

# === 2) 相机内参:优先读 camera_primesense.json,读不到就用常用默认值 ===
intr_json = os.path.join(DATA_DIR, "camera_primesense.json")
if os.path.exists(intr_json):
    with open(intr_json, "r", encoding="utf-8") as f:
        data = json.load(f)
    # Open3D 的示例里常见字段是 intrinsic_matrix(3x3, 行优先)
    K = data.get("intrinsic_matrix", None)
    if K and len(K) == 9:
        fx, fy = K[0], K[4]
        cx, cy = K[2], K[5]
        width  = data.get("width", 640)
        height = data.get("height", 480)
    else:
        # 兜底
        fx = fy = 525.0
        cx, cy = 319.5, 239.5
        width, height = 640, 480
else:
    fx = fy = 525.0
    cx, cy = 319.5, 239.5
    width, height = 640, 480

intr = o3d.camera.PinholeCameraIntrinsic(width, height, fx, fy, cx, cy)
print(f"[INFO] Intrinsics: fx={fx:.1f}, fy={fy:.1f}, cx={cx:.1f}, cy={cy:.1f}, size={width}x{height}")

# === 3) 创建 TSDF 体 ===
voxel = 0.02       # 体素边长 2cm
sdf_trunc = 0.08   # 截断 8cm
tsdf = o3d.pipelines.integration.ScalableTSDFVolume(
    voxel_length=voxel,
    sdf_trunc=sdf_trunc,
    color_type=o3d.pipelines.integration.TSDFVolumeColorType.RGB8
)

# === 4) 逐帧:里程计 + 融合(深度单位 mm) ===
depth_scale = 1000.0
depth_trunc = 3.0  # 3 米外丢弃
odo_option = o3d.pipelines.odometry.OdometryOption()
odo_method = o3d.pipelines.odometry.RGBDOdometryJacobianFromHybridTerm()

def make_rgbd(cpath, dpath):
    color = o3d.io.read_image(cpath)
    depth = o3d.io.read_image(dpath)
    return o3d.geometry.RGBDImage.create_from_color_and_depth(
        color, depth,
        depth_scale=depth_scale,
        depth_trunc=depth_trunc,
        convert_rgb_to_intensity=False
    )

T_global = np.eye(4)
rgbd_prev = make_rgbd(color_paths[0], depth_paths[0])
tsdf.integrate(rgbd_prev, intr, np.linalg.inv(T_global))

for i in range(1, len(color_paths)):
    rgbd = make_rgbd(color_paths[i], depth_paths[i])
    success, T_step, _ = o3d.pipelines.odometry.compute_rgbd_odometry(
        rgbd_prev, rgbd, intr, np.eye(4), odo_method, odo_option
    )
    if success:
        T_global = T_global @ T_step
    else:
        print(f"[WARN] 第 {i} 帧里程计失败,沿用上一帧位姿")
    tsdf.integrate(rgbd, intr, np.linalg.inv(T_global))
    rgbd_prev = rgbd

# === 5) 提取网格并保存 ===
mesh = tsdf.extract_triangle_mesh()
mesh.compute_vertex_normals()
out_path = os.path.join(os.getcwd(), "mesh_redwood.ply")
o3d.io.write_triangle_mesh(out_path, mesh)
print(f"[OK] 已输出: {out_path}")
  1. 用 Open3D 的简易查看器看看网格
scss 复制代码
python -c "import open3d as o3d; m=o3d.io.read_triangle_mesh(r'.\tsdf_demo\mesh_redwood.ply'); m.compute_vertex_normals(); o3d.visualization.draw_geometries([m])"

坐标系约定不一致:图形学里常见 +Y 为上,而很多相机/机器人坐标系里图像坐标 +y 向下、或世界坐标的"上"是 +Z。

相关推荐
行走的陀螺仪1 小时前
.vscode 文件夹配置详解
前端·ide·vscode·编辑器·开发实践
2503_928411562 小时前
11.24 Vue-组件2
前端·javascript·vue.js
Bigger2 小时前
🎨 用一次就爱上的图标定制体验:CustomIcons 实战
前端·react.js·icon
谢尔登2 小时前
原来Webpack在大厂中这样进行性能优化!
前端·webpack·性能优化
cypking3 小时前
Vue 3 + Vite + Router + Pinia + Element Plus + Monorepo + qiankun 构建企业级中后台前端框架
前端·javascript·vue.js
雨雨雨雨雨别下啦4 小时前
【从0开始学前端】vue3简介、核心代码、生命周期
前端·vue.js·vue
simon_93494 小时前
受够了压缩和收费?我作为一个码农,手撸了一款无限容量、原图直出的瀑布流相册!
前端
e***87705 小时前
windows配置永久路由
android·前端·后端
Dorcas_FE6 小时前
【tips】动态el-form-item中校验的注意点
前端·javascript·vue.js
小小前端要继续努力6 小时前
前端新人怎么更快的融入工作
前端