在这篇文章中我们会给大家介绍一个具体的案例,基于安富利Ultra96 开发板的OpenCV 光流的项目。这块开发板是一款基于赛灵思16nm Zynq MPSOC 芯片性价比很不错的开发板,十分适合于机器视觉、人工智能等嵌入式计算的应用。赛灵思的Zynq 系列器件是一款出色的SOC器件,包括ARM处理器部分(PS)和可编程逻辑部分(PL),可以有效地实现软硬件的协同工作,更好的发挥器件的资源,在汽车、消费类、测试仪器、工业等领域都有广泛应用。
通过这个案例,我们可以了解到赛灵思的Zynq 器件可以支持流行的python 语言的开发,同时也支持 OpenCV 应用的开发。借助于PYNQ 框架,可以大大加速python 语言在嵌入式的开发效率。同时在PYNQ 里面增加了对 hardware library – overlay 的支持,提供了专门的 python API 对overlay的调用操作,可以动态加载 bitstream。在这个optical flow 的案例中,我们比较了用软件实现的Farneback光流算法和用硬件逻辑实现的dense non-pyramidal Lucas-Kanade光流算法之间的性能差异。
光流 optical flow 是一个比较复杂的算法函数,主要是用来检测在一个画面中的物体运动情况。光流有几种很相似的算法,在这个案例我们采用了OpenCV的 Farneback 算法和赛灵思 xFOpenCV 库里的 dense non-pyramidal Lucas-Kanade 算法。同时我们既可以采用SD卡里存储好的图片也可以用外接 USB 摄像头实时采集图片来作为输入。
借助这个案例,大家可以更加深入的了解下面几点:
Overlay:硬件库
- 不同的算法可以实现在不同的bitstream 里面,bitstream 可以简单理解为在器件的逻辑部分PL 实现的算法硬件加速器
- 可以用API 来访问 overlay (下载 bitstream 十分容易)
Python
- PYNQ 可以支持python在赛灵思Zynq平台上编程
- Python 是一个高效率的编程语言
Jupyter Notebook
- 这是一个交互式的计算环境,容许工程师创建 notebook 文档,包括:编写代码、可交互的小工具、画图、注释文字、嵌入图片和视频等。
- 这个工具容许工程师在浏览器环境下编辑和运行python代码

图1: 光流实现的软件和硬件堆栈
从图1可以清楚地看出软件和硬件实现的区别,软件的实现就是传统的openCV 函数在python 语言里调用,然后运行在Zynq 器件的PS 处理器部分,在这个实现中没有用到逻辑的PL 部分。从硬件实现来看,仍然是采用python 语言编程,不过目前是调用赛灵思优化后的openCV library – xFOpenCV,这些 library都有对应的硬件overlay 在PL 里面来实现。最后我们来比较2种实现方法的性能,包括处理的时间和处理的帧率指标。
结果说明:


图2: 光流实现的软件和硬件堆栈


图3:结果性能比较
代码参考:
下面是调用算法 overlay 和 存储管理器的代码,属于程序的预处理部分。

图4:初始化代码参考
这是软件环境实现的代码

图5:软件代码参考
下面是硬件环境实现的代码,主要有2处的区别,用红色标注了。
- 变量存储的定义:通常在软件设计只需要考虑存储空间大小就可以了,因为存储的架构基本是固定的。但是在硬件设计里要考虑硬件实现的因素,包括:定点和浮点,数据位数,存储空间的具体长宽尺寸以及是采用阵列 Array、 FIFO、双口RAM等实现的架构。因为在硬件设计里,存储空间和架构可以完全自定义,尤其在嵌入式产品里,要尽可能节约存储资源。
- 光流函数的调用:这是和软件程序的主要区别,在硬件代码里是通过 API 调用 overlay 来操作,这个光流函数其实是在Zynq 器件的PL 里实现的,也就是OpenCV算法硬件加速的概念。

图6:硬件代码参考
最后再简单介绍下赛灵思的 xfOpenCV library, 这是个针对赛灵思器件优化的OpenCV的库, 主要面对在赛灵思Zynq-7000 和Zynq MPSOC 器件上的嵌入式开发者,当然也可以运行在纯 FPGA 器件上。借助赛灵思开发工具SDx 或者目前的 Vitis 工具链,工程师可以在纯软件的开发环境中调用这些计算机视觉的函数,在FPGA 做硬件加速处理。另外,xfOpenCV 库的函数功能也很类似传统的OpenCV 函数,这样方便开发者理解和做移植。关于赛灵思xfOpenCV 详细的描述请参考赛灵思的UG1233 用户手册。