3D感知介绍
目录
- 传感器
- RGB-D相机
- 点云
1.传感器
主动式传感器是指向目标发射电磁波,然后收集从目标反射回来的电磁波信息的传感器,如合成孔径雷达等。
被动式传感器指只能收集地而目标反时来自太阳光的能量或目标自身辐射的电进波能量的传感器,如摄影相机和多光谐扫描仪等。探测器指接收地物电磁辐射的物理元件,是传感器中最重要的部分,其功能是实现能量转换,测量和记录接收到的电磁锅射能。常用的探测元件有感光股片、光电敏感元件、固体敏感元件和波导。
(1)主动传感器
主动式传感器是指向目标发射电磁波,然后收集从目标反射回来的电磁波信息的传感器,如合成孔径雷达等。
1)激光测距仪(激光雷达)
三维激光测距仪或三维激光扫描仪是基于光探测和测距(激光雷达)方法开发的主动传感器。也就是说,这些传感器用脉冲激光照射目标并测量反射的脉冲。
由于激光频率是一个已知的稳定量,所以通过测量从脉冲发送到接收的时间来计算到视场中物体的距离。
激光雷达的优点
与普通微波雷达相比,激光雷达由于使用的是激光束,工作频率较微波高了许多,因此带来了很多优点,主要有:
- 分辨率高
- 隐蔽性好、抗有源干扰能力强
- 低空探测性能好
- 体积小、质量轻
激光雷达的缺点
- 工作时受天气和大气影响大
- 价格较高
- 尺寸较大
2)ToF相机(飞行时间相机)
3DToF相机(飞行时间相机)是一种主动传感器,它通过用红外光源照射一个区域并观察到达现场和返回现场所花费的时间来执行深度测量。
但是,与激光测距仪不同的是,ToF摄像机可以捕获每个光脉冲的整个视场,而没有任何移动部件。这样可以快速采集数据。
根据其工作原理,ToF传感器可分为两类:脉冲运行时间和相移连续波。
脉冲运行时间传感器
脉冲运行时间传感器发出光脉冲并启动计时器,然后等待直到检测到反射并停止计时器,从而直接测量光的飞行时间。
尽管从概念上讲是直观且简单的,但此技术需要非常精确的硬件来进行计时。
相移连续波传感器
与脉冲运行时间传感器不同,相移连续波传感器发出连续的调制光波流。在此,通过测量反射波的相移来计算深度,从而创建场景的3D深度图。
3)超声波传感器
就像激光扫描仪使用激光脉冲进行距离测量一样,超声波传感器使用高频声音脉冲。
超声波传感器发出高频声音脉冲,然后测量声音回声反射回去所花费的时间。
传感器通常由两个压电晶体组成,一个充当发射器(如扬声器),另一个充当接收器(如麦克风)。
由于空气中的声速是已知的(每秒约343米),因此超声波传感器会通过计时反射脉冲到达接收器所需的时间来计算与目标的距离。
(2)被动式传感器
1)单目相机
一个简单的单目彩色摄像机可以用来推断给定场景的深度数据。虽然不简单,但可以使用软件技术从多个2D图像计算深度。
其中一种技术是“运动结构”。
在这种方法中,一个给定的物体或场景的多个图像从一个移动的摄像机中获取,以从产生的视频流中重建一个3D模型。深度是通过三角测量技术计算出来的,这就要求在整个运动过程中对相机的姿态进行精确测量。
结果表明,将这些三角剖分技术与单幅图像的深度推断相结合,可以从运动结果中改进结构。
2)立体相机
立体摄像机系统由两个单眼摄像机组成,它们之间有精确的已知距离。深度信息是通过比较两个摄像头观察同一物体或场景的图像帧来获得的。
两个摄像头感知到的场景中给定物体位置的差异称为视差。立体声摄像机,很像人眼,利用这种差异来计算与给定对象相关的深度数据。
2.RGB-D相机
RGB-D相机结合了主动和被动传感器的优点,它由被动RGB相机和主动深度传感器组成。与传统相机不同,RGB-D相机除了提供RGB图像外,还提供每个像素的深度信息。
传统上,主动深度传感器是红外(IR)投影仪和接收器。就像连续波飞行时间传感器一样,RGB-D摄像机通过在场景中发射光信号并分析反射光来计算深度,但是入射波调制是在空间而非时间上执行的。
这是通过以预定模式将光从IR发射器投射出并通过解释该模式中由目标物体表面引起的变形来计算深度来完成的。这些图案的范围从简单的条纹到独特而复杂的斑点图案。
使用RGB-D相机进行3D感知的优势在于,与立体相机不同,它们通过直接提供每个像素的深度值而不是从原始图像帧中推断深度信息来节省大量计算资源。
此外,这些传感器价格便宜,并且具有简单的USB即插即用接口。RGB-D摄像机可用于从映射到复杂对象识别的各种应用。
RGB-D 相机工作原理
RGB-D相机具有两个主要功能部分,即RGB相机和深度传感器。
(1)图像的获取
RGB图像传感器通过测量光和密度来工作。可以使用红色,绿色和蓝色这三种颜色范围。它通过使用通常称为感测器的传感器元件来实现。每个感测器设计为仅允许特定波长范围的光的波长,对应于特定的颜色范围,并且滤除所有其他波长。入射在每个传感器上的光子会产生电荷,每次曝光完成后,相机的处理器就会读取这些电荷。这些传感器上的信息会映射到图像上,因此只有三种颜色中的一种是使用彩色滤光片阵列或CFA以交替的模式捕获每个像素的图像。使用CFA,我们可以同时测量同一传感器上所有三个颜色通道的强度。以Bryce Bayer命名的拜耳滤光片是如图所示。
CFA是使用最广泛的,它交替使用蓝绿色和绿色红色的行。如果对它们进行计数,您会发现绿色感官的数量是蓝色或红色的两倍。以这种方式设计的滤镜,以模仿人眼的成像质量。由于每个像素仅包含有关单一颜色的信息,因此使用称为去马赛克的技术来推断相邻像素剩下的两个颜色通道的强度。
让我们看一个简单的去马赛克的例子。
拜耳算法已将蓝色分配给突出显示的像素,这意味着它将直接从传感器接收蓝色通道的强度信息。
同时,通过平均对角相邻像素的强度来计算该像素的红色强度。类似地,绿色通道的强度通过平均拱形和像素的强度来计算。
通过链接可以找到有关数字成像,滤色器阵列和去马赛克的更多信息。
(2)添加深度
大多数RGB-D相机都使用一种称为“结构化光”的技术来从场景中获取深度信息。
此设置的功能与立体相机的设置非常相似,但有两个主要区别。
在立体相机中,我们通过比较左右摄像机捕获的图像之间的差异或差异来计算深度。与此相反,结构化的灯光设置包含一台投影仪和一台摄像机。
我们可以看到如何从RGB-D相机生成深度图:
投影机在场景上投射出已知的图案。该图案可以像一系列条纹或复杂的斑点图案一样简单。
然后,摄像机捕获场景中物体反射出的光图案。场景中物体的形状会使感知的模式失真。通过比较已知的投影图案(保存在传感器硬件上)和反射图案,可以生成深度图,就像立体相机一样。
3.点云
点云是三维物体的数字表示。在实际实现中,它们还可以包含每个点的附加元数据,以及许多在点云上操作的有用方法。
其他元数据的示例可能包括
- 每个点的RGB值
- 强度值
- 当前的曲率信息
提供的其他方法可能包括
- 空间遍历点的迭代器
- 基于特定属性过滤云的方法
- 在云上执行统计分析的操作符
几乎所有3D扫描仪或激光雷达都将数据输出为高精度点云。来自立体摄像机和RGB-D摄像机的数据也可以轻松转换为点云。点云用于众多应用中,其中3D空间信息是数据的关键组成部分。一些示例应用程序包括:
- 深度传感器测量
- 真实物体的模型
- 机器人工作区的范围
- 环境图
至于如何通过计算表示点云,以下是与来自RGB-D摄像机的每个数据点关联的数据类型的示例:
属性 | 常用数据类型 |
---|---|
x轴 | float |
y轴 | float |
z轴 | float |
红色值 | Unsigned 8-bit int |
蓝色值 | Unsigned 8-bit int |
绿色值 | Unsigned 8-bit int |
从RGB-D数据创建点云
以苹果作为示例,这是RGB图像:
这是深度图:
程序如下:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from time import time
from matplotlib.axes._axes import _log as matplotlib_axes_logger
# 关闭报错
matplotlib_axes_logger.setLevel('ERROR')
# 读取图像和深度图
image_location = '1.png'
depth_map_location = '2.png'
# 载入图像
depth_map = mpimg.imread(depth_map_location)
image = mpimg.imread(image_location)
# 初始化和建立图像
start_time = time()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# 读取图片行列
rows = depth_map.shape[0]
cols = depth_map.shape[1]
# 发送没有正确映射的像素
max_val = depth_map.max() * 1.1
# 循环计数器置零
count = 0
# 为了节省时间,减少像素,计算需要在30秒以内
pixel_cut = 4
point_num = int(rows/pixel_cut+1) * int(cols/pixel_cut+1)
# 遍历所有像素
for x in range(cols):
for y in range(rows):
if (x % pixel_cut == 0 and y % pixel_cut == 0):
count += 1
# 获取像素点颜色
pixel_color = ([image[y, x, 0], image[y, x, 1], image[y, x, 2]])
# pixel_color = image[y, x, 0]
print("\r", "进度百分比:{0}%".format(round(count*100/point_num)), end="", flush=True)
# 获取每个粒子的点深度
depth = depth_map[y, x]
# 发送点没有正确映射k
if depth == []:
depth = max_val
ax.scatter(x, depth, y, c=pixel_color, marker='o')
# Axis Labels
ax.set_xlabel('Width')
ax.set_ylabel('Depth')
ax.set_zlabel('Height')
plt.gca().invert_zaxis()
# 变视角旋转
elevation = 40 # Up/Down
azimuth = 320 # Left/Right
ax.view_init(elevation, azimuth)
plt.show()
print("\n", "Outputted {} of the {} points".format(count, 6552))
print("Results produced in {:04.2f} seconds".format(time() - start_time))
以下为输出: