DepthAI的整体架构
官方给的DepthAI的整体架构如下图所示:
其中:
- Host 主机端是连接 OAK 设备的计算机,如 PC 或 RPi。
- Device 设备端是 OAK 设备本身。如果设备端发生了某些事情,则意味着它正在机器人视觉核心(RVC)上运行。
- Pipeline 管道是设备端的完整工作流,由节点和它们之间的连接组成。
- Node 节点 Node 是DepthAI的单一功能。节点具有输入或输出,并具有可配置的属性(如相机节点上的分辨率)。
- Connection 连接 是一个节点的输出和另一个节点的输入之间的链接。为了定义管道数据流,连接定义在何处发送消息以实现预期结果
- XLink 是一个中间件,能够在设备和主机之间交换数据。XLinkIn节点允许将数据从主机发送到设备,而XLinkOut则相反。
- Message 消息在节点之间传输,由连接定义
Device 对象
Device
对象表示 OAK 设备。启动设备时,我们必须向其上传一个管道,该管道将在 VPU 上执行。 在代码中创建Device时,固件将与管道和其他资产(例如 NN blob)一起上传。
创建Device即OAK设备的代码如下:
#使用depthai库创建了一个空的Pipeline对象
pipeline = depthai.Pipeline()
# 通过depthai.Device(pipeline)创建与OAK相机的连接
with depthai.Device(pipeline) as device:
# 打印 MxID(设备标识)、USB速度和已连接的相机数量。
print('MxId:',device.getDeviceInfo().getMxId())
print('USB speed:',device.getUsbSpeed())
print('Connected cameras:',device.getConnectedCameras())
# 使用device.getInputQueue("input_name", maxSize=4, blocking=False)创建了一个输入队列(input_q),用于在主机和设备之间传递消息。该输入队列可以在设备端使用XLinkIn来接收消息。
input_q = device.getInputQueue("input_name", maxSize=4, blocking=False)
# 使用device.getOutputQueue("output_name", maxSize=4, blocking=False)创建了一个输出队列(output_q),用于从设备端向主机传递消息。该输出队列可以在设备端使用XLinkOut来发送消息。
output_q = device.getOutputQueue("output_name", maxSize=4, blocking=False)
# 主循环
while True:
# 通过output_q.get()来从output_q队列中获取一个来自设备的消息。这里使用了阻塞模式,即如果队列为空,则会等待一个消息。也可以使用output_q.tryGet()来进行非阻塞的消息获取,如果队列为空,则返回None。
output_q.get() # Or output_q.tryGet() for non-blocking
# 创建了一个depthai.ImageManipConfig对象cfg,并使用input_q.send(cfg)将该消息发送给设备。这里的cfg可以是在主机上进行图像处理的配置,通过发送该配置给设备,可以控制设备上的图像处理操作。
cfg = depthai.ImageManipConfig()
input_q.send(cfg)
上面这段代码使用depthai库创建了一个Pipeline对象,并在与OAK相机连接的设备上进行了一些基本的配置和消息传递操作。
通过标识连接到指定设备
如果有多台设备,并且只想连接到特定的设备,或者 OAK PoE 摄像头在外部 子网中,可以通过指定 MxID、IP 或 USB 端口名称来连接要连接到的设备。
# 通过depthai.DeviceInfo()创建了一个DeviceInfo对象,用于存储设备信息,并指定MXID参数。
device_info = depthai.DeviceInfo("14442C108144F1D000") # MXID
#device_info = depthai.DeviceInfo("192.168.1.44") # IP Address
#device_info = depthai.DeviceInfo("3.3.3") # USB port name
# 使用depthai.Device()创建设备连接时,将pipeline和device_info作为参数传递给Device对象。这将使用指定的设备信息来建立与相机的连接。
with depthai.Device(pipeline, device_info) as device:
定义输入/输出队列
在初始化设备之后,还必须初始化输入/输出队列。这些队列将位于主机上(在RAM中)。
# 定义输出队列
outputQueue = device.getOutputQueue("output_name")
# 定义输入队列
inputQueue = device.getInputQueue("input_name")
定义输出队列时,设备可以在任何时间点向其推送新消息,主机可以在任何时候从中读取。通常,当主机从队列中快速读取时,队列(无论其大小)大部分时间都将保持为空。但是,当我们在主机端添加东西(额外的处理、分析等)时,可能会发生设备向队列写入的速度比主机从中读取的速度快的情况。然后,队列中的消息将开始添加-在这种情况下,maxSize和blocking标志都决定了队列的行为。我们可以通过以下方式设置这些标志:
# 初始化队列时指定
queue = device.getOutputQueue(name="myQueue", maxSize=5, blocking=False)
# 或者 通过调用方法指定
queue.setMaxSize(10)
queue.setBlocking(True)
这段代码初始化和配置了输出队列(OutputQueue)对象。
通过device.getOutputQueue(name=“myQueue”, maxSize=5, blocking=False)方法创建了一个输出队列(OutputQueue)对象。这里的name参数用于给输出队列命名,maxSize参数指定了队列的最大大小,即最多可以存储的消息数量,blocking参数指定了队列的阻塞模式。
在这段代码中,输出队列的名称被设置为"myQueue",最大大小为5,阻塞模式为非阻塞式。这意味着,当没有消息可用时,调用输出队列的get()方法将立即返回,而不会等待消息的到达。
然后,在初始化之后,通过调用queue.setMaxSize(10)和queue.setBlocking(True)来分别更改输出队列的最大大小和阻塞模式。这里的setMaxSize()方法将输出队列的最大大小更改为10,setBlocking()方法将输出队列的阻塞模式更改为阻塞式(即当队列为空时,