英特尔 D435/D435i双目相机 使用指南
目录
Intel RealSense D435深度相机介绍:
关于左右红外图像:
关于像素深度的检索:
Intel RealSense 各种工具:
工具的介绍
相机基本操作
相机自校准
获取相机参数
python脚本
Linux命令行
相机运行并显示画面
获得深度图像
点云
帧对齐
英特尔官方手册:调整深度摄像头以获得最佳性能
首先以相机的最佳深度分辨率运行
确保图像已正确曝光(曝光不佳时性能不佳的首要原因)
后处理
更改深度步长
彩色摄像头
使用阳光,但避免眩光
Intel RealSense D435深度相机介绍:
一对立体红外传感器(Stereo IR Pair) + 一个红外激光发射器(IR Projector) + RGB Camera
RGB摄像头分辨率达2000万像素,3D传感器可以30帧/秒的速度提供分辨率高达1280 × 720,或者以90帧/秒的速度提供848 × 480的较低分辨率。 深度距离在0.1 m~10 m之间,视场角度为85 × 58度。
工作原理:左右红外相机(接收器)分贝产生两幅也就是左侧和右侧ir灰度图像,中间红外点阵发射器(红外散斑)相当于补光灯,进而可以得到点云。红外点阵发射器强度可调,是否发射也可调,不打开也能测深度,只是效果不好。最右边的rgb相机用于采集彩色图片,最终可以将彩色视频流与深度流进行对齐。
测距原理和一般的双目相机相同,都是基于左右图像的视差来求得距离。只是相比于普通彩色rgb相机,红外ir相机是用来接收目标返回的红外光线的,得到的是左右两幅红外灰度图像。若把屋里灯光关掉,黑暗的环境,红外ir相机一样可以生成深度图像,只是质量略有下降。
视差目前仅在D400系列上可用,可使用控件修改控制视差。(advanced_mode)
关于左右红外图像:
translation[1]、
translation[2]为零
)关于像素深度的检索:
立体视差通过逆线性关系与深度相关,并且可以通过 1 / rs2_get_depth_scale(…) 查询记录视差为 1 的点的距离。下面显示了如何检索像素的深度(以米为单位):
c++:
const float scale = rs2_get_depth_scale(sensor, NULL);
const uint16_t * image = (const uint16_t *)rs2_get_frame_data(frame, NULL);
float depth_in_meters = 1 / (scale * image[pixel_index]);
Intel RealSense 各种工具:
工具的介绍
相机基本操作
更详细说明见官网:
Projection in RealSense SDK 2.0 · IntelRealSense/librealsense Wiki (github.com)
相机自校准
更详细内容可见官网:
Intel® RealSense™ Self-Calibration for D400 Series Depth Cameras
这张图片也就是说,在 Viewer 上进行校准,当误差小于一定值时,可以忽略。
如果校准过程中报错:可能是没有足够的有效深度像素,通常可以通过确保投影仪处于打开状态来补救。
获取相机参数
python脚本
# 注意!!!通过python script获取内参一定要看好自己到底用了哪个video stream
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.rgb8, 30)
cfg = pipeline.start(config)
time.sleep(1)
profile = cfg.get_stream(rs.stream.depth) # 获取深度流的配置文件
intr = profile.as_video_stream_profile().get_intrinsics() # 向下播放到视频流并获取内在信息
print(intr) # 获取内参 width: 640, height: 480, ppx: 319.115, ppy: 234.382, fx: 597.267, fy: 597.267, model: Brown Conrady, coeffs: [0, 0, 0, 0, 0] 319.1151428222656
print(intr.ppx) # 获取指定某个内参
Linux命令行
rs-sensor-control
相机运行并显示画面
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.rgb8, 30)
pipeline.start(config)
time.sleep(1)
frames = pipeline.wait_for_frames()
depth_frame = frames.get_depth_frame()
color_frame = frames.get_color_frame()
# Convert images to numpy arrays
depth_image = np.asanyarray(depth_frame.get_data())
color_image = np.asanyarray(color_frame.get_data())
# # Apply colormap on depth image (image must be converted to 8-bit per pixel first)
# depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
#
# # Stack both images horizontally
# images = np.hstack((color_image, depth_colormap))
#
# # Show images
# cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
# cv2.imshow('RealSense', images)
# cv2.waitKey(1)
fig, axes = plt.subplots(1, 2)
for ax, im in zip(axes, [color_image, depth_image]):
ax.imshow(im)
ax.axis('off')
plt.show()
pipeline.stop()
获得深度图像
通过函数从2D像素坐标映射到3D坐标需要了解该像素的深度(以米为单位)。下面显示了如何获得像素的深度(以米为单位):
python:
dpt_frame = pipe.wait_for_frames().get_depth_frame().as_depth_frame()
pixel_distance_in_meters = dpt_frame.get_distance(x,y)
若设备无法确定给定图像像素的深度,则深度图像中将存储零值。这表示“无深度”。C++可以修改深度的刻度。(python似乎也可以)
点云
pyrealsense2提供了一个处理块,用于从深度和颜色框架创建点云和相应的纹理映射。从深度影像创建的点云是深度流的3D坐标系中的一组点。下面是如何创建点云对象:
python:
import pyrealsense2 as rs
pc = rs.pointcloud()
points = pc.calculate(depth_frame)
pc.map_to(color_frame)
帧对齐
通常在处理颜色和深度图像时,需要将每一个像素从一个图像映射到另一个图像
import pyrealsense2 as rs
align = rs.align(rs.stream.color)
aligned_frames = align.proccess(depth_and_color_frameset)
color_frame = aligned_frames.first(rs.stream.color)
aligned_depth_frame = aligned_frames.get_depth_frame()
英特尔官方手册:调整深度摄像头以获得最佳性能
调整深度摄像头以获得最佳性能 (intelrealsense.com)
首先以相机的最佳深度分辨率运行
确保图像已正确曝光(曝光不佳时性能不佳的首要原因)
检查自动曝光是否良好,若不好,则切换到手动曝光以确保拥有良好的灰度左右图像。曝光不佳是性能不佳的首要原因。
通常,我们建议先调整曝光以获得最佳效果,同时保持GAIN=16(最低设置)。增加增益往往会引入电子噪声,虽然彩色图像可能看起来更好,但深度质量会下降。曝光单位为微秒,因此33000为33ms。请注意,过度曝光图像可能与曝光不足一样糟糕,因此请小心找到合适的曝光。
自动曝光功能的使用见官方手册
后处理
英特尔没有对深度图像进行任何的后处理,而是将其留给其他的应用程序。在SDK2.0中有一些简单的后处理选项,通常有以下处理步骤:
- 子采样:在捕获后降低x-y分辨率通常有利于减少更高级别的计算。分辨率减低2倍讲授后续处理速度提高4倍。此外,子采样可用于使用非零均值或非零中位数函数对数据进行一些基本的孔填充和平滑处理。最后,子采样实际上也有助于点云的可视化。
- 时间过滤:使用一些时间平均来改善深度,深度数据中存在时间噪声。建议使用 IIR 过滤器。但在某些情况下,使用“持久性”也可能是有益的。
- 保留边缘的滤波:平滑深度噪点,保留边缘,同时使表面更平坦。建议在视差域(即深度刻度为 1/距离)中进行此处理,并通过逐渐增加步长阈值进行试验,直到它看起来最适合预期用途。另一种成功的后处理技术是使用由 RGB 图像引导的域变换滤波器或双线性滤波器。例如,这可以帮助锐化边缘。
- 孔填充:有必要根据相邻值或RGB图像用最佳猜测来填充孔
更改深度步长
可能需要在高级模式 API 中更改“深度单位”。默认情况下,D4 VPU 提供 16 位深度,深度单位为 1000um (1mm)。这意味着最大范围将约为65m。但是,例如,通过将其更改为5000um,可以将深度报告为最大值5×65 = 325m。
彩色摄像头
优点:
- 像素完美对齐、校准并与深度图重叠
- 完美的时间同步
- 无需额外的开销即可对齐颜色与深度
- 不会产生额外的遮挡伪像,因为它完全共对其。
缺点:
- 如果投影仪打开,它通常会显示投影仪图案
使用阳光,但避免眩光
- 阳光可以降低传感器的噪音,并倾向于"带出"物体的纹理。此外,曝光可以减少到接近1ms,这也减少了运动伪像。因此,结果是英特尔实感D4xx摄像头实际上在阳光下表现非常好。
- 需要注意的一个问题是指向太阳或靠近太阳时的镜片眩光。建议用挡板遮挡镜片,以降低镜片眩光的风险。
- 在自动曝光方面要特别小心,尤其是在图像中可以看到太阳或太阳反射的情况下。默认情况下,自动曝光算法会尝试将整个图像的平均强度保持在一定范围内。如果太阳在那个图像中,其他一切都会突然变成黑色。对于许多应用,如自主机器人或汽车,只需将自动曝光算法的兴趣区域更改为较小的尺寸,或者具体到图像的下半部分,它会有所帮助。
来源:凝色清