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。

相关推荐
小猪猪屁3 小时前
WebAssembly 从零到实战:前端性能革命完全指南
前端·vue.js·webassembly
EMT3 小时前
记一个Vue.extend的用法
前端·vue.js
RaidenLiu3 小时前
Riverpod 3:组合与参数化的进阶实践
前端·flutter
jason_yang3 小时前
vue3自定义渲染内容如何当参数传递
前端·javascript·vue.js
年年测试3 小时前
Browser Use 浏览器自动化 Agent:让浏览器自动为你工作
前端·数据库·自动化
维维酱3 小时前
React Fiber 架构与渲染流程
前端·react.js
gitboyzcf3 小时前
基于Taro4最新版微信小程序、H5的多端开发简单模板
前端·vue.js·taro
姓王者3 小时前
解决Tauri2.x拖拽事件问题
前端
冲!!4 小时前
vue3存储/获取本地或会话存储,封装存储工具,结合pina使用存储
前端·javascript·vue.js