RealSense D435i 图像采集与数据读取

一、相机会读取哪些数据?

1. 彩色图像(RGB / Color)

保存格式:.png 或 .jpg

就像普通相机拍的照片,记录葡萄、叶片、枝梗的颜色和纹理。可用于目标分割、葡萄区域识别,以及给点云添加颜色。

2. 原始深度图(Depth)

保存格式:16 位 png、.npy

图像的每个像素记录对应位置的深度值。它是生成三维点云的关键输入。深度为 0 的像素通常表示没有有效深度测量。

3. 三维点云(Point Cloud)

保存格式:.ply、.pcd

每个点包含三维坐标 \((x,y,z)\),还可以附带 RGB 颜色。点云不是相机直接输出的原始图像,而是利用深度、相机内参等数据计算得到的。

4. 相机标定参数与采集信息

保存格式:.json 或 .csv

包括焦距、主点坐标、畸变参数、深度比例尺、深度与彩色相机之间的外参、时间戳和帧编号。

5.左右红外图像

6.内置六轴 IMU(加速度计和陀螺仪)数据


二、这些数据之间是什么关系?

三、数据的保存

方法一:纯 SDK(Python)

1.安装 pyrealsense2

bash 复制代码
pip install pyrealsense2

2.基础读取 + 保存(彩色、深度、点云、相机内参、外参、深度比例尺与时间戳)

单帧采集

新建data.py

操作方式:

  • 运行程序后,窗口会同时显示彩色图像和深度预览。

  • 按 S:保存当前这一组数据。

  • 按 Q:退出程序

python 复制代码
import os
import json
from datetime import datetime

import cv2
import numpy as np
import pyrealsense2 as rs


# ==========================================
# 1. 基本设置
# ==========================================
SAVE_ROOT = "realsense_data"
os.makedirs(SAVE_ROOT, exist_ok=True)

pipeline = rs.pipeline()
config = rs.config()

# 先使用两款相机较常用的测试分辨率
config.enable_stream(
    rs.stream.depth, 640, 480, rs.format.z16, 30
)
config.enable_stream(
    rs.stream.color, 640, 480, rs.format.bgr8, 30
)

# 启动相机
profile = pipeline.start(config)
device = profile.get_device()

# 获取深度比例尺:原始深度单位转换为米
depth_scale = device.first_depth_sensor().get_depth_scale()

# 将深度图对齐到彩色图像坐标系
align = rs.align(rs.stream.color)

# 点云计算对象
pc = rs.pointcloud()


# ==========================================
# 2. 辅助函数:读取相机标定参数
# ==========================================
def get_device_info(device, key):
    try:
        return device.get_info(key)
    except Exception:
        return None


def get_intrinsics(frame):
    intr = frame.profile.as_video_stream_profile().intrinsics

    return {
        "width": int(intr.width),
        "height": int(intr.height),
        "fx": float(intr.fx),
        "fy": float(intr.fy),
        "cx": float(intr.ppx),
        "cy": float(intr.ppy),
        "distortion_model": str(intr.model),
        "distortion_coefficients": [
            float(v) for v in intr.coeffs
        ]
    }


def get_extrinsics(depth_frame, color_frame):
    ext = depth_frame.profile.get_extrinsics_to(
        color_frame.profile
    )

    return {
        "rotation": [float(v) for v in ext.rotation],
        "translation_m": [
            float(v) for v in ext.translation
        ]
    }


# ==========================================
# 3. 保存当前一组数据
# ==========================================
def save_sample(
    depth_frame,
    color_frame,
    aligned_depth_frame,
    depth_raw,
    color_bgr,
    aligned_depth_raw
):
    # 每次采集创建独立文件夹
    sample_name = datetime.now().strftime(
        "sample_%Y%m%d_%H%M%S_%f"
    )
    sample_dir = os.path.join(SAVE_ROOT, sample_name)
    os.makedirs(sample_dir, exist_ok=True)

    # 原始深度单位转换为米
    depth_m = (
        depth_raw.astype(np.float32) * depth_scale
    )
    aligned_depth_m = (
        aligned_depth_raw.astype(np.float32) * depth_scale
    )

    # 1) 保存彩色图像
    cv2.imwrite(
        os.path.join(sample_dir, "color.png"),
        color_bgr
    )

    # 2) 保存原始深度图
    # PNG 保留 uint16 数值,不要先转成 8 位图
    cv2.imwrite(
        os.path.join(sample_dir, "depth_raw_z16.png"),
        depth_raw
    )
    np.save(
        os.path.join(sample_dir, "depth_raw_z16.npy"),
        depth_raw
    )

    # 3) 保存以米为单位的深度数组
    np.save(
        os.path.join(sample_dir, "depth_m.npy"),
        depth_m
    )

    # 4) 保存对齐到彩色图像的深度数据
    cv2.imwrite(
        os.path.join(
            sample_dir, "depth_aligned_to_color_z16.png"
        ),
        aligned_depth_raw
    )
    np.save(
        os.path.join(
            sample_dir, "depth_aligned_to_color_m.npy"
        ),
        aligned_depth_m
    )

    # 5) 保存深度可视化图,仅供观察,不用于精度计算
    valid = depth_raw > 0
    depth_vis_gray = np.zeros(
        depth_raw.shape, dtype=np.uint8
    )

    # 0.2~2.0 m 仅用于设置显示范围
    depth_vis_gray[valid] = np.clip(
        (depth_m[valid] - 0.2) / (2.0 - 0.2) * 255,
        0, 255
    ).astype(np.uint8)

    depth_vis = cv2.applyColorMap(
        depth_vis_gray, cv2.COLORMAP_JET
    )
    depth_vis[~valid] = (0, 0, 0)

    cv2.imwrite(
        os.path.join(sample_dir, "depth_preview.png"),
        depth_vis
    )

    # 6) 根据原始深度生成带颜色的三维点云
    pc.map_to(color_frame)
    points = pc.calculate(depth_frame)

    points.export_to_ply(
        os.path.join(sample_dir, "pointcloud_rgb.ply"),
        color_frame
    )

    # 7) 保存标定参数和采集信息
    metadata = {
        "camera_name": get_device_info(
            device, rs.camera_info.name
        ),
        "serial_number": get_device_info(
            device, rs.camera_info.serial_number
        ),
        "firmware_version": get_device_info(
            device, rs.camera_info.firmware_version
        ),
        "depth_scale_m_per_unit": float(depth_scale),
        "depth_raw_note": (
            "depth_m = depth_raw_z16 * "
            "depth_scale_m_per_unit; raw=0 means invalid"
        ),
        "depth_timestamp_ms": float(
            depth_frame.get_timestamp()
        ),
        "color_timestamp_ms": float(
            color_frame.get_timestamp()
        ),
        "depth_frame_number": int(
            depth_frame.get_frame_number()
        ),
        "color_frame_number": int(
            color_frame.get_frame_number()
        ),
        "depth_intrinsics": get_intrinsics(depth_frame),
        "color_intrinsics": get_intrinsics(color_frame),
        "depth_to_color_extrinsics": get_extrinsics(
            depth_frame, color_frame
        ),
        "depth_aligned_to_color": True,
        "coordinate_unit": "meter"
    }

    with open(
        os.path.join(sample_dir, "metadata.json"),
        "w",
        encoding="utf-8"
    ) as f:
        json.dump(
            metadata, f, ensure_ascii=False, indent=2
        )

    print("已保存一组数据:", sample_dir)


# ==========================================
# 4. 实时采集与键盘控制
# ==========================================
try:
    # 预热相机,等待自动曝光等状态稳定
    for _ in range(30):
        pipeline.wait_for_frames()

    print("相机已启动。")
    print("按 S 保存一组数据;按 Q 退出。")

    while True:
        frames = pipeline.wait_for_frames()

        depth_frame = frames.get_depth_frame()
        color_frame = frames.get_color_frame()

        if not depth_frame or not color_frame:
            continue

        # 对齐深度到彩色图像
        aligned_frames = align.process(frames)
        aligned_depth_frame = (
            aligned_frames.get_depth_frame()
        )

        if not aligned_depth_frame:
            continue

        # 读取相机输出
        depth_raw = np.asanyarray(
            depth_frame.get_data()
        )
        color_bgr = np.asanyarray(
            color_frame.get_data()
        )
        aligned_depth_raw = np.asanyarray(
            aligned_depth_frame.get_data()
        )

        # 生成仅供预览的深度图
        depth_m = (
            depth_raw.astype(np.float32) * depth_scale
        )
        valid = depth_raw > 0
        depth_vis_gray = np.zeros(
            depth_raw.shape, dtype=np.uint8
        )
        depth_vis_gray[valid] = np.clip(
            (depth_m[valid] - 0.2) / 1.8 * 255,
            0, 255
        ).astype(np.uint8)

        depth_vis = cv2.applyColorMap(
            depth_vis_gray, cv2.COLORMAP_JET
        )
        depth_vis[~valid] = (0, 0, 0)

        # 左侧彩色图,右侧深度预览
        preview = np.hstack((color_bgr, depth_vis))
        cv2.imshow("RGB | Depth", preview)

        key = cv2.waitKey(1) & 0xFF

        if key == ord("s"):
            save_sample(
                depth_frame,
                color_frame,
                aligned_depth_frame,
                depth_raw,
                color_bgr,
                aligned_depth_raw
            )

        elif key == ord("q"):
            break

finally:
    pipeline.stop()
    cv2.destroyAllWindows()
    print("相机已关闭。")

连续采集

使用 RealSense 的 .bag 录制功能。.bag 是相机数据记录文件,可以保存配置的传感器数据流及其时间信息,之后再回放、处理和导出点云。官方 SDK 支持这种录制与回放流程。

python 复制代码
import pyrealsense2 as rs

pipeline = rs.pipeline()
config = rs.config()

config.enable_stream(
    rs.stream.depth, 640, 480, rs.format.z16, 30
)
config.enable_stream(
    rs.stream.color, 640, 480, rs.format.bgr8, 30
)

# 开始采集前指定录制文件
config.enable_record_to_file("grape_capture.bag")

pipeline.start(config)

print("正在录制 RGB 和深度数据。")
print("按 Ctrl+C 停止录制。")

try:
    while True:
        pipeline.wait_for_frames()

except KeyboardInterrupt:
    print("正在停止录制...")

finally:
    pipeline.stop()
    print("录制结束,请检查 grape_capture.bag")

代码会持续录制彩色图像和深度数据,直到按 Ctrl+C 停止

相关推荐
深视智能科技3 天前
深视智能点激光位移传感器用于光模块外壳点胶引导
视觉检测
会飞锦鲤5 天前
工业AI视觉检测项目完整实施方案
人工智能·深度学习·视觉检测·缺陷检测·模型训练·ai项目·工业应用
shijuejianceliu5 天前
传统规则视觉与嵌入式AI智能相机的技术差异
人工智能·嵌入式硬件·视觉检测·相机
深视智能科技7 天前
中大尺寸工件在线三维测量:多相机线扫如何覆盖多面与多测点
视觉检测
深视智能科技8 天前
三维激光轮廓测量仪用于反光手机中框的三维扫描
视觉检测
微尘hjx9 天前
【Deep-OC-SORT 02】多轨迹算法Deep-OC-SORT-相对 OC-SORT 的改进点
人工智能·算法·yolo·目标跟踪·视觉检测·ultralytics·deep-oc-sort
深视智能科技9 天前
BGA封装锡球高度与顶点平面度怎么测?线激光方案的测量过程与
视觉检测
拓恒技术9 天前
从“可见光漏检”到“热异常锁定”:无人机河道排污口识别与溯源的技术链路
人工智能·视觉检测·无人机
深视智能科技9 天前
BGA封装锡球高度差机器视觉检测系统
视觉检测
song150265372989 天前
小型零部件外观检测难?AI机器视觉检测设备,适配全行业小件质检
人工智能·计算机视觉·视觉检测