跳到主要内容
技术文档/奥比中光/什么是深度相机?
奥比中光 / TECHNICAL WIKI

什么是深度相机?

3D 相机

为初学者介绍了深度相机的概念

Orbbec深度相机
什么是深度相机?
02 / DOCUMENTATION

内容概述

Community Wiki

深度图的每个有效像素都记录一个距离值:这个点离相机有多少毫米。多数深度相机还会同步输出 RGB 彩色图。

适合谁看:刚拿到第一台深度相机、需要读懂它输出的数据的人;给机器人、机械臂、AGV 加装视觉的开发者;正在为某个场景挑选型号的选型者。

读完能得到什么:

  1. 看得懂一张深度图,包括灰度版和彩色版分别该怎么读;
  2. 知道深度数据怎么变成三维坐标和点云;
  3. 判断手里的相机属于哪条技术路线,边界在哪里;
  4. 遇到深度图大面积发黑时,知道先检查什么。

建议阅读顺序:第一次接触深度相机,先读第 1 至 4 节;正在选型,再读第 5 至 8 节;已经拿到设备,可直接查阅第 9、10 节和附录 C、D。

全文内容概览

  • 深度图保存的是距离,不是“看起来像灰度图”的普通照片。
  • 算法计算应使用原始 16 位深度数据;伪彩深度图只用于观察和说明。
  • 结构光、ToF 与双目各有边界,选型应先看环境光、工作距离和表面纹理。
  • 黑洞、飞点和边缘毛刺通常是场景或成像原理造成的,并不等于相机损坏。

03 / DOCUMENTATION

普通摄像头缺了什么

Community Wiki

一张 RGB 图片是一个二维数组,每个元素记录红绿蓝三个亮度值。三维世界被投影到这个平面上,深度信息在投影过程中丢失。

人在判断远近时,会结合双眼视差、遮挡关系、焦外模糊以及对物体大小的经验。这些依据足够日常使用,但它们不给出一份可计算的数值。深度相机补上的正是这个数值:每个像素对应一个到相机的距离,单位通常为毫米。

普通 RGB 相机深度相机
输出颜色图(2D)深度图(2D + Z 值),多数同时输出彩色图
每个像素的含义亮度 / 颜色该点到相机的距离(mm)
能回答这是什么这是什么,以及它在哪里、多大、多远
受光照影响强,需要足够亮度取决于技术路线:主动红外适合弱光,但可能受阳光干扰;被动双目依赖环境纹理和光照
典型用途识别、检测、读码避障、抓取、重建、体感交互

RGB 相机回答画面里有什么,深度相机在此基础上回答它们在哪里、多远、多大。


04 / DOCUMENTATION

深度图怎么看

Community Wiki

深度图是一个二维数组,每个元素是距离值,不是颜色。同一份数据有两种常见呈现方式,初学者容易在这一步混淆。

  • 灰度深度图:把距离映射成亮度,越近越白、越远越黑。这是原始数据的直接可视化,一个像素对应一个数值,没有插值,也没有色带。
  • 彩色深度图,也称伪彩深度图或深度热度图:把同一个距离数值映射成一条彩色色带,常用 JET,从红到黄、绿、蓝。它不是另一份数据,只是灰度版换了一套配色。远近层次在灰阶里不容易分辨,换成色带之后差异更明显。

两者是同一份数据的两种画法,彩色版的颜色由灰度版的亮度换算而来。

2.1 一次实拍:同一画面的灰度与彩色

同一场景的灰度深度图与彩色深度图
同一场景的灰度深度图与彩色深度图

图 1:同一帧数据的两种呈现方式,Orbbec Astra 2 拍摄于实验室工位。左为 16 位灰度深度图,近处亮、远处暗;右为同一数据的伪彩版本,近处红、远处蓝。三处圆圈标出的是同一批没有数据的区域。

对比着看,有四点区别。

结构完全一致。 货架、桌子、保温杯、地面的轮廓在两张图里位置相同,因为就是同一份数据。彩色版看起来信息更多,来自配色对距离差异的放大,数据本身没有增加。

黑洞位置也一致。 左图的黑块对应右图的黑块,数量与位置都相同。这说明黑洞源于数据缺失,与渲染方式无关。

灰阶的分辨力集中在邻近范围。 这张图的深度范围是 516 mm 至 16616 mm,跨度 16 米,而人眼在灰阶上大约只能分辨几十级。8 米和 15 米的物体在灰度图里几乎是同一个深灰色,在彩色图里则落在不同的蓝调上。分析远近层次时用彩色版更合适。

灰度适合看形状,彩色适合看层次。 灰度图没有色相干扰,物体边缘和平面连续性更容易看清;彩色图的颜色跳变会把距离分层显示出来,前景、中景、背景可以直接区分。

本次采集的完整参数见附录 B。

2.2 彩色热度图的读数规则

深度值的配色规则与黑洞成因
深度值的配色规则与黑洞成因

图 2:(b) 伪彩映射规则;(c) 同一帧里三类黑洞的成因。

读彩色深度图时,有三项参数决定了图上的颜色代表什么。

色带方向。 常见的 JET 配色是红橙表示近、黄绿表示中、蓝色表示远,但方向取决于软件设置,有些工具用反向配色,有些用 VIRIDIS 之类不带色相的色带。拿到任何一台设备的图,先放一个已知距离的物体进去,例如把手置于 0.5 米处,确认色带方向后再做判断。

量程上限。 伪彩需要把一段距离区间映射到整条色带,这个区间称为量程。本文所有图使用固定量程 0 至 6000 mm。

如果改为按当前画面最大值自动归一化,会出现这样的问题:画面最远处达到 16 米时,6 米处的货架只占到色带的三分之一,2.5 米处的杯子被压到色带顶端附近,整片区域的颜色拉不开差距。固定量程可以让关心的距离区间分配到更多颜色层级。

纯黑与深灰的含义不同。 本文的处理约定如下:

图上颜色数值含义说明
纯黑 (0, 0, 0)depth = 0该像素没有测到有效深度
深灰 (40, 40, 40)depth > 量程上限测到了,但超出设定的分析范围
其他颜色0 < depth ≤ 量程上限正常数据,颜色即距离

把没测到和测到但太远这两种情况用不同方式标示,排查时可以直接区分二者。

2.3 三个典型特征

近处细节多,远处变糊。 深度精度通常会随距离增加而下降;双目方案的深度误差常随距离近似平方增长,其他路线也会受到信噪比和反射强度影响。这属于成像边界,不一定是产品缺陷。同一个平面在近处可能只有毫米级起伏,到了远处则可能扩大到厘米级,具体数值以型号规格和实测为准。

黑洞。 图 2(c) 标出三类原因:超出有效量程、被遮挡,光线去不了或回不来、镜面和圆柱面反光,光反射到其他方向去了。玻璃、镜面、黑色吸光材质同样会大面积失效。深度图有空洞是常态,没有空洞反而值得检查。

边缘毛刺。 物体轮廓处常有飞点或拖尾,原因是一个像素的视野里同时包含了前景和背景,算法只能给出折中值。中值滤波、双边滤波可以压掉一部分。

拿到任何一台新相机,先对着白墙、纸箱、自己的手、显示器屏、玻璃窗各拍一张深度图。能看出这五样东西的差别,基本就摸清了这台设备的工作边界。


05 / DOCUMENTATION

灰度深度图与彩色深度图

Community Wiki

上一节说明如何读图,这一节说明两种图各自的用途。这是实际工作中最常见的选择。

灰度深度图彩色深度图
数据本质原始测量值,本文为 16 位,单位 mm同一数据的着色版本,8 位三通道
位深16 位,0 至 65535 mm 无损8 位,颜色被量化成 256 级
精度损失无有,且不可逆
优点保留全部数值,可直接参与计算距离分层直观,色差敏感,适合汇报
缺点灰阶分辨力低,远距层次看不出颜色是映射结果,不能当作数据使用
适合场景算法输入、测量、点云生成、存档调试预览、写文档、汇报演示、快速判读

3.1 分工原则

机器计算用 16 位灰度数据,人眼判读用彩色图。

这个分工有具体的数值依据。16 位灰度图每个像素可以表达 0 至 65535 共 65536 个距离值,转成 8 位彩色后只剩 256 级,一个颜色台阶对应约 23 mm 的距离差。用彩色图做测量,精度只能到厘米级;用原始 16 位数据,理论上可以到毫米级。

因此彩色图只承担显示职责,不回写到算法流程中。

3.2 彩色深度图的典型用途

  • 快速判断数据是否正常:检查视野里有没有大片黑洞、量程设置是否正确。
  • 分层与分割:颜色跳变处往往就是物体边界,手动框选和调参时更直观。
  • 向他人解释深度数据:一张彩色深度图比一堆数字更容易讲清,汇报和写文档都适用。
  • 多帧比对:固定量程下,两帧之间的色差用眼睛就能捕捉到。

3.3 灰度深度图的典型用途

  • 生成点云:需要真实毫米值,见第 4 节。
  • 距离测量与阈值分割:depth[(depth > 500) & (depth < 800)] 这类操作只能在数值上做,不能在颜色上做。
  • 图像存档与复现:存 16 位 PNG 是无损的,他人拿到可以算出相同结果。存成 JPG 或截图,数据就失效了。

用截图工具截下彩色深度图放进报告,然后注明某处深 2.5 米,这种写法有问题。截图里只有颜色,没有毫米值。要报数,就报从原始数据里读出来的数。


06 / DOCUMENTATION

从深度图到三维坐标

Community Wiki

深度图配合相机内参,可以反算出三维坐标。点云、三维重建、位姿估计、抓取规划都从这里开始。

针孔相机模型与反投影公式
针孔相机模型与反投影公式

图 3:一个物点 P 投影到像素 (u, v);知道该像素的深度 Z 与内参,就能反算回 P 的三维坐标。

代码块
纯文本
X = (u - cx) * Z / fxY = (v - cy) * Z / fyZ = depth(u, v)

其中 fx fy cx cy 是内参,即焦距与主点,由出厂标定给出,SDK 提供读取接口。实际使用时注意三点:

  1. 光心指向场景的方向是 Z,图像平面上的偏移量需要按焦距换算回物理尺度;
  2. 内参不准会导致点云整体拉伸或偏移,使用前应读取并核对,不要假设为标准值;
  3. 对每个像素执行一遍,得到的结果就是点云。

点数估算:1600×1200 的深度图,即使有效像素只有 80%,单帧也有约 150 万个三维点。这对算力有要求,实际项目通常先降采样再处理。


07 / DOCUMENTATION

三条主流技术路线

Community Wiki

三条路线回答的是同一个问题:如何测出光走过的距离。各自的物理原理不同,限制条件也不同。

三条技术路线的原理示意
三条技术路线的原理示意

图 4:结构光投射已知图案,观察图案变形;ToF 发射调制光,测量往返时间;双目用两台相机观察同一物体,由视差计算距离。

5.1 结构光(Structured Light)

原理:相机旁边有一个红外投射器,把一副已知图案打到物体表面,图案形式包括散斑、条纹、网格。图案遇到凹凸会变形,另一颗红外相机拍下变形后的图案,比对理论图案与实际图案的差异,反推每个点的深度。

类比:在一张布满格子的透明纸上,格子弯了,就知道对应位置有起伏。

优势:近距离精度高,分辨率高,成本低,模组体积可以做到很小。

软肋:怕强光。太阳光里的红外成分会淹没投射图案,户外基本失效。怕镜面与透明物。测量距离通常限制在数米以内,工作距离越远,投射图案在物体表面越稀疏,精度下降越快。

代表:Orbbec Astra 2、Astra Mini Pro 系列。

5.2 飞行时间(ToF, Time of Flight)

原理:向场景发射调制过的红外光,测量光从发出到反射回来所需时间或相位差,乘以光速再除以二,得到距离。整幅画面同时曝光,一次得到全场景深度。

类比:与蝙蝠回声定位同原理,把声波换成光。

优势:测距快,抗纹理干扰,白墙、纯色表面、弱光环境都能稳定出图。作用距离比结构光远,帧率高,适合动态场景。

软肋:空间分辨率偏低,因为每个像素都要独立计时,像素尺寸难以做小。存在多路径干扰,光在角落和凹槽里多次弹射后才回到相机,会算出偏远的结果。镜面反射直接失效。工作距离与视场角互相牵制,要覆盖大范围就得牺牲测量距离,见第 7.1 节。

代表:Orbbec Femto 系列,包括 Femto Bolt、Femto Mega、Femto Mega I,基于 Microsoft iToF 技术。

5.3 双目立体视觉(Stereo Vision)

原理:用两颗相机间隔一段固定距离同时拍摄同一场景,这段距离称为基线。同一个物体在两幅图中的位置有偏移,偏移量称为视差,距离越近视差越大。根据三角测量原理,用视差和基线即可算出距离。

代码块
纯文本
Z = f * B / d

其中 f 为焦距,B 为基线,d 为视差。

类比:人用两只眼睛判断远近,依据的就是视差。

优势:被动方案不主动发射红外光,多台设备同时工作互不干扰。基线越长,远距离精度越好。既可以在室外阳光下被动工作,也可以在弱光下开启红外投射,转为主动双目。

软肋:极度依赖纹理。白墙、玻璃、光滑表面这类无纹理区域,两幅图里找不到可匹配的特征点,深度会缺失。对两个镜头的标定精度要求极高,轻微形变就会导致深度整体漂移。

代表:Orbbec Gemini 330 系列,包括 Gemini 335、335L、335Le,基于 MX6800 ASIC,主动与被动结合,IP65,室内外可用;Gemini 2 系列为主动双目,适用于室内与半室外。

5.4 三条路线对比

维度结构光ToF双目立体视觉
是否主动发光是,红外图案是,调制红外可被动,也可主动加投射
典型工作距离(按具体型号)0.6 至 8 m(Astra 2)0.25 至 5.46 m,随模式变化0.15 至 10 m(Gemini 2)/ 0.17 至 20 m+(Gemini 335L)
近距离精度★★★★★★★
远距离表现★★★★★★,长基线更佳
空间分辨率★★★★★★★★
室外强光★,失效★★★★★,被动模式可用
弱光与无光★★★★★★★,需主动模式
无纹理表面★★★★★★★,失效
镜面与透明物★★★
多机同时使用需分时或调频需分时或调频★★★,被动模式互不干扰
成本低中中

星级仅表示定性趋势,用于快速建立直觉。具体型号的数值以官方数据手册为准。


08 / DOCUMENTATION

场景反推选型

Community Wiki

选型的起点是场景,型号放在后面。

场景反推选型流程
场景反推选型流程

图 5:三条问句先缩小到一条技术路线,最后再回到具体型号的模式表。

你的场景特征优先考虑原因
室内、近距离(小于 2 m)、需要看清细节结构光近距精度与分辨率最优,成本最低
需要识别手势、人体骨架、动作ToF抗纹理干扰,帧率高,动态捕捉稳
户外或阳光直射环境双目被动模式结构光与 ToF 的红外会被日光淹没
全黑环境或夜间作业结构光或 ToF自带红外照明,不依赖环境光
以白墙、纯色地面为主的空间结构光或 ToF双目在无纹理区域会大面积缺少深度
需要多台相机同时覆盖同一区域双目被动模式无主动光源,多机之间不会互相干扰
远距离(大于 5 m)避障双目,长基线精度随基线增加,远距衰减更慢
机械臂精细抓取(小于 1 m)结构光或 ToF近距离精度是首要指标
玻璃、镜面、抛光金属占比高无理想方案三者都受限,需改用其他传感手段或增加辅助措施
亚毫米级尺寸测量不属于本类产品需工业级 3D 扫描或激光轮廓仪

两条特征冲突时的优先级:环境光、距离、纹理条件、分辨率、成本。环境光决定能否出图,优先级最高;分辨率与成本可以权衡。


09 / DOCUMENTATION

Orbbec 产品线速查

Community Wiki

本节回答一个问题:三条技术路线各自对应 Orbbec 的哪些型号。因此只列路线、型号与关键规格,完整规格表、包装清单、SDK 文档和购买链接跳转官方页面。选方向看这里,确认细节看官方页。

下表数值全部取自 Orbbec 官网产品页规格栏,并附原文出处。

型号技术路线关键规格(官网原文口径)定位官方出处
Astra 2结构光0.6 至 8 m;深度 1600×1200@30fps;FOV H58.2° V45.2°;RGB 1920×1080@30fps;室内,0 至 35°C;精度 ≤0.16% @1m室内近距、高分辨率,性价比首选产品页
Femto BoltToF(iToF)0.25 至 5.46 m,随模式变化;深度 1024×1024@15fps(WFOV)或 640×576@30fps(NFOV);FOV 120°×120°(WFOV)或 75°×65°(NFOV);RGB 3840×2160@30fps与 Azure Kinect DK 模式兼容,存量项目迁移友好产品页
Femto MegaToF(iToF)同 Femto Bolt 的深度规格;内置 NVIDIA Jetson Nano;RGB 4K 最高 25fps;支持 PoE 与以太网自带算力与网口,适合远端部署与多机同步产品页
Gemini 335 / 335L双目(主动加被动)0.17 至 20 m+,最佳 0.25 至 6 m;深度 1280×800@30fps;FOV H90° V65°;IP65,−10 至 50°C,室内外通用AMR、机械臂、人形机器人的主流选择产品页
Gemini 2主动双目(Active Stereo IR)0.15 至 10 m;深度 1280×800@30fps;FOV H91° V66°;RGB 1920×1080@30fps;室内与半室外上一代紧凑双目,存量项目与教程较多产品页

7.1 深度模式对照表

ToF 的工作距离与视场角是绑定关系,不能拆开看。以 Femto 系列为例:

深度模式分辨率视场角工作距离
NFOV 非装箱640×57675°×65°0.5 至 3.86 m
NFOV 2×2 装箱320×28875°×65°0.5 至 5.46 m
WFOV 2×2 装箱512×512120°×120°0.25 至 2.88 m
WFOV 非装箱1024×1024120°×120°0.25 至 2.21 m

宣传语里的 5.46 m 只在 320×288 的低分辨率窄视场模式下成立。需要 120° 大视场时,最远只能到 2.21 至 2.88 m。选型时应查实际要跑的那个模式所在行的数字,不要采用产品标题上的最大值。

数据来源:Orbbec 官方文档《Femto Mega Hardware Specifications》,更新于 2025-09-15。

一个估算方法:尚未确定模式时,先按 NFOV 加 2×2 装箱,也就是 5.46 m 这一档估算距离,这是 ToF 方案里距离与视场比较均衡的配置;确实需要大范围覆盖时再切到 WFOV,并把距离预期减半。

7.2 软件与生态

  • Orbbec SDK v2:官方跨平台 SDK,支持 Windows、Linux、Android,提供深度、彩色、IR、IMU 等数据流,以及对齐、点云等后处理能力。
  • ROS2 驱动:官方提供 OrbbecSDK_ROS2 驱动包,可发布深度、彩色、点云、相机内参等话题。
  • 算力平台:Jetson 系列(Orin Nano、Orin NX 等)与 x86 笔记本均已验证。
  • 安装与接入步骤:见本系列后续文章《如何安装并使用奥比中光官方软件》与《在我的机器人中如何接入深度相机(ROS2)》。

10 / DOCUMENTATION

典型应用场景

Community Wiki

深度相机开启的是空间交互类应用,与普通摄像头的用途有明显区分。业界已经验证的成熟方向大致分四类。

感知与导航:AGV 与 AMR 的障碍物检测、地形分析,机器人自主导航建图配合 SLAM,无人机避障。

操作与抓取:机械臂的目标定位与 6D 位姿估计,无序抓取,协作机器人的安全区监控。这类应用对近距离精度要求较高。

重建与测量:房间与物体的三维重建,体积测量用于物流计费,人体尺寸测量,AR 与 VR 场景锚定。

人机交互:手势识别、体感游戏、人体骨架跟踪、人脸活体检测用于防照片和屏幕攻击、动作捕捉。

想了解这类设备能做什么,可以直接看实际运行的项目。Orbbec 官方与 SeedStudio、AIFITLAB 等生态伙伴的 wiki 上有大量可复现教程,覆盖房间重建、手语识别等方向。


11 / DOCUMENTATION

常见失效原因

Community Wiki

90% 的相机故障报告,实际原因是场景超出了设备的物理边界。下表按现象列出常见原因与处理办法。

现象常见原因应对
整幅深度图全黑或全是 0曝光被日光压制;驱动未正常初始化;深度流未使能遮光重测;检查设备枚举;确认 SDK 中深度流配置
存下来的图几乎全黑深度流刚启动时前几帧数据不完整,或读到的是压缩帧等有效像素占比稳定后再保存,见附录 D 第 3 条
大片区域无深度玻璃、镜面、黑色吸光材质、超出量程、被遮挡换角度避开反射;缩短距离;贴漫反射胶带
彩色深度图近处一片黑或一片红伪彩量程设得太小,或按全图最大值归一化固定量程,超量程单独涂色,见第 2.2 节
户外完全不可用结构光被太阳光淹没改用双目方案,或加装遮光罩并降低工作距离
同样的表面,深度时好时坏环境光变化;自动曝光在调整固定曝光时间,关闭自动曝光;稳定光源
深度整体偏移几厘米标定漂移;温度变化;镜头有污渍清洁镜头;预热 5 至 10 分钟后重测;必要时重新标定
物体边缘出现飞点或拖尾前景与背景混在同一像素视场内属正常现象,用中值滤波、双边滤波或时域滤波处理
多台相机互相干扰主动光源频率冲突错开调制频率;分时曝光;或改用被动双目
点云与彩色图错位D2C 对齐未开启,或该型号不支持在 SDK 中开启对齐;核对两图分辨率;详见附录 E
Jetson 上帧率上不去USB 带宽不足;未使用 USB 3.0 接口换 USB 3.0 口;降低分辨率或帧率;避免经过 hub
深度图分辨率看着很方深度传感器原生分辨率低,被上采样插值正常现象,看原生分辨率而非输出尺寸

排查顺序固定为:场景、光线、距离、接线、驱动、硬件。先检查环境,最后再怀疑设备。


12 / DOCUMENTATION

上手路径

Community Wiki

搞清楚是什么之后,接下来只有两步,按顺序走即可。

第一步 · 让相机出图

装好 Orbbec SDK 与官方查看器,先在桌面环境里看到正常的深度图与彩色图。这一步的重点是确认能稳定取到数值,效果好坏可以后面再调。附录 B 的脚本可以直接使用。 → 《安装并使用奥比中光官方软件》

第二步 · 接进机器人

用鱼香 ROS 安装 Desktop 版 ROS2,编译官方 OrbbecSDK_ROS2 驱动包,在 RViz2 里看到深度点云,并确认话题名称与坐标系。 → 《在机器人中接入奥比中光深度相机(ROS 2)》

两步跑通之后,再看具体项目的教程,包括重建、抓取、体感、检测,会发现它们都只是在这两步之上叠加算法。


13 / DOCUMENTATION

术语表

Community Wiki

术语英文含义
深度图Depth Map逐像素记录到相机距离的二维数组,单位通常为 mm
灰度深度图Grayscale Depth深度数据的直接可视化,越近越亮,保留完整数值
彩色深度图Colored / Pseudo-color Depth同一份数据按色带着色,便于人眼判读
色带Colormap把数值映射成颜色的规则,常见 JET、VIRIDIS
量程Range伪彩映射覆盖的距离区间,如 0 至 6000 mm
点云Point Cloud由深度图与内参反算出的三维点集合
内参Intrinsics焦距、主点、畸变系数等描述相机成像几何的参数
外参Extrinsics描述两个传感器之间的相对位姿
基线Baseline双目方案中两颗相机光心之间的距离
视差Disparity同一物点在左右图中像素位置的偏移量
D2CDepth to Color把深度图对齐到彩色图坐标系
iToFindirect ToF通过测量调制光的相位差间接计算飞行时间
FOVField of View视场角,分水平、垂直、对角
飞点Flying Pixels物体边缘处错误的三维点
多路径干扰Multi-path Interference光经多次反射后返回,导致测得距离偏大
主动与被动Active / Passive是否主动发射光信号参与测量

14 / DOCUMENTATION

参考资料与复核记录

Community Wiki

主要依据

来源链接用于本文哪些内容
Orbbec 官网 · Astra 2 产品页orbbec.com/products/structured-light-camera/astra-2Astra 2 的距离、分辨率、FOV、精度、工作环境
Orbbec 官网 · Femto Bolt 产品页orbbec.com/products/tof-camera/femto-boltFemto Bolt 规格与误差定义
Orbbec 官网 · Femto Mega 产品页orbbec.com/products/tof-camera/femto-megaFemto Mega 规格与 Jetson 内置
Orbbec 官方文档 · Femto Mega Hardware Specificationsdoc.orbbec.com,更新于 2025-09-15第 7.1 节四种深度模式的对照表
Orbbec 官网 · Gemini 335L 产品页orbbec.com/products/stereo-vision-camera/gemini-335lGemini 335 与 335L 规格、IP65、MX6800
Orbbec 官网 · Gemini 2 产品页orbbec.com/products/stereo-vision-camera/gemini-2Gemini 2 规格
Orbbec 技术文章 · The Performance Metrics of 3D Vision Technologiesorbbec.com/?p=37264精度、重复性、帧率、延迟、多机干扰等指标定义
Orbbec 技术文章 · Integrated 3D Vision Systemsorbbec.com/blog/integrated-3d-vision-systems三条技术路线的原理与适用场景划分
AIFITLAB Wikiwiki.aifitlab.com栏目结构与品牌、产品、Quick start 分级参考
SeedStudio Wikiwiki.seedstudio.com产品 wiki 页的章节组织方式参考

文中数值的使用说明

  1. 所有具体参数均取自官方来源,未使用第三方博客、电商页或媒体转载的数值。
  2. 数值用于说明技术路线的量级差异与选型方向,不构成选型承诺或性能保证。
  3. 参数随固件版本与工作模式变化,实际选型以官方最新数据手册和手上设备的实测结果为准。
  4. 本文实拍图见第 2、3 节,由作者用 Orbbec Astra 2 在实验室采集,参数见附录 B。
  5. 若本文数值与官方页面出现出入,以官方页面为准,并请通过下方反馈渠道告知修正。

15 / DOCUMENTATION

附录 A:图片索引

Community Wiki

图号所在章节内容原始文件
图 12.1 一次实拍同一帧的灰度深度图与彩色深度图并排,三处无数据区域用圆圈标出fig_gray_vs_color.png
图 22.2 彩色热度图的读数规则左为 JET 色带与量程标尺,右为同一帧中三类黑洞的成因标注fig_depth_reading.png
图 34. 从深度图到三维坐标针孔相机模型,展示物点、像素与反投影公式的关系fig_pinhole.png
图 45. 三条主流技术路线结构光、ToF、双目三者的原理示意fig_three_routes.png
图 56. 场景反推选型由场景特征逐步缩小到技术路线的判断流程fig_select_flow.png
图 6附录 B 原始采集图彩色图,1280 × 720color.png
图 7附录 B 原始采集图伪彩深度图,1600 × 1200depth_color.png
图 8附录 B 原始采集图16 位灰度深度图,1600 × 1200depth_gray.png

图 1 与图 2 中的实拍画面来自同一帧深度数据,原始输出见图 6 至图 8,采集条件见附录 B。图 3 至图 5 为示意图,由程序绘制。


16 / DOCUMENTATION

附录 B:实拍样张与采集参数

Community Wiki

第 2、3 节的图来自以下这次采集,参数可复现。

项目数值
设备Orbbec Astra 2
深度分辨率1600 × 1200
彩色分辨率1280 × 720
深度格式Y16,16 位,单位 mm
伪彩量程0 至 6000 mm,JET
有效深度像素占比80.7%
6 m 以内像素占比61.4%
深度范围516 mm 至 16616 mm
深度中位数2386 mm
D2C 对齐未做,见附录 E
场景实验室工位:前台面与保温杯为前景,右侧白色货架为中景,后方实验室纵深为远景

原始采集图

以下三张为本次采集输出。图 1 由深度数据的灰度显示版与伪彩显示版合成;浏览器预览 16 位 depth_gray.png 时可能显得很暗,这是显示方式造成的,原始毫米值仍保存在文件中。

彩色图,1280 × 720,对应 Astra 2 的 RGB 输出:

本次采集的彩色图
本次采集的彩色图

伪彩深度图,1600 × 1200,量程 0 至 6000 mm:

本次采集的伪彩深度图
本次采集的伪彩深度图

16 位灰度深度图,1600 × 1200,像素值即毫米数,此处为便于观看做了亮度拉伸:

本次采集的 16 位灰度深度图
本次采集的 16 位灰度深度图

原始数据请保留 16 位灰度版本。彩色图和截图都无法还原毫米值,原始文件一旦丢失,这组数据只能看不能用。上图的亮度经过拉伸,不能用于读取距离。


17 / DOCUMENTATION

附录 C:采集脚本

Community Wiki

两个版本。精简版适合第一次跑通,完整版是本文所有实拍图的生成脚本。

依赖:pip install pyorbbecsdk2 opencv-python numpy

C.1 精简版

代码块
Python
import cv2import numpy as npimport pyorbbecsdk as ob
ctx = ob.Context()dev = ctx.query_devices().get_device_by_index(0)pipe = ob.Pipeline(dev)cfg = ob.Config()cfg.enable_stream(ob.OBStreamType.DEPTH_STREAM)cfg.enable_stream(ob.OBStreamType.COLOR_STREAM)pipe.start(cfg)
for _ in range(200):    frames = pipe.wait_for_frames(1000)    if frames is None:        continue    depth_frame = frames.get_depth_frame()    color_frame = frames.get_color_frame()    if depth_frame is None or color_frame is None:        continue
    # Astra 2 启动前几帧是 RLE 压缩,必须等到 Y16 才有完整深度    if depth_frame.get_format() != ob.OBFormat.Y16:        continue
    w, h = depth_frame.get_width(), depth_frame.get_height()    raw = np.frombuffer(depth_frame.get_data(), dtype=np.uint16)    if raw.size != w * h:        continue    depth_mm = raw.reshape(h, w)          # 单位:毫米
    # 伪彩:固定 6 m 量程,近处暖、远处冷,无效涂黑、超量程涂深灰    MAX_MM = 6000    norm = 255 - (np.clip(depth_mm, 0, MAX_MM) / MAX_MM * 255).astype(np.uint8)    depth_vis = cv2.applyColorMap(norm, cv2.COLORMAP_JET)    depth_vis[depth_mm == 0] = (0, 0, 0)    depth_vis[depth_mm > MAX_MM] = (40, 40, 40)
    # 彩色图,Astra 2 默认输出 MJPG 或 YUYV    cw, ch = color_frame.get_width(), color_frame.get_height()    buf = np.frombuffer(color_frame.get_data(), dtype=np.uint8)    if color_frame.get_format() == ob.OBFormat.MJPG:        color = cv2.imdecode(buf, cv2.IMREAD_COLOR)    else:        color = cv2.cvtColor(buf.reshape(ch, cw, 2), cv2.COLOR_YUV2BGR_YUYV)
    cv2.imwrite("color.png", color)    cv2.imwrite("depth_color.png", depth_vis)    cv2.imwrite("depth_gray.png", depth_mm)   # 16 位,保留原始毫米值    break
pipe.stop()

C.2 完整版

相比精简版,增加了异常处理、启动等待、参数快照和交互保存。

代码块
Python
"""capture_depth_color.py读取 Orbbec 相机,保存灰度深度图与彩色图。依赖:pip install pyorbbecsdk2 opencv-python numpy输出:depth_gray.png(16位) / depth_color.png(伪彩) / color.png / meta.txt"""
import os, sys, datetimeimport cv2import numpy as npimport pyorbbecsdk as ob
SAVE_DIR = "output"

def depth_to_color(depth_mm, max_mm=6000):    """毫米深度 -> 伪彩图。近处暖色、超出量程深灰、无效深度纯黑。"""    clipped = np.clip(depth_mm.astype(np.float32), 0, max_mm)    norm = 255 - (clipped / max_mm * 255).astype(np.uint8)    color = cv2.applyColorMap(norm, cv2.COLORMAP_JET)    color[depth_mm == 0] = (0, 0, 0)          # 测不到    color[depth_mm > max_mm] = (40, 40, 40)    # 超出量程    return color

def frame_to_bgr(frame):    """彩色帧 -> BGR,兼容 MJPG / YUYV / UYVY / RGB / BGR / RGBA / BGRA。"""    w, h = frame.get_width(), frame.get_height()    fmt = frame.get_format()    data = np.frombuffer(frame.get_data(), dtype=np.uint8)    if fmt == ob.OBFormat.RGB:        return cv2.cvtColor(data.reshape(h, w, 3), cv2.COLOR_RGB2BGR)    if fmt == ob.OBFormat.BGR:        return data.reshape(h, w, 3).copy()    if fmt == ob.OBFormat.RGBA:        return cv2.cvtColor(data.reshape(h, w, 4), cv2.COLOR_RGBA2BGR)    if fmt == ob.OBFormat.BGRA:        return cv2.cvtColor(data.reshape(h, w, 4), cv2.COLOR_BGRA2BGR)    if fmt == ob.OBFormat.YUYV:        return cv2.cvtColor(data.reshape(h, w, 2), cv2.COLOR_YUV2BGR_YUYV)    if fmt == ob.OBFormat.UYVY:        return cv2.cvtColor(data.reshape(h, w, 2), cv2.COLOR_YUV2BGR_UYVY)    if fmt == ob.OBFormat.MJPG:        return cv2.imdecode(data, cv2.IMREAD_COLOR)    raise RuntimeError(f"不支持的彩色格式:{fmt}")

def depth_to_mm(frame):    """深度帧 -> uint16 毫米数组。非 Y16 帧返回 None(跳过)。"""    if frame.get_format() != ob.OBFormat.Y16:        return None    w, h = frame.get_width(), frame.get_height()    raw = np.frombuffer(frame.get_data(), dtype=np.uint16)    if raw.size != w * h:        return None    depth = raw.reshape(h, w)    scale = frame.get_depth_scale()    if scale and abs(scale - 1.0) > 1e-6:        depth = (depth.astype(np.float32) * scale).astype(np.uint16)    return depth

def save_all(color, depth, dvis, info):    os.makedirs(SAVE_DIR, exist_ok=True)    cv2.imwrite(f"{SAVE_DIR}/color.png", color)    cv2.imwrite(f"{SAVE_DIR}/depth_gray.png", depth)     # 16 位原始值    cv2.imwrite(f"{SAVE_DIR}/depth_color.png", dvis)
    valid = depth[depth > 0]    with open(f"{SAVE_DIR}/meta.txt", "w", encoding="utf-8") as f:        f.write(f"采集时间: {datetime.datetime.now():%Y-%m-%d %H:%M:%S}n")        f.write(f"设备: {info.get_name()}n")        f.write(f"序列号: {info.get_serial_number()}n")        f.write(f"固件: {info.get_firmware_version()}n")        f.write(f"深度尺寸: {depth.shape[1]}x{depth.shape[0]}n")        f.write(f"彩色尺寸: {color.shape[1]}x{color.shape[0]}n")        f.write(f"有效深度占比: {valid.size / depth.size * 100:.1f}%n")        if valid.size:            f.write(f"深度范围: {valid.min()} ~ {valid.max()} mmn")    print(f"[已保存] 4 个文件 -> {os.path.abspath(SAVE_DIR)}")

def main():    ctx = ob.Context()    devs = ctx.query_devices()    if devs.get_count() < 1:        print("未检测到设备")        return 1
    dev = devs.get_device_by_index(0)    info = dev.get_device_info()    print(f"已连接:{info.get_name()}  SN={info.get_serial_number()}")
    pipe = ob.Pipeline(dev)    cfg = ob.Config()    cfg.enable_stream(ob.OBStreamType.DEPTH_STREAM)    cfg.enable_stream(ob.OBStreamType.COLOR_STREAM)    pipe.start(cfg)
    stable = 0    try:        while True:            fs = pipe.wait_for_frames(1000)            if fs is None:                continue            df, cf = fs.get_depth_frame(), fs.get_color_frame()            if df is None or cf is None:                continue
            depth = depth_to_mm(df)            if depth is None:                continue                      # RLE 帧,跳过
            ratio = (depth > 0).sum() / depth.size * 100            if ratio > 30:                stable += 1
            color = frame_to_bgr(cf)            dvis = depth_to_color(depth)
            cv2.imshow(f"color | depth (valid {ratio:.1f}%)",                       np.hstack([                           cv2.resize(color, (640, 360)),                           cv2.resize(dvis, (640, 480))[:360]                       ]))
            # 等稳定 10 帧再存,避开启动时的不完整帧            if stable == 10:                save_all(color, depth, dvis, info)                print("按 s 再存,按 q 退出")
            k = cv2.waitKey(1) & 0xFF            if k == ord("q"):                break            if k == ord("s") and ratio > 10:                save_all(color, depth, dvis, info)    finally:        pipe.stop()        cv2.destroyAllWindows()    return 0

if __name__ == "__main__":    sys.exit(main())

C.3 自己生成灰度与彩色对比图

需要做成图 1 那样的并排对比,在拿到 depth_mm 后加几行即可:

代码块
Python
MAX_MM = 6000
# 灰度版:近处亮、远处暗grey = 255 - (np.clip(depth_mm, 0, MAX_MM) / MAX_MM * 255).astype(np.uint8)grey[depth_mm == 0] = 0grey[depth_mm > MAX_MM] = 40
# 彩色版:同一份 grey 套色带color_depth = cv2.applyColorMap(grey, cv2.COLORMAP_JET)
cv2.imwrite("depth_gray_view.png", grey)         # 8 位,仅用于显示cv2.imwrite("depth_color.png", color_depth)      # 8 位三通道

这里有两个名字相近的灰度文件:depth_gray.png 为 16 位,存毫米值,用来计算;depth_gray_view.png 为 8 位,存拉伸后的亮度,用来看。


18 / DOCUMENTATION

附录 D:实机踩坑记录

Community Wiki

以下 6 条均为实测结果,设备为 Orbbec Astra 2,固件 2.8.20,pyorbbecsdk 2.9.3。

现象真实原因解法
cannot reshape array of size 552422启动前几帧是 RLE 压缩视差图,不是 Y16检测 get_format() != Y16 就跳过,等它自行切换
用 FormatConverter 转换后拿不到毫米值该过滤器把深度渲染成 3 通道彩色图像,convertType 取 0 至 21 结果都相同不使用转换器,直接等待 Y16 帧
存下来的深度图几乎全黑Y16 刚切换后的十几帧数据不完整,有效率仅 1% 至 2%等有效率超过 30% 且连续稳定 10 帧再保存
彩色深度图近处物体一片黑伪彩按全图最大值归一化,近景被压到色带底端固定量程,例如 6 m;超量程涂深灰,无效涂黑
HResult 0xc00d3704 硬件 MFT 启动流式传输失败相机被其他进程占用,例如预览窗口未关闭关闭占用进程后重试
预览里彩色图被拉伸变形彩色 1280×720 为 16:9,深度 1600×1200 为 4:3,宽高比不同按高度等比缩放后拼接,不要强行拉满

第一条影响最大。Astra 2 的深度流在启动后前 2 帧格式为 OBFormat.RLE,是压缩视差数据,只有几十 KB;第 3 帧起自动切换为 OBFormat.Y16,尺寸 1600×1200×2 即 3,840,000 字节。本文记录的所有 reshape 报错和全黑图,根源都在这里。


19 / DOCUMENTATION

附录 E:关于 D2C 对齐

Community Wiki

本文的实拍图未做深度到彩色(D2C)的对齐,两图视野不同,不能像素级对应。在 Astra 2 上的实测结果如下:

  • config.set_align_mode(OBAlignMode.SW_MODE) 不生效,深度输出仍为 1600×1200,彩色为 1280×720
  • 改用独立的 Align 过滤器可以把深度转到 1280×720,但会报 Unsupported format for C2D conversion,或导致有效像素骤降至 4.4%
  • get_camera_param() 返回的内参为全 0,无法手工配准

如果需要彩色与深度精确叠加,例如做彩色点云或物体分色渲染,需换用支持的型号,或在应用层自行完成配准。

不过,说明数据本身长什么样并不需要对这两颗镜头做对齐。本文对比灰度与彩色两种呈现方式,用的是同一份深度数据,两种画法逐像素对应。


20 / SUPPORT

讨论、纠错与持续维护

Forum / GitHub / Community