介绍
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 modules2from pathlib import Path34import blobconverter5import cv26import depthai7import numpy as np8910pipeline = depthai.Pipeline()1112# First, we want the Color camera as the output13cam_rgb = pipeline.createColorCamera()14cam_rgb.setPreviewSize(300, 300) # 300x300 will be the preview frame size, available as 'preview' output of the node15cam_rgb.setInterleaved(False)1617detection_nn = pipeline.createMobileNetDetectionNetwork()18# Blob is the Neural Network file, compiled for MyriadX. It contains both the definition and weights of the model19# We're using a blobconverter tool to retreive the MobileNetSSD blob automatically from OpenVINO Model Zoo20detection_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)2324# XLinkOut is a "way out" from the device. Any data you want to transfer to host need to be send via XLink25xout_rgb = pipeline.createXLinkOut()26xout_rgb.setStreamName("rgb")2728xout_nn = pipeline.createXLinkOut()29xout_nn.setStreamName("nn")3031cam_rgb.preview.link(xout_rgb.input)32cam_rgb.preview.link(detection_nn.input)33detection_nn.out.link(xout_nn.input)3435# Pipeline is now finished, and we need to find an available device to run our pipeline36# we are using context manager here that will dispose the device after we stop using it37with depthai.Device(pipeline) as device:38 # From this point, the Device will be in "running" mode and will start sending data via XLink3940 # To consume the device results, we get two output queues from the device, with stream names we assigned earlier41 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 results44 frame = None45 detections = []4647 # Since the detections returned by nn have values from <0..1> range, they need to be multiplied by frame width/height to48 # receive the actual position of the bounding box on the image49 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)535455 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 any57 in_rgb = q_rgb.tryGet()58 in_nn = q_nn.tryGet()5960 if in_rgb is not None:61 # If the packet from RGB camera is present, we're retrieving the frame in OpenCV format using getCvFrame62 frame = in_rgb.getCvFrame()6364 if in_nn is not None:65 # when data from nn is received, we take the detections array that contains mobilenet-ssd results66 detections = in_nn.detections676869 if frame is not None:70 for detection in detections:71 # for each bounding box, we first normalize it to match the frame size72 bbox = frameNorm(frame, (detection.xmin, detection.ymin, detection.xmax, detection.ymax))73 # and then draw a rectangle on the frame to show the actual result74 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 screen76 cv2.imshow("preview", frame)7778 # at any time, you can press "q" and exit the main loop, therefore exiting the program itself79 if cv2.waitKey(1) == ord('q'):80 break818283848586878889909192939495969798