DepthAI v2 has been superseded by DepthAI v3. You are viewing legacy documentation.

介绍

让我们从一个示例来了解基础知识。我们将创建一个简单的应用程序,该程序运行一个对象检测神经网络, 并流式传输带有可视化神经网络检测结果的彩色视频。我们将使用 DepthAI Python API 来创建该应用程序。
1

创建管道

数据源

现在,我们要添加的第一个节点是 ColorCamera。该节点会自动选择中间的摄像头(在大多数设备中即为彩色摄像头),并将视频流提供给管道中的下一个节点。
我们将使用预览输出,调整为 300x300 以适应 mobilenet-ssd 的输入尺寸(稍后定义)。
关于 ColorCamera 节点的更多信息,请参阅 ColorCamera 文档

检测网络

接下来,让我们定义一个带有 mobilenet-ssd 网络的 MobileNetDetectionNetwork 节点。
每个我们想要使用的神经网络都必须先编译成 blob 文件,这是一个包含网络权重和配置的二进制文件,并且可以加载到设备中。
有关编译网络的更多信息,请参阅编译神经网络部分。
本示例的 blob 文件将使用 blobconverter 工具自动编译并下载。
blobconverter.from_zoo() 函数返回模型的 Path,因此我们可以直接将其放入 detection_nn.setBlobPath() 函数中。
使用此节点时,神经网络输出将在设备端解析,我们将收到可直接使用的检测结果对象。为此,我们还需要设置置信度阈值以过滤掉不正确的检测结果。

接收器

如果我们希望查看神经网络的输出,需要添加一个 XLinkOut 节点。该节点会将数据发送到主机,以便我们进一步处理。
每个 XLinkOut 节点只应连接到一个节点,因此我们需要为检测网络添加一个,并为 RGB 流添加另一个。

连接各节点

现在我们需要连接各个节点。我们将 ColorCamera 连接到 MobileNetDetectionNetwork,并将 MobileNetDetectionNetwork 连接到 XLinkOut。同时,我们还将 ColorCamera 连接到 XLinkOut 以获取视频流。
请注意,一个节点的输出可以同时连接到多个节点的输入。
2

上传并运行管道

连接设备

为了将构建好的管道上传到设备,我们必须先初始化它。通常的做法是使用上下文管理器进行初始化,这样我们就不必担心完成后关闭设备。depthai.Device(pipeline) 调用将创建一个 Device 对象,并将创建的 Pipeline 对象传递给它。在后台,此调用会检查 USB 和网络接口,以确定设备是否可用并准备好接受连接。

初始化队列

消费设备消息

我们创建一个无限循环来保持设备打开。在每次循环迭代中,我们尝试检索设备发送到我们上面创建的队列的消息。.tryGet() 方法将返回数据包,如果没有数据则返回 None。.try() 方法类似,但会阻塞直到接收到数据包。
  • 如果 RGB 相机数据包存在,我们使用 getCvFrame() 方法以 OpenCV 格式获取帧:.getCvFrame()
  • 当接收到神经网络的数据时,我们获取包含 mobilenet-ssd 结果的检测数组:.detections

绘制帧

如果我们想查看结果,可以使用 OpenCV 实现。我们使用从 rgb 队列接收到的 frame,并为从 nn 队列消费到的每个检测结果在图像上绘制一个矩形。我们收到的边界框坐标通常是归一化的范围 [0, 1],因此如果我们希望在 RGB 帧上绘制,需要先反归一化它们。这是通过自定义函数 frameNorm() 完成的。
1# first, import all necessary modules
2from pathlib import Path
3
4import blobconverter
5import cv2
6import depthai
7import numpy as np
8
9
10pipeline = depthai.Pipeline()
11
12# First, we want the Color camera as the output
13cam_rgb = pipeline.createColorCamera()
14cam_rgb.setPreviewSize(300, 300) # 300x300 will be the preview frame size, available as 'preview' output of the node
15cam_rgb.setInterleaved(False)
16
17detection_nn = pipeline.createMobileNetDetectionNetwork()
18# Blob is the Neural Network file, compiled for MyriadX. It contains both the definition and weights of the model
19# We're using a blobconverter tool to retreive the MobileNetSSD blob automatically from OpenVINO Model Zoo
20detection_nn.setBlobPath(blobconverter.from_zoo(name='mobilenet-ssd', shaves=6))
21# Next, we filter out the detections that are below a confidence threshold. Confidence can be anywhere between <0..1>
22detection_nn.setConfidenceThreshold(0.5)
23
24# XLinkOut is a "way out" from the device. Any data you want to transfer to host need to be send via XLink
25xout_rgb = pipeline.createXLinkOut()
26xout_rgb.setStreamName("rgb")
27
28xout_nn = pipeline.createXLinkOut()
29xout_nn.setStreamName("nn")
30
31cam_rgb.preview.link(xout_rgb.input)
32cam_rgb.preview.link(detection_nn.input)
33detection_nn.out.link(xout_nn.input)
34
35# Pipeline is now finished, and we need to find an available device to run our pipeline
36# we are using context manager here that will dispose the device after we stop using it
37with depthai.Device(pipeline) as device:
38 # From this point, the Device will be in "running" mode and will start sending data via XLink
39
40 # To consume the device results, we get two output queues from the device, with stream names we assigned earlier
41 q_rgb = device.getOutputQueue("rgb")
42 q_nn = device.getOutputQueue("nn")
43 # Here, some of the default values are defined. Frame will be an image from "rgb" stream, detections will contain nn results
44 frame = None
45 detections = []
46
47 # Since the detections returned by nn have values from <0..1> range, they need to be multiplied by frame width/height to
48 # receive the actual position of the bounding box on the image
49 def frameNorm(frame, bbox):
50 normVals = np.full(len(bbox), frame.shape[0])
51 normVals[::2] = frame.shape[1]
52 return (np.clip(np.array(bbox), 0, 1) * normVals).astype(int)
53
54
55 while True:
56 # we try to fetch the data from nn/rgb queues. tryGet will return either the data packet or None if there isn't any
57 in_rgb = q_rgb.tryGet()
58 in_nn = q_nn.tryGet()
59
60 if in_rgb is not None:
61 # If the packet from RGB camera is present, we're retrieving the frame in OpenCV format using getCvFrame
62 frame = in_rgb.getCvFrame()
63
64 if in_nn is not None:
65 # when data from nn is received, we take the detections array that contains mobilenet-ssd results
66 detections = in_nn.detections
67
68
69 if frame is not None:
70 for detection in detections:
71 # for each bounding box, we first normalize it to match the frame size
72 bbox = frameNorm(frame, (detection.xmin, detection.ymin, detection.xmax, detection.ymax))
73 # and then draw a rectangle on the frame to show the actual result
74 cv2.rectangle(frame, (bbox[0], bbox[1]), (bbox[2], bbox[3]), (255, 0, 0), 2)
75 # After all the drawing is finished, we show the frame on the screen
76 cv2.imshow("preview", frame)
77
78 # at any time, you can press "q" and exit the main loop, therefore exiting the program itself
79 if cv2.waitKey(1) == ord('q'):
80 break
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98