新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > Xilinx Zynq使用HLS实现OpenCV的开发流程

Xilinx Zynq使用HLS实现OpenCV的开发流程

作者:郭丰收时间:2014-03-13来源:电子产品世界收藏

  摘要:首先介绍中图像类型和函数处理方法,之后通过设计实例描述在中调用库函数实现图像处理的几个基本步骤,阐述从设计到RTL转换综合的开发流程。

本文引用地址:http://www.eepw.com.cn/article/234670.htm

  关键词:;;;OpenCV;Zynq AP SOC

  开源计算机视觉 (OpenCV) 被广泛用于开发计算机视觉应用,它包含2500多个优化的视频函数的函数库并且专门针对台式机和GPU进行优化。Xilinx 高层次综合工具能够使用C/C++ 编写的代码直接创建RTL硬件,显著提高设计生产力,同时,Xilinx Zynq全SOC系列器件嵌入双核ARM Cortex-A9将软件能力与FPGA的硬件可编程能力实现完美结合,以低功耗和低成本等系统优势实现单芯片无以伦比的系统性能、灵活性、可扩展性,加速图形处理产品设计上市时间。OpenCV拥有成千上万的用户,而且OpenCV的设计无需修改即可在 Zynq器件的ARM处理器上运行,但是利用OpenCV实现的高清处理经常受外部存储器的限制,尤其是存储带宽会成为性能瓶颈,存储访问也限制了功耗效率。使用Xilinx公司的VivadoHLS高级语言综合工具,可以轻松实现OpenCV C++视频处理设计到RTL代码的转换,输出Zynq的硬件加速器或者直接在FPGA上实现实时硬件视频处理功能。同时,Xiinx公司的Zynq All-programmable SoC是实现嵌入式计算机视觉应用的好方法,解决了在单一处理器上实现视频处理性能低功耗高的限制,Zynq高性能可编程逻辑和嵌入式ARM内核,是一款性能功耗最优化的图像处理集成式解决方案。

  1 OpenCV中图像IplImage, CvMat, Mat 类型的关系和VivadoHLS中图像hls::Mat类型

  OpenCV中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage,这三种类型都可以代表和显示图像,但是,Mat类型侧重于计算,数学性较高。而CvMat和IplImage类型更侧重于“图像”,OpenCV对其中的图像操作(缩放、单通道提取、图像阈值操作等)进行了优化。

  1.1 OpenCV中的Mat矩阵类型

  在OpenCV中,Mat是一个多维的密集数据数组。可以用来处理向量和矩阵、图像、直方图等等常见的多维数据。

  Mat类型较CvMat与IplImage类型来说,有更强的矩阵运算能力,支持常见的矩阵运算。在计算密集型的应用当中,将CvMat与IplImage类型转化为Mat类型将大大减少计算时间花费。

  1.2 OpenCV中的CvMat与IplImage类型

  在openCV中,CvMat和IplImage类型更侧重于“图像”,尤其是对其中的图像操作进行一定程度的优化。OpenCV没有向量(vector)的数据结构,但当我们要表示向量时,需要用矩阵数据表示。但是,CvMat更抽象,它的元素数据类型并不仅限于基础数据类型,而且可以是任意的预定义数据类型,比如RGB或者别的多通道数据。、

  在OpenCV类型关系上,我们可以说IplImage类型继承自CvMat类型,当然还包括其他的变量将之解析成图像数据。IplImage类型较之CvMat多了很多参数,比如depth和nChannels。IplImage对图像的另一种优化是变量origin原点,为了弥补这一点,OpenCV允许用户定义自己的原点设置。

  1.3 VivadoHLS中图像数据类型hls::Mat<>

  VivadoHLS视频处理函数库使用hls::Mat<>数据类型,这种类型用于模型化视频像素流处理,实质等同于hls::steam<>流的类型,而不是OpenCV中在外部memory中存储的matrix矩阵类型。因此,在用vivadoHLS实现OpenCV的设计中,需要将输入和输出HLS可综合的视频设计接口,修改为Video stream接口,也就是采用HLS提供的video接口可综合函数,实现AXI4 video stream到VivadoHLS中hls::Mat<>类型的转换。

  2 使用VivadoHLS实现OpenCV到RTL代码转换的流程

  2.1 OpenCV设计中的权衡

  OpenCV图像处理是基于存储器帧缓存而构建的,它总是假设视频frame数据存放在外部DDR 存储器中,因此,OpenCV对于访问局部图像性能较差,因为处理器的小容量高速缓存性能不足以完成这个任务。而且出于性能考虑,基于OpenCV设计的架构比较复杂,功耗更高。在对分辨率或帧速率要求低,或者在更大的图像中对需要的特征或区域进行处理是,OpenCV似乎足以满足很多应用的要求,但对于高分辨率高帧率实时处理的场景下,OpenCV很难满足高性能和低功耗的需求。

  基于视频流的架构能提供高性能和低功耗,链条化的图像处理函数减少了外部存储器访问,针对视频优化的行缓存和窗口缓存比处理器高速缓存更简单高效,更易于使用VivadoHLS 在FPGA部件中采用数据流优化来实现。

  VivadoHLS对OpenCV的支持,不是指可以将OpenCV的函数库直接综合成RTL代码,而是需要将代码转换为可综合的代码,这些可综合的视频库称为HLS视频库,由VivadoHLS提供。

  OpenCV函数不能直接通过HLS进行综合,因为OpenCV函数一般都包含动态的内存分配、浮点以及假设图像在外部存储器中存放或者修改。

  VivadoHLS视频库用于替换很多基本的 OpenCV函数,它与OpenCV具有相似的接口和算法,主要针对在FPGA架构中实现的图像处理函数,包含了专门面向FPGA的优化,比如定点运算而非浮点运算(不必精确到比特位),片上的行缓存(line buffer)和窗口缓存(window buffer)。图2.1展示了在Xilinx Zynq AP SOC器件上实现视频处理的系统结构。

  图2.1 Zynq视频处理系统结构

  2.2 在FPGA/Zynq开发中使用VivadoHLS实现OpenCV的设计流程

  设计开发流程主要有如图2.2三个步骤。

  1. 在计算机上开发OpenCV应用,由于是开源的设计,采用C++的编译器对其进行编译,仿真和debug,最后产生可执行文件。这些设计无需修改即可在 ARM内核上运行OpenCV应用。

  2. 使用I/O函数抽取FPGA实现的部分,并且使用可综合的VivadoHLS Video库函数代码代替OpenCV函数的调用。

  3. 运行HLS生成RTL代码,在VivadoHLS工程中启动co-sim,HLS工具自动重用OpenCV的测试激励验证产生的RTL代码。在Xilinx的ISE或者Vivado开发环境中做RTL的集成和SoC/FPGA实现。

  图2.2 在FPGA/Zynq设计中使用OpenCV的开发流程

  2.2.1 VivadoHLS视频库函数

  HLS视频库是包含在hls命名空间内的C++代码。#include “hls_video.h”

  HLS视频库与OpenCV等具有相似的接口和等效的行为,例如:

  OpenCV库:cvScale(src, dst, scale, shift);

  HLS视频库:hls::Scale<...>(src, dst, scale, shift);

  HLS视频库的一些构造函数具有类似的或替代性的模板参数,例如:

  OpenCV库:cv::Mat mat(rows, cols, CV_8UC3);

  HLS视频库:hls::Mat mat(rows, cols);

  ROWS和COLS指定处理的最大图像尺寸。

  表1 VivadoHLS视频处理函数库

  2.2.2 VivadHLS实现OpenCV设计的局限性

  首先,必须用HLS视频库函数代替OpenCV调用。

  其次,不支持OpenCV通过指针访问帧缓存,可以在HLS中使用VDMA和 AXI Stream adpater函数代替。

  再者,不支持OpenCV的随机访问。HLS对于读取超过一次的数据必须进行复制,更多的例子可以参见见hls::Duplicate()函数。

  最后,不支持OpenCVS的In-place更新,比如 cvRectangle (img, point1, point2)。

  下表2列举了OpenCV中随机访问一帧图像处理对应HLS视频库的实现方法。

  表2 OpenCV和HLS中对一帧图像像素访问对应方法

 

OpenCV

HLS视频库

读操作

pix = cv_mat.at(i,j)

pix = cvGet2D(cv_img,i,j)

hls_img>> pix

写操作

cv_mat.at(i,j) = pix

cvSet2D(cv_img,i,j,pix)

hls_img<< pix

  2.3 用HLS实现OpenCV应用的实例(快速角点滤波器image_filter)

  我们通过快速角点的例子,说明通常用VivadoHLS实现OpenCV的流程。首先,开发基于OpenCV的快速角点算法设计,并使用基于OpenCV的测试激励仿真验证这个算法。接着,建立基于视频数据流链的OpenCV处理算法,改写前面OpenCV的通常设计,这样的改写是为了与HLS视频库处理机制相同,方便后面步骤的函数替换。最后,将改写的OpenCV设计中的函数,替换为HLS提供的相应功能的视频函数,并使用VivadoHLS综合,在Xilinx开发环境下在FPGA可编程逻辑或作为Zynq SOC硬件加速器实现。当然,这些可综合代码也可在处理器或ARM上运行。

  2.3.1 设计基于OpenCV的视频滤波器设计和测试激励

  在这个例子中,首先设计开发完全调用OpenCV库函数的快速角点滤波器设计opencv_image_filter.cpp和这个滤波器的测试激励(不在本例中展示),测试激励用于仿真验证opencv_image_filter算法功能。OpenCV算法实现的设计代码如下:

  void opencv_image_filter(IplImage* src, IplImage* dst)

  {

  IplImage* gray = cvCreateImage( cvGetSize(src), 8, 1 );

  std::vectorkeypoints;

  cv::Mat gray_mat(gray,0);

  cvCvtColor(src, gray, CV_BGR2GRAY );

  cv::FAST( gray_mat, keypoints, 20, true);

  cvCopy( src,dst);

  for (inti=0;i

  {

  cvRectangle(dst, cvPoint(keypoints[i].pt.x-1,keypoints[i].pt.y-1),

  cvPoint(keypoints[i].pt.x+1,keypoints[i].pt.y+1), cvScalar(255,0,0),CV_FILLED);

  }

  cvReleaseImage( &gray );

  }

  例子2.3.1 通常的OpenCV视频处理代码opencv_image_filter.cpp

  上面的例子是直接调用OpenCV在处理器上软件应用实现的例子,可以看到在算法设计中直接调用opencV库函数,测试激励读入图像,经过滤波器处理输出的图像保存分析。可以看到,算法的处理基于IPIimage类型,输入和输出图像都使用此类型。

  2.3.2 使用IO函数和Vivado HLS视频库替换OpenCV函数库

  需要特别说明的是,Xilinx公司通常使用的视频处理模块是基于AXI4 streaming协议进行不同模式见像素数据的交互,也就是我们所说的AXI4 video接口协议格式。为了和Xilinx视频库接口协议统一,VivadoHLS提供了视频接口函数库,用于从OpenCV程序中抽取需要进行RTL综合转换的顶层函数,并把这些可综合的代码和OpenCV不可综合转换的代码进行隔离。然后,对需要综合转换为RTL代码的OpenCV函数,用Xilinx VivadoHLS提供相应功能的可综合video函数进行替换。最后在C/C++编译环境下仿真验证OpenCV代码和替换video函数后功能的一致性,并在VivadoHLS开发环境中做代码综合和产生RTL代码的co-sim混合仿真验证。

  VivadoHLS可综合的视频接口函数:

  Hls::AXIvideo2Mat 转换AXI4 video stream到hls::Mat表示格式

  Hls::Mat2AXIvideo 转换hls::Mat数据格式到AXI4 video stream

  首先,我们对2.3.1中OpenCV的设计进行改写,改写的代码还是完全基于OpenCV的函数,目的是为了对视频的处理机制基于视频流的方式,与VivadoHLS视频库提供函数的处理机制一致。

  其次,使用Vivado HLS视频库替代标准OpenCV函数,并使用可综合的视频接口函数,采用video stream的方式交互视频数据。用于FPGA的硬件可综合模块由VivadoHLS视频库函数与接口组成,我们用hls命名空间中的相似函数代替OpenCV函数,增加接口函数构建AXI4 stream类型的接口。

  void image_filter(AXI_STREAM& input, AXI_STREAM& output, int rows, int cols)

  {

  hls::Mat _src(rows,cols);

  hls::Mat _dst(rows,cols);

  hls::AXIvideo2Mat(input, _src);

  hls::Mat src0(rows,cols);

  hls::Mat src1(rows,cols);

  hls::Mat mask(rows,cols);

  hls::Matdmask(rows,cols);

  hls::Scalar<3,unsigned char> color(255,0,0);

  hls::Duplicate(_src,src0,src1);

  hls::Mat gray(rows,cols);

  hls::CvtColor(src0,gray);

  hls::FASTX(gray,mask,20,true);

  hls::Dilate(mask,dmask);

  hls::PaintMask(src1,dmask,_dst,color);

  hls::Mat2AXIvideo(_dst, output);

  }

  例子2.3.2 采用VivadoHLS视频库替换后可综合的设计opencv_image_filter.cpp

  最后,在vivadoHLS开发环境下综合例子2.3.2.2的设计,产生RTL代码并重用OpenCV的测试激励验证RTL代码功能。

  3 VHLS实现OpenCV设计流程总结

  OpenCV函数可实现计算机视觉算法的快速原型设计,并使用VivadoHLS工具转换为RTL代码,在FPGA可编程逻辑上或者Zynq SoC逻辑上作为硬件加速器,实现高分辨率高帧率的实时视频处理。计算机视觉应用与生俱来的异构特性,使其需要软硬件相结合的实现方案,采用Vivado HLS视频库能加快OpenCV函数向FPGA或Zynq SOC全可编程架构的映射。

  参考文献:

  [1]Vivado Design Suite User Guide: High-LevelSynthesis(UG902).

  [2]Accelerating OpenCV applications with Zynq using VivadoHLS video libraries(XAPP1167)

  [3]Bradski G,Kaebler “A.Learning OpenCV”.ISBN 978-7-302-20993-5

  [4]Implementing Memory structure for video processing in the vivadoHLStool(XAPP793)

  [5] Rafael C.Gonzalez,Richard E.Wood “Digital Image Processing, Third Edition”ISBN 978-7-121-11008-5

滤波器相关文章:滤波器原理


滤波器相关文章:滤波器原理


c++相关文章:c++教程


cvt相关文章:cvt原理




评论


相关推荐

技术专区

关闭