中国 · 南京 · 栖霞区紫东路2号紫东国际创意园B3-2幢5F
+86-18994094214 (仅工作日:8:30~17:30)
contact@oakchina.cn

OpenCV CEO教你用OAK(一):OAK和DepthAI入门

OpenCV CEO教你用OAK(一):OAK和DepthAI入门

参考资料:地址

这是OAK智能深度相机编程专栏的第一篇文章,OAK-DOAK-D-Lite都是3D人工智能相机。

这个系列的下一篇文章请点击这里查看。

什么是3D人工智能?

3D人工智能让计算机视觉能够基于以下两种感知进行同步决策:

  1. 视觉识别感知:这是人工智能在视觉上 “看到 “和 “解释 “其周围事物的能力。例如,OAK-D的RGB相机与相机内置的神经网络的处理器NPU连接,用于神经网络加速,检测相机所看到的场景中的一只猫、一个人或一辆车等物体。
  2. 深度定位感知:这是人工智能理解物体的空间坐标位置、物理大小的能力。

3D人工智能的想法是受人类视觉的启发,我们用眼睛来理解我们周围环境和事物。此外,我们用双眼(即立体视觉)来感知事物离我们有多远。

OAK的RGB-D深度和点云示例(点击图片查看代码)

OAK-D和OAK-D-Lite是3D AI相机

OpenCV的OAK-D和OAK-D-Lite包括以下重要组成部分:

  1. 4K RGB相机:放置在中心的RGB相机可以捕捉到高分辨率的4k画面。通常情况下,这种相机是用于视觉识别的。
  2. 立体深度相机:这是一个由两个摄像头组成的系统(“立体”一词是指两台),用于深度空间计算感知,也能够用于视觉识别(3D神经网络推理)。
  3. Intel Myriad™X VPU:这是OAK的“大脑”。它是一个强大的处理器,能够运行yolo v4、yolo v5 yolo x等各种主流的神经网络,同时能从立体图像中实时创建深度图,将识别结果和深度计算结果进行内部融合,通过API接口就能得到物体的种类和坐标位置。

OAK-D和OAK-D-Lite的应用

OAK-D正被广泛应用于各个领域,在2021年的OpenCV AI竞赛中,你可以看到很多应用。

你可以在编程教育新生儿智能监控残疾人辅助技术AR/VR使用无人机进行仓库检查智能农业体育分析零售机器人,甚至广告机器人中看到OAK的身影。

你也可以在Indiegogo这个众筹页面看到更多用OAK-D和OAK-D-Lite做的超赞项目。

很兴奋?想学习如何用OAK设备编程?请往下细看。

目录

  1. OAK-D与OAK-D-Lite对比
  2. 安装DepthAI
  3. DepthAI管道与获取左深度摄像头数据
  4. 创建完整的深度视觉管道
  5. 输出
  6. 结尾

1.OAK-D与OAK-D-Lite对比

就功能而言,这两个相机几乎是相同的。你几乎可以用OAK-D-Lite做到OAK-D所能做到的一切,初学者应该不会注意到太大的区别,不过这两个相机确实有一些参数区别。OAK-D-Lite外观时尚,更轻、更便宜,OAK-D功能略微全面一些。2022年我们会推出增加了结构光和TOF传感器的OAK-D-Pro相机,敬请期待。

特性/规格OAK-DOAK-D-Lite
RGB摄像头1200万像素,4k,高达60fps1300万像素,4k,高达60fps
黑白摄像头1280x800p,120fps,全局快门640x480p,120fps,全局快门
IMU×
USB-C,电源插孔√,√√,×
VPUMyriad-X, 4T算力Myriad-X, 4T算力

OpenCV AI Kit

2.安装DepthAI

点击图片查看教程

使用OAK-D或OAK-D-Lite最棒的是没有外部硬件或软件的依赖,因为它集成了硬件、固件和软件,体验极其丝滑。DepthAI可以看做是API(应用编程接口),我们通过它对OAK-D进行编程。它是跨平台的,所以你不需要担心不兼容你的操作系统。接下来,让我们继续通过启动终端或Powershell来安装API。如果你的网络信号不错,这个过程应该只需要30秒。

git clone https://github.com/luxonis/depthai.git
cd depthai
python3 install_requirements.py
python3 depthai_demo.py

你也可以按照这个文档>>来操作

3.DepthAI管道与获取左深度摄像头数据

节点是具有各种功能的单元模块,管道是连接各种节点的数据流通道。让我们通过下面的插图来理解DepthAI管道,在图中,我们显示了执行给定命令时相机内部发生的情况。这是一个非常简单的管道,通过这个管道,我们可以从左边的摄像头捕捉画面。

1)创建管道

这里,我们实例化管道对象。

import depthai as dai
pipeline = dai.Pipeline()
Instantiate pipeline

2)创建摄像头节点

通过下面的代码,我们创建了单个摄像头节点。它现在还没有任何功能,只是认出了单个摄像头。

mono = pipeline.createMonoCamera()
Initiate mono camera node

3)选择相机

要访问摄像头,比如我们现在要访问左边的摄像头,我们需要选择它,用SetBoardSocket即可。它还在内部创建了一个输入节点X-LinkIn,X-Link是摄像头与主机(计算机)通信的一种机制。

mono.setBoardSocket(dai.CameraBoardSocket.LEFT)
Selecting mono camera

4)创建XLinkOut节点并获取帧

要获得输出,我们需要创建X-LinkOut节点。相机可以有数个其他输出,比如来自右相机的数据流,或者来自RGB相机的数据流,或者其他一些我们现在不需要关心的输出。本例中,它被命名为“Left”,这样它就不会与其他输出冲突。最后,我们将单个黑白摄像头的输出作为输入连接到X-LinkOut节点。

xout = pipeline.createXLinkOut()
xout.setStreamName("left")
mono.out.link(xout.input)
Linking output to X-LinkOut node

以上命令只是为设备做准备,它并没有真正地处理任何事情。所有的命令都在主机内部运行。你可以把它看作是一个预处理步骤。通过下面的代码片段,我们将管道从主机传输到OAK中。

现在,我们可以从X-LinkOut节点获取输出帧。注意,X-LinkOut节点的输出不是单个帧。实际上,它创建了一个可以存储多个帧的序列。这对于某些需要多帧的应用可能是有用的,比如视频编码。但在我们的例子中,我们不需要多帧。所以,现在让我们把它保留为默认的单帧。如你所见,序列使用指定流GetOutputQueue的方法。

接下来,我们查询序列以提取帧。此时,帧图从设备传输到主机。帧图属于Depthai.ImgFrame这个类别,此类别可以有几种类型。为了使OpenCV好用,我们使用了GetCvFrame,它以numpy数组的形式返回图像。我们的基本管道就此结束。

with dai.Device(pipeline) as device:
queue = device.getOutputQueue(name="left")
frame = queue.get()
imOut = frame.getCvFrame()

现在让我们为左右摄像头建立一个完整的管道,我们将使用来自左右黑白摄像头的输出来显示并排的视图和合并的视图。

4.创建完整的深度视觉管道

Stereo vision pipeline OAK-D

尽管DepthAI库同时支持Python和C++,但C++还不是一个稳定的版本。因此,在这篇文章中,我们将重点放在python上。

此文发出时间是2022年1月份,现在depthai的C++库已经比较稳定了,可放心使用!

导入库

import cv2
import depthai as dai
import numpy as np

提取帧的函数

它从序列中查询帧,将其传输到主机,并将帧转换为numpy数组。

def getFrame(queue):
# Get frame from queue
frame = queue.get()
# Convert frame to OpenCV format and return
return frame.getCvFrame()

选择黑白摄像头的函数

这里,为管道创建一个摄像头节点。然后,我们使用setResolution。这个setResolution有下列属性可供选择。

  • 700_P(1280×720 p)
  • 800_P(1280×800 P)
  • 400_P(640×400 p)
  • 480_P(640×480 p)

在我们的例子中,我们将分辨率设置为640×400 p。通过使用isLeft布尔值,board socket被设置LEFT或RIGHT。

def getMonoCamera(pipeline, isLeft):
  # Configure mono camera
  mono = pipeline.createMonoCamera()

  # Set Camera Resolution
    mono.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P)
  if isLeft:
      # Get left camera
      mono.setBoardSocket(dai.CameraBoardSocket.LEFT)
  else :
      # Get right camera
      mono.setBoardSocket(dai.CameraBoardSocket.RIGHT)
  return mono

主要函数

管道和设置摄像头

我们首先创建管道并设置左、右摄像头。预定义函数GetMonoCamera在内部创建X-Linkin节点并返回单摄像投输出。然后相机的输出被绑定到X-LinkOut节点。

if __name__ == '__main__':
   pipeline = dai.Pipeline()

    # Set up left and right cameras
    monoLeft = getMonoCamera(pipeline, isLeft = True)
    monoRight = getMonoCamera(pipeline, isLeft = False)

    # Set output Xlink for left camera
    xoutLeft = pipeline.createXLinkOut()
    xoutLeft.setStreamName("left")

    # Set output Xlink for right camera
    xoutRight = pipeline.createXLinkOut()
    xoutRight.setStreamName("right")

    # Attach cameras to output Xlink
    monoLeft.out.link(xoutLeft.input)
    monoRight.out.link(xoutRight.input)

将管道传输到设备

一旦安装就绪,我们将管道传输到设备(摄像头),左、右摄像头输出的序列用各自的名称定义。帧容量被设置为maxSize,在本例中,这只是单一的帧。我们还创建了一个命名窗口,以便稍后用于显示输出。这个sideBySide 是一个用于切换摄像头视图的布尔值(并排或合并视图)。

with dai.Device(pipeline) as device:
    # Get output queues.
    leftQueue = device.getOutputQueue(name="left", maxSize=1)
    rightQueue = device.getOutputQueue(name="right", maxSize=1)

    # Set display window name
    cv2.namedWindow("Stereo Pair")
    # Variable used to toggle between side by side view and one
    frame view.
    sideBySide = True

主循环

到目前为止,我们已经创建了一个管道,将摄像头输出链接到X-LinkOut节点并获得序列。现在,是时候查询帧,并通过预定义的getFrame将它们转换为OpenCV可用的numpy数组格式了。对于并排视图,帧在numpy的帮助下水平连接。Hstack(水平堆叠)函数。对于重叠输出,我们只是通过将强度降低2倍来增加帧。

键盘输入打破循环,切换显示(并排视图和合并视图)。

while True:
    # Get left frame
    leftFrame = getFrame(leftQueue)
    # Get right frame
    rightFrame = getFrame(rightQueue)

    if sideBySide:
        # Show side by side view
        imOut = np.hstack((leftFrame, rightFrame))
    else :
        # Show overlapping frames
        imOut = np.uint8(leftFrame/2 + rightFrame/2)

    # Display output image
    cv2.imshow("Stereo Pair", imOut)

    # Check for keyboard input
    key = cv2.waitKey(1)
    if key == ord('q'):
        # Quit when q is pressed
        break
    elif key == ord('t'):
        # Toggle display when t is pressed
        sideBySide = not sideBySide

5.输出

Mono camera outputs side by side view
并排视图
Mono camera outputs side view
合并视图

6.结尾

关于OpenCV AI Kit with Depth的介绍到此结束,我希望你喜欢这种轻松的阅读,并知晓如何用OAK-D。在下一篇文章中,我们将介绍如何从OAK-D中获取深度图的管道。

参考文献

DepthAI文档

OpenCV商店

Kickstart页面

中文文档

Tags:

索引