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。

相关推荐
Hyyy1 天前
普通前端续命周报——第1周
前端·javascript
KaMeidebaby1 天前
卡梅德生物技术快报|抗独特型抗体开发:半抗原检测技术瓶颈拆解,抗独特型抗体开发工程化实践
前端·数据库·人工智能·其他·百度·新浪微博
2501_940041741 天前
纯前端创意交互:五款全新实用工具与视觉应用生成指南
前端·交互
刀法如飞1 天前
《道德经》简单解说版-第 2 章:天下皆知美之为美
前端·后端·面试
发现一只大呆瓜1 天前
超全 Vite 性能优化指南:网络、资源、预渲染三维落地方案
前端·面试·vite
IT_陈寒1 天前
Vue的computed属性怎么突然不更新了?
前端·人工智能·后端
智商不够_熬夜来凑1 天前
【Picker】单选多选
前端·javascript·vue.js
米饭不加菜1 天前
Typora 原生流程图语法完全指南(Flowchart.js)
前端·javascript·流程图
scan7241 天前
langgraphy条件边
前端·javascript·html
冰小忆1 天前
类变量在继承场景下的初始化规则是怎样的?
java·前端·数据库