1. 为什么D435i到现在还是深度相机里的“真香”选择
搞了几年机器人视觉和三维重建,我经手的深度相机少说也有七八款,从结构光到ToF再到双目立体视觉,兜兜转转一圈回来,发现实验室里出镜率最高的还是Intel RealSense D435i。这玩意儿2018年发布,放到今天参数已经不算亮眼,但你在GitHub上翻一圈开源项目,从机械臂抓取到SLAM建图,从体积测量到手势交互,D435i的出场率依然碾压一众后来者。原因不复杂:它把双目立体视觉、主动红外投射、IMU惯性单元塞进了一个巴掌大的铝合金壳子里,而且SDK成熟、跨平台支持好、社区踩坑记录足够多。你遇到的大部分问题,前人都遇到过并且留下了解决方案,这对工程落地来说比参数表上的几个数字重要得多。
但“用的人多”和“用得顺手”是两码事。我见过太多团队兴冲冲买回来,插上USB跑个realsense-viewer觉得效果不错,一到自己写代码集成就各种翻车:深度图空洞一大片、点云飘得没法看、跑着跑着USB断连、ARM平台上编译报错、标定完精度反而更差了。这些问题很少是相机本身坏了,绝大多数是对它的硬件特性理解不到位,加上参数配置没有根据实际场景调优。这篇内容就是把我这几年在D435i上踩过的坑、调过的参数、验证过的方案系统性地梳理一遍,从硬件底层特性讲到具体场景的性能调优,再到标定和常见故障排查。不管你是刚拿到相机的新手,还是已经在项目里用了一段时间但效果不理想的开发者,应该都能从中找到可以直接抄作业的东西。
2. D435i硬件特性深度拆解:参数背后的真实含义
2.1 双目立体视觉+红外投射的工作原理
D435i的核心是一对红外双目相机,左右两个红外传感器基线距离50毫米,配合中间那个红外激光投射器工作。它的深度计算逻辑是标准的多视图立体匹配:左眼和右眼同时拍一张红外图,算法在两张图里找同名点,根据视差和基线距离算出深度。公式很简单,深度等于焦距乘以基线除以视差。基线固定50毫米,焦距由标定得到,所以深度精度直接取决于视差计算的准确度。
这里有个关键点很多人忽略:D435i的深度质量高度依赖被摄物体的纹理。双目匹配的本质是找特征点,如果面对一面白墙或者纯色桌面,左右图长得一模一样,算法根本找不到对应点,深度图就是一片空洞。这时候红外投射器就派上用场了,它往场景里打一层人眼不可见的红外散斑,人为制造纹理,让匹配算法有东西可抓。所以你在暗光或者低纹理场景下用D435i,一定要确保红外投射器是开着的。但反过来,如果场景本身纹理丰富、光照充足,投射器开着反而可能引入噪声,因为散斑图案会和物体本身的纹理叠加,干扰匹配。我一般建议在室外或者光照良好的室内把投射器功率调低甚至关闭,在暗光或白墙场景下再开高。
2.2 深度范围与精度的真实表现
官方标称D435i的深度范围是0.2米到10米,但这个数字有很强的误导性。0.2米是最小可测距离,实际在这个距离上深度噪声非常大,因为太近的话左右相机的视场重叠区域不够,匹配容易出错。10米是理论最大值,但在这个距离上深度误差可能达到几十厘米,基本没有实用价值。根据我的实测经验,D435i在0.5米到3米这个区间内表现最稳定,深度误差可以控制在1%到2%左右。3米到5米误差开始明显增大,5米以上就只能做定性参考了。
精度还和分辨率设置强相关。D435i支持多种深度分辨率,从424x240到1280x720。分辨率越高,同样视场下每个像素代表的实际角度越小,视差计算的精度理论上越高,但计算量也越大,帧率会下降。而且高分辨率下噪声也会增加,因为每个像素接收到的红外光能量减少了。我通常的做法是:做近距离高精度抓取时用848x480或1280x720,做远距离SLAM或者避障时用640x480甚至424x240,优先保证帧率。下面这张表是我在不同分辨率下实测的深度噪声和推荐场景,供你参考。
| 深度分辨率 | 帧率范围 | 0.5m处噪声 | 2m处噪声 | 推荐场景 |
|---|---|---|---|---|
| 424x240 | 6-90fps | ±3mm | ±15mm | 远距离避障、快速移动 |
| 640x480 | 6-90fps | ±2mm | ±10mm | SLAM、一般抓取 |
| 848x480 | 6-90fps | ±1.5mm | ±8mm | 精细抓取、体积测量 |
| 1280x720 | 6-30fps | ±1mm | ±6mm | 静态高精度重建 |
2.3 IMU单元的隐藏价值与使用陷阱
D435i比D435多了一个IMU,包含一个加速度计和一个陀螺仪。很多人买回来根本没用过这个IMU,觉得深度相机就好好做深度就行了。但在移动机器人或者手持扫描场景下,IMU的价值非常大。它可以在视觉跟踪丢失的时候提供短时间的位姿估计,也可以和视觉做松耦合或紧耦合的融合,提升SLAM系统的鲁棒性。特别是在快速旋转或者纹理缺失导致视觉跟踪失败的瞬间,IMU的角速度和加速度积分能撑住位姿估计不崩。
但IMU的使用有几个坑。第一,D435i的IMU和深度相机之间的外参需要标定,出厂值只是大概的,如果你要做紧耦合融合,必须自己标定IMU到相机的变换矩阵。第二,IMU的坐标系和相机坐标系不一致,加速度计和陀螺仪的轴向需要根据实际安装方向做旋转。第三,IMU的数据频率虽然高(加速度计和陀螺仪各250Hz),但噪声也不小,直接积分会快速漂移,必须做零偏校准和滤波。我一般建议用Kalibr或者imu_utils工具先做IMU的噪声模型标定,得到随机游走和零偏不稳定性参数,再喂给VIO算法。
2.4 接口与供电:USB线缆的玄学问题
D435i用USB Type-C接口,支持USB 3.0及以上。这里有一个被无数人吐槽过的问题:USB线缆的质量直接决定相机能不能稳定工作。我遇到过太多次,用一根看起来没问题的Type-C线,相机能枚举,realsense-viewer也能出图,但跑几分钟就断连,或者深度图时不时卡顿。换一根Intel原装线或者带屏蔽层的好线,问题立刻消失。原因在于D435i的深度计算和红外投射需要较大的瞬时电流,劣质线缆的压降会导致相机内部电压不稳,触发保护性断连。
另外,如果你用ARM平台(比如Jetson系列或者树莓派),USB控制器的兼容性也是个大坑。有些ARM板子的USB 3.0控制器对UVC协议的支持不完整,realsense-viewer能跑但自己写的程序调用SDK就报错。这种情况通常需要更新内核或者打USB补丁,具体方案我在后面的排查章节会详细说。供电方面,D435i可以从USB取电,但如果同时开高分辨率深度+RGB+IMU,功耗会超过USB 3.0的900mA上限,建议用带外部供电的USB Hub,或者直接用Y型线从两个USB口取电。
3. 开发环境搭建与SDK编译的实战细节
3.1 x86平台上的快速部署
在Ubuntu x86_64上部署RealSense SDK是最省心的路径。官方提供了apt源和预编译包,几条命令就能搞定。但这里有个版本选择的坑:librealsense的版本和内核版本、CUDA版本之间有兼容性矩阵。如果你用的是Ubuntu 20.04或者22.04,建议直接用官方apt源安装最新稳定版,不要自己从源码编译,除非你需要特定的补丁或者后端支持。
# 添加Intel RealSense apt源 sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE sudo add-apt-repository "deb https://librealsense.intel.com/Debian/apt-repo $(lsb_release -cs) main" sudo apt-get update sudo apt-get install librealsense2-dkms librealsense2-utils librealsense2-dev安装完成后,插上D435i,运行realsense-viewer,如果能看到深度流和RGB流,说明基础环境没问题。但要注意,librealsense2-dkms会编译内核模块,如果你后续升级了内核,需要重新运行sudo dpkg-reconfigure librealsense2-dkms来重新编译模块,否则相机会枚举失败。这个坑我踩过好几次,系统自动更新内核后相机突然不认了,排查半天才发现是DKMS模块没跟着更新。
3.2 ARM64平台编译的避坑要点
ARM平台是重灾区。Jetson Nano、Jetson Xavier NX、树莓派4B这些板子我都试过,编译librealsense的过程各有各的痛。首先,官方apt源只提供x86_64的包,ARM平台必须从源码编译。其次,ARM平台的CPU性能有限,完整编译librealsense可能需要30分钟到1小时,而且内存不足会导致编译中途OOM。Jetson Nano只有4GB内存,编译时建议开交换分区或者用-j2限制并行编译任务数。
# ARM平台源码编译librealsense git clone https://github.com/IntelRealSense/librealsense.git cd librealsense mkdir build && cd build cmake .. -DCMAKE_BUILD_TYPE=Release -DFORCE_RSUSB_BACKEND=ON -DBUILD_EXAMPLES=true make -j2 sudo make install这里的关键参数是-DFORCE_RSUSB_BACKEND=ON。在ARM平台上,内核的UVC驱动往往对RealSense的支持不完整,强制使用RSUSB后端可以绕过内核驱动,直接通过libusb访问相机。代价是CPU占用会高一些,但稳定性大幅提升。另外,如果你在Jetson上要用CUDA加速点云处理,还需要在cmake时加上-DBUILD_WITH_CUDA=ON,并确保CUDA路径正确。
还有一个ARM平台特有的问题:USB带宽。Jetson Nano的USB 3.0控制器带宽有限,同时开深度848x480@30fps和RGB 1920x1080@30fps可能会丢帧。解决办法是降低RGB分辨率或者帧率,或者只开深度流。如果你确实需要高分辨率RGB,可以考虑用MIPI CSI相机替代RGB模块,D435i只负责深度。
3.3 Python绑定的安装与版本匹配
很多做算法验证的同行喜欢用Python调D435i,pyrealsense2确实方便。但pip安装的pyrealsense2版本必须和系统里安装的librealsense版本匹配,否则会出现符号找不到或者运行时崩溃。我一般建议先确认系统librealsense版本,然后安装对应版本的pyrealsense2。
# 查看librealsense版本 rs-enumerate-devices --version # 安装匹配的pyrealsense2 pip install pyrealsense2==2.54.2.5684如果你在虚拟环境里用pyrealsense2,还要注意虚拟环境是否能访问系统的USB设备。有时候需要把当前用户加入plugdev组,或者配置udev规则,否则普通用户权限下相机枚举会失败。
# 添加udev规则 sudo cp config/99-realsense-libusb.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules && sudo udevadm trigger4. 深度图质量调优:从“能用”到“好用”的关键参数
4.1 深度预设模式的选择逻辑
librealsense提供了几套预设的深度参数配置,在realsense-viewer里可以直接切换。很多人不知道这个选项,或者随便选一个就不管了。实际上不同预设对深度图质量的影响非常大。默认预设是“Default”,适合大多数场景,但如果你做近距离高精度抓取,“High Accuracy”预设会更好,它会牺牲一些帧率和边缘响应速度来换取更平滑的深度图。“High Density”预设适合纹理丰富的场景,能保留更多细节但噪声也更大。“Medium Density”是折中方案。
我一般建议在realsense-viewer里把几个预设都试一遍,观察同一场景下深度图的空洞率、边缘锐度和噪声水平,找到最适合你场景的那个。选好之后,在代码里通过rs2::advanced_mode加载对应的JSON配置文件,或者直接设置rs2::sensor的选项值。注意,预设切换后需要几秒钟稳定,不要频繁切换。
4.2 激光投射器功率与深度单位
激光投射器功率(Laser Power)是D435i最关键的调优参数之一。默认值通常是150左右(范围0-360)。功率越高,投射的散斑越亮,在暗光或远距离下深度图越完整,但近距离下噪声也会增加,而且功耗和发热上升。我的经验是:0.3米到1米近距离用80-120,1米到3米用150-200,3米以上用250-300。如果场景光照充足且纹理丰富,可以直接关掉投射器(设为0),深度图反而更干净。
深度单位(Depth Units)决定了深度图里一个整数值代表多少米。默认是0.001米,也就是1毫米。如果你做远距离测量,深度值会很大,16位深度图最大只能表示65535,也就是65.535米,够用但精度浪费了。这时候可以把深度单位改成0.01米,量程扩大到655米,代价是精度降到1厘米。反过来,做近距离高精度测量时,可以把深度单位改成0.0001米,量程缩小到6.5米,但精度提升到0.1毫米。这个参数要根据你的实际工作距离来选,不要无脑用默认值。
4.3 深度图后处理滤波器的正确打开方式
librealsense提供了一套后处理滤波器,包括去噪、空洞填充、时域滤波等。这些滤波器用好了能大幅提升深度图质量,用不好反而会引入伪影和延迟。我逐个说一下我的使用心得。
Decimation Filter(降采样):把深度图分辨率降低,比如从848x480降到424x240。好处是减少计算量、降低噪声,坏处是丢失细节。我一般在点云生成前用一次,把深度图降到我需要的分辨率。
Spatial Filter(空间滤波):在空间域上平滑深度图,减少孤立噪声点。这个滤波器对边缘的保持还不错,但迭代次数多了会让边缘变模糊。我一般设2-3次迭代,平滑alpha设0.5左右。
Temporal Filter(时域滤波):利用前后帧的信息来稳定深度值,对静态场景效果很好,能显著减少深度图的闪烁。但如果你做动态场景或者相机在移动,时域滤波会引入拖影。我一般只在静态测量时开,移动场景关掉。
Hole Filling Filter(空洞填充):把深度图中的无效像素用周围的有效值填充。这个滤波器要慎用,因为它填充的值是估计出来的,不是真实测量值。做抓取的时候如果依赖填充后的深度,可能会抓空。我一般只在可视化的时候开,做实际计算时关掉。
Threshold Filter(阈值滤波):把超出指定距离范围的深度值置为无效。这个很有用,可以去掉背景干扰,只保留工作区域内的深度。比如你做传送带抓取,可以把阈值设成0.3米到1.5米,传送带以外的全部忽略。
滤波器的顺序也有讲究。我推荐的顺序是:Decimation -> Threshold -> Spatial -> Temporal -> Hole Filling。先降采样减少数据量,再阈值去掉无关区域,然后空间和时域滤波去噪,最后按需填充空洞。
4.4 深度图与RGB图的对齐
D435i的深度相机和RGB相机是分开的,物理位置不同,视场也不完全重合。如果你要把深度图的像素和RGB图的像素对应起来,必须做对齐(Align)。librealsense提供了rs2::align模块,可以把深度图对齐到RGB视角,或者把RGB对齐到深度视角。我一般建议把深度对齐到RGB,因为RGB分辨率更高,对齐后深度图会插值到RGB的分辨率,看起来更直观。
但要注意,对齐操作会引入额外的计算开销,而且对齐后的深度图边缘会有插值误差。如果你做的是像素级的精确测量,比如测量物体尺寸,最好直接用原始深度图,通过标定得到的内外参自己投影,不要用SDK的对齐功能。对齐功能适合可视化或者对精度要求不高的应用。
5. 相机标定:从入门到不翻车
5.1 为什么出厂标定不够用
D435i出厂时已经做了标定,内参和外参都存在相机里,SDK可以直接读取。很多人觉得这样就够了,不需要自己再标。但出厂标定是在标准环境下做的,你的实际使用场景可能和标准环境差异很大。比如你给相机加了外壳、装了滤镜、或者相机摔过一下,外参就可能变了。另外,出厂标定的精度对于一般应用够用,但如果你做高精度测量或者多相机融合,出厂标定的误差就不可忽略了。
我一般建议在以下几种情况下必须重新标定:相机受到过撞击或跌落;相机工作温度与标定时差异很大(比如从空调房拿到室外);需要亚毫米级测量精度;多相机系统中各相机之间的外参需要精确已知。其他情况下,出厂标定可以先跑起来,等发现精度不够再标。
5.2 内参标定的实操步骤
内参标定就是求相机的焦距、主点、畸变系数。D435i的深度相机和RGB相机需要分别标定。我常用的工具是OpenCV的calibrateCamera函数,配合棋盘格标定板。标定板的大小要根据工作距离选,近距离用小的,远距离用大的。一般建议标定板占画面1/3到1/2面积,在多个角度和距离下采集20-30张图像。
import cv2 import numpy as np # 棋盘格参数 pattern_size = (9, 6) square_size = 0.025 # 25mm # 准备对象点 objp = np.zeros((pattern_size[0]*pattern_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) objp *= square_size # 采集图像并检测角点 objpoints = [] imgpoints = [] for img_path in image_list: img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, pattern_size, None) if ret: corners_refined = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) objpoints.append(objp) imgpoints.append(corners_refined) # 标定 ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)标定完成后,用cv2.projectPoints把棋盘格角点重投影回图像,计算重投影误差。一般重投影误差小于0.5像素算合格,小于0.3像素算优秀。如果误差太大,检查标定板是否平整、图像是否模糊、角点检测是否准确。
5.3 深度与RGB外参标定
外参标定是求深度相机到RGB相机的旋转和平移矩阵。这个比内参标定麻烦一些,因为深度图的分辨率低、噪声大,直接检测棋盘格角点效果不好。我常用的方法是:先用RGB相机检测棋盘格角点,得到RGB下的角点坐标;然后在深度图上找到对应位置的深度值,反投影得到深度相机坐标系下的3D点;最后用cv2.solvePnP求两个坐标系之间的变换。
但深度图在棋盘格边缘往往有空洞,直接取深度值可能无效。我的技巧是:在棋盘格角点周围取一个小窗口,用窗口内有效深度的中值作为该角点的深度。如果窗口内有效点太少,就丢弃这个角点。一般采集20张以上图像,每张图检测到6个以上有效角点,就能得到稳定的外参。
标定完外参后,验证方法是:把深度图上的点用外参投影到RGB图像上,看是否和RGB图像中的对应点重合。如果偏差在几个像素以内,说明标定合格。
5.4 IMU标定与相机-IMU联合标定
如果你要用IMU做VIO,IMU本身的噪声参数和相机-IMU外参都必须标定。IMU噪声标定我推荐用imu_utils工具,把相机静止放置2小时以上,采集IMU数据,然后离线计算Allan方差,得到陀螺仪和加速度计的随机游走和零偏不稳定性参数。这个过程比较耗时,但标定一次可以用很久。
相机-IMU外参标定推荐用Kalibr工具。需要采集一段同时包含相机图像和IMU数据的rosbag,相机看着标定板做充分的激励运动(三个轴都要有旋转和平移)。Kalibr会同时优化相机内参、IMU噪声参数和相机-IMU外参。这个过程计算量很大,建议在x86机器上跑,ARM平台会很慢。
标定完成后,把结果写成YAML文件,喂给VIO算法(比如VINS-Mono、ORB-SLAM3)。如果VIO跑起来漂移很大或者初始化失败,大概率是标定参数不对,回去检查标定过程。
6. 常见故障排查与性能调优速查
6.1 相机枚举失败与断连问题
这是最高频的问题。现象是插上相机后realsense-viewer提示“No device connected”,或者用着用着突然断连。排查思路如下。
先确认USB线缆。换一根Intel原装线或者已知质量好的线,直插主板USB口,不要经过Hub。如果问题消失,说明是线缆或Hub的问题。如果问题依旧,检查dmesg日志,看有没有USB相关的错误。
dmesg | grep -i usb dmesg | grep -i uvc如果看到uvcvideo: Failed to query (GET_INFO) UVC control之类的错误,说明内核UVC驱动和相机通信有问题。在x86平台上,可以尝试更新内核或者安装librealsense2-dkms。在ARM平台上,建议用RSUSB后端重新编译librealsense,绕过内核驱动。
如果相机用一段时间后断连,摸一下相机外壳是不是很烫。D435i全功率运行时发热不小,过热会触发保护。改善散热或者降低分辨率/帧率/激光功率可以减少发热。
6.2 深度图大面积空洞
深度图空洞多,先看场景是不是低纹理或者反光。白墙、玻璃、镜面、黑色物体都是D435i的克星。白墙和黑色物体是因为纹理不足,红外散斑打上去也看不清;玻璃和镜面是因为红外光直接穿透或者镜面反射,相机接收不到回波。这些是物理限制,软件调参解决不了,只能改场景或者换其他原理的深度相机。
如果场景没问题但空洞还是多,检查激光投射器是否打开、功率是否足够。在realsense-viewer里把Laser Power调到最大试试。如果最大功率还是不行,可能是投射器坏了或者被遮挡了。另外,检查深度预设是不是选错了,有些预设对空洞的容忍度低。
6.3 点云飘移与噪声过大
点云飘移通常有几个原因。一是深度图噪声大,点云自然跟着抖。解决办法是开时域滤波,或者用多帧平均。二是相机标定不准,特别是外参,导致点云在空间中的位置有系统性偏差。重新标定可以解决。三是IMU没标定或者没融合,相机移动时点云跟着晃。如果你做移动扫描,必须把IMU用起来。
点云噪声过大,除了深度图本身的噪声,还要检查点云生成时的参数。比如rs2::pointcloud的map_to函数可以把深度图映射到RGB视角,但如果RGB和深度的外参不准,映射后的点云会有重影。另外,点云的体素滤波(Voxel Grid)可以降采样去噪,但体素大小要选合适,太小了去噪效果不明显,太大了会丢失细节。
6.4 ARM平台性能优化
在Jetson或者树莓派上跑D435i,性能优化是永恒的话题。首先,关闭不需要的数据流。如果你只用深度,就把RGB和IMU都关掉,能省不少CPU和USB带宽。其次,降低分辨率和帧率。640x480@15fps对于大多数SLAM和避障应用足够了,没必要追求30fps。第三,用硬件加速。Jetson有GPU和DLA,可以把点云生成、滤波、特征提取这些操作放到GPU上。librealsense支持CUDA后端,编译时打开-DBUILD_WITH_CUDA=ON,点云生成会快很多。
另外,ARM平台的USB控制器有时候会有带宽瓶颈。如果你同时开深度和RGB,而且分辨率都比较高,可能会丢帧。解决办法是降低RGB分辨率,或者用MIPI CSI相机替代RGB。Jetson Nano的USB 3.0带宽是5Gbps,理论上够用,但实际控制器效率不高,建议留出余量。
6.5 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 相机枚举失败 | USB线缆/驱动/权限 | dmesg查USB日志 | 换线、装DKMS、加udev规则 |
| 用一段时间断连 | 过热/供电不足 | 摸外壳温度、查电流 | 改善散热、外供电、降功耗 |
| 深度图空洞多 | 低纹理/反光/投射器关 | 换场景测试、查Laser Power | 开投射器、调功率、改场景 |
| 点云飘移 | 标定不准/无IMU融合 | 重投影验证、查IMU数据 | 重新标定、融合IMU |
| ARM平台编译失败 | 内存不足/内核不兼容 | 查编译日志、查内核版本 | 开交换分区、用RSUSB后端 |
| 帧率上不去 | 分辨率高/USB带宽满 | 查实际帧率、查USB占用 | 降分辨率、关多余流 |
| 深度值跳变 | 时域滤波关/场景动态 | 开时域滤波对比 | 开时域滤波、多帧平均 |
| RGB和深度不对齐 | 外参不准/未对齐 | 投影验证 | 重新标定、用align模块 |
7. 机械臂抓取场景下的D435i实战配置
机械臂抓取是D435i最典型的应用场景之一,也是坑最多的场景。我拿一个实际的传送带抓取项目来说,配置是D435i固定在机械臂末端上方约0.8米处,工作区域是传送带上0.3米到1.2米的范围,目标是抓取随机摆放的金属零件。
首先,深度分辨率选848x480@30fps,这个分辨率下0.8米处的深度噪声大约±1.5毫米,对于零件抓取够用。激光功率设180,因为金属零件表面有反光,需要足够的散斑来保证匹配。深度单位保持默认的0.001米。后处理滤波器开Decimation降到424x240减少计算量,Threshold限制在0.3米到1.2米去掉传送带背景,Spatial滤波2次迭代去噪,Temporal滤波稳定静态帧,Hole Filling关掉因为抓取需要真实深度。
标定方面,内参用出厂值,外参自己标了一遍,因为相机装了外壳。手眼标定用easy_handeye或者自己写AX=XB求解,采集15个不同位姿,标定误差控制在2毫米以内。抓取时,先对深度图做平面分割找到传送带平面,然后对平面以上的点做欧式聚类,每个聚类是一个零件,计算聚类中心的三维坐标,转换到机械臂基座坐标系,发给运动规划模块。
实际跑下来,抓取成功率从最初的60%提升到95%以上,主要改进点在于:激光功率从默认150调到180,金属反光导致的空洞减少了70%;时域滤波从关闭改为开启,深度跳变导致的抓空减少了80%;手眼标定从用出厂值改为自己标,定位偏差从5毫米降到2毫米以内。这几个参数调优的收益远比换更贵的相机大。
8. 一些没人告诉你但很重要的经验
D435i的固件版本会影响深度质量。我遇到过同一个相机,升级固件后深度图噪声明显变大,回滚固件又恢复正常。所以如果你当前固件跑得好好的,不要随便升级。如果必须升级,先备份当前固件版本号,升级后对比测试,不行就回滚。
相机的USB连接顺序也有讲究。如果你有多个USB设备,D435i尽量插在独立的USB控制器上,不要和其他高带宽设备共享。在Linux下可以用lsusb -t查看USB拓扑,确认相机是否和其他设备挂在同一个Hub下。
深度图和RGB图的时间戳对齐在移动场景下很关键。D435i的深度和RGB是分开曝光的,时间戳有微小差异。如果你做RGB-D SLAM,必须用rs2::syncer做时间同步,或者用硬件同步信号。软件同步的精度在毫秒级,对于快速运动场景可能不够。
最后,D435i的深度图在物体边缘会有“飞点”,就是深度值突然跳到背景深度。这是双目匹配在边缘处的固有缺陷,因为边缘处左右图的匹配容易出错。解决办法是在点云生成后做边缘剔除,或者用形态学操作腐蚀一下深度图边缘。做抓取的时候,如果抓取点选在边缘附近,很容易抓空,建议把抓取点往物体中心偏移几个像素。
这个相机我用了快五年,从最初的各种翻车到现在基本能稳定出活,最大的体会是:参数调优的收益远大于硬件升级,而调优的前提是理解它的工作原理和物理限制。不要指望D435i能在所有场景下都表现完美,它有自己的舒适区,在舒适区内把参数调到位,它能给你非常可靠的结果。超出舒适区,比如测玻璃、测远距离、强光室外,再怎么调也没用,该换方案就换方案。