一、相机会读取哪些数据?
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.基础读取 + 保存(彩色、深度、点云、相机内参、外参、深度比例尺与时间戳)
单帧采集
操作方式:
-
运行程序后,窗口会同时显示彩色图像和深度预览。
-
按
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 停止
