ZYNQ学习之路19.在SDx中使用xfOpenCV图像加速处理

简介

Xilinx的reVISION栈包含了一系列开发平台、算法和应用的开发资源,它支持流行的神经网络包括AlexNet, GoogleLeNet, VGG, SSD和FCN等,并且该视觉库提供了用于创建和实现CNN神经网络层的库,机器学习的元素被实现为一系列硬件加速的函数库,在应用开发层,Xilinx提供了标准的框架和库包括Caffe和OpenCV, reVISION栈同时也提供了第三方平台的开发平台,包括很多的传感器。

xfOpenCV是使用Xilinx SoC和FPGA优化硬件加速的OpenCV函数库,这些函数全部是用C/C++代码编写,使用高级综合工具(HLS)综合到FPGA中运行。本例程使用SDx2018.2和Zturn board平台进行设计。

OpenCV和xfOpenCV最主要的区别就是传统的OpenCV是在CPU(x86,ARM...)中运行,而xfOpenCV是在Xilinx SoC和FPGA中运行,使用SOC优化的代码可以比嵌入式GPU快40倍,比嵌入式CPU快100倍以上,鉴于所有的代码都是用C/C++编写,很容易移植为自己的机器视觉函数。

本文以Zturnboard为例介绍如何在SDSoC中使用OpenCV,本文在Ubuntu 16 64位,SDSoC2018.2(安装在ubuntu中)中测试通过。

一、概述

下图展示一个单传感器设计的reVISION框图:

图1-1 reVISION架构图
  • 视频数据输入(蓝色部分)
  • 使用硬件急速的内存到内存的机器视觉库(红色部分)
  • 视频数据输出(绿色部分)

1.1 平台

Xilinx提供了ZCU102和ZCU104的单传感器reVISION平台,它支持以下视频接口。

1.1.1 源

  • USB2/3接口摄像头,高达1080p60或双目1080p30.
  • HDMI 输入达4K60
  • MIPI CSI通过FMC扩展板卡连接,高达4K60

1.1.2 显示

  • HDMI输出4K60
  • DP输出4K30

1.2 设计样例

Xilinx提供了一些用于参考的设计样例,它们通常是从一个视频文件中读取每一帧进行处理,使用标准的OpenCV调用(如cv::imread()),然后使用xfopencv函数处理这一帧,最后输出为一个文件(如cv::imwrite())。例程说明了五种不同的xfopencv硬件加速视觉的OpenCV函数。

  • 双边滤波器
  • Harris滤波器
  • 密集光流
  • 双目视觉(深度检测)
  • 透视变换
  •  

二、配置系统环境

在本系列教程的基础上修改SDSoC platform。

2.1 配置文件系统

配置文件系统包含OpenCV的动态库

$ cd <plnx project>
$ petalinux-config -c rootfs
//进入菜单选择
PetaLinux Package Groups --->
    packagegroup-petalinux-opencv --->
[*]      packagegroup-petalinux-opencv
图2-1 配置rootfs包含opencv

NOTE:在首次链接OpenCV时需要联网,否则会报错!此时需要保证ubuntu能访问网络。

然后编译工程并打包

$ petalinux-build -c rootfs
$ petalinux-package --boot --format BIN --fsbl ./images/linux/zynq_fsbl.elf --fpga ./images/linux/system.bit --u-boot

将新生成的image.ub(大小会增加很多,大约50多MB)替换原来的文件新文件中增加了opencv的动态库文件,放在平台设计文件夹中即可。

图2-2 编译petalinux工程后的images/linux文件夹内容

用此镜像启动系统,查看/usr/lib目录,可以发现增加了opencv的动态库。

root@ZturnTemplate:~# ls /usr/lib
dri                                  libgphoto2.so.6.0.0                  libopencv_saliency.so.3.3.0
gconv                                libgphoto2_port                      libopencv_shape.so.3.3
gdk-pixbuf-2.0                       libgphoto2_port.so.12                libopencv_shape.so.3.3.0
gio                                  libgphoto2_port.so.12.0.0            libopencv_stereo.so.3.3
girepository-1.0                     libgstapp-1.0.so.0                   libopencv_stereo.so.3.3.0
gstreamer-1.0                        libgstapp-1.0.so.0.1202.0            libopencv_stitching.so.3.3
libGL.so.1                           libgstaudio-1.0.so.0                 libopencv_stitching.so.3.3.0
libGL.so.1.2.0                       libgstaudio-1.0.so.0.1202.0          libopencv_structured_light.so.3.3
libICE.so.6                          libgstbase-1.0.so.0                  libopencv_structured_light.so.3.3.0
libICE.so.6.3.0                      libgstbase-1.0.so.0.1202.0           libopencv_superres.so.3.3
libSM.so.6                           libgstcheck-1.0.so.0                 libopencv_superres.so.3.3.0
libSM.so.6.0.1                       libgstcheck-1.0.so.0.1202.0          libopencv_surface_matching.so.3.3
libX11-xcb.so.1                      libgstcontroller-1.0.so.0            libopencv_surface_matching.so.3.3.0
libX11-xcb.so.1.0.0                  libgstcontroller-1.0.so.0.1202.0     libopencv_tracking.so.3.3
libX11.so.6                          libgstnet-1.0.so.0                   libopencv_tracking.so.3.3.0
libX11.so.6.3.0                      libgstnet-1.0.so.0.1202.0            libopencv_video.so.3.3
libXau.so.6                          libgstpbutils-1.0.so.0               libopencv_video.so.3.3.0
libXau.so.6.0.0                      libgstpbutils-1.0.so.0.1202.0        libopencv_videoio.so.3.3
libXcomposite.so.1                   libgstreamer-1.0.so.0                libopencv_videoio.so.3.3.0
libXcomposite.so.1.0.0               libgstreamer-1.0.so.0.1202.0         libopencv_videostab.so.3.3
libXcursor.so.1                      libgstriff-1.0.so.0                  libopencv_videostab.so.3.3.0
libXcursor.so.1.0.2                  libgstriff-1.0.so.0.1202.0           libopencv_xfeatures2d.so.3.3
libXdamage.so.1                      libgsttag-1.0.so.0                   libopencv_xfeatures2d.so.3.3.0
libXdamage.so.1.1.0                  libgsttag-1.0.so.0.1202.0            libopencv_ximgproc.so.3.3
libXdmcp.so.6                        libgstvideo-1.0.so.0                 libopencv_ximgproc.so.3.3.0
libXdmcp.so.6.0.0                    libgstvideo-1.0.so.0.1202.0          libopencv_xobjdetect.so.3.3
libXext.so.6                         libgthread-2.0.so.0                  libopencv_xobjdetect.so.3.3.0
libXext.so.6.4.0                     libgthread-2.0.so.0.5200.3           libopencv_xphoto.so.3.3
libXfixes.so.3                       libgtk-3.so.0                        libopencv_xphoto.so.3.3.0
libXfixes.so.3.1.0                   libgtk-3.so.0.2200.17                liborc-0.4.so.0
libXft.so.2                          libharfbuzz.so.0                     liborc-0.4.so.0.27.0
libXft.so.2.3.2                      libharfbuzz.so.0.10400.8             libpango-1.0.so.0
libXi.so.6                           libhistory.so.7                      libpango-1.0.so.0.4000.6
libXi.so.6.1.0                       libhistory.so.7.0                    libpangocairo-1.0.so.0
libXrandr.so.2                       libjpeg.so.62                        libpangocairo-1.0.so.0.4000.6
libXrandr.so.2.2.0                   libjpeg.so.62.2.0                    libpangoft2-1.0.so.0
libXrender.so.1                      libkmod.so.2                         libpangoft2-1.0.so.0.4000.6
libXrender.so.1.3.0                  libkmod.so.2.3.2                     libpangoxft-1.0.so.0
libXtst.so.6                         libltdl.so.7                         libpangoxft-1.0.so.0.4000.6
libXtst.so.6.1.0                     libltdl.so.7.3.1                     libpci.so.3
libXxf86vm.so.1                      liblzma.so.5                         libpci.so.3.5.5
libXxf86vm.so.1.0.0                  liblzma.so.5.2.3                     libpcre.so.1
libatk-1.0.so.0                      libmediactl.so.0                     libpcre.so.1.2.9
libatk-1.0.so.0.22409.1              libmediactl.so.0.0.0                 libpixman-1.so.0
libatk-bridge-2.0.so.0               libopencv_aruco.so.3.3               libpixman-1.so.0.34.0
libatk-bridge-2.0.so.0.0.0           libopencv_aruco.so.3.3.0             libpng16.so.16
libatspi.so.0                        libopencv_bgsegm.so.3.3              libpng16.so.16.31.0
libatspi.so.0.0.1                    libopencv_bgsegm.so.3.3.0            libpython3.5m.so.1.0
libbz2.so.1                          libopencv_bioinspired.so.3.3         libreadline.so.7
libbz2.so.1.0.6                      libopencv_bioinspired.so.3.3.0       libreadline.so.7.0
libcairo-gobject.so.2                libopencv_calib3d.so.3.3             libsocketcan.so.2
libcairo-gobject.so.2.11400.10       libopencv_calib3d.so.3.3.0           libsocketcan.so.2.2.1
libcairo.so.2                        libopencv_ccalib.so.3.3              libssl.so.1.0.2
libcairo.so.2.11400.10               libopencv_ccalib.so.3.3.0            libstdc++.so.6
libcrypto.so.1.0.2                   libopencv_core.so.3.3                libstdc++.so.6.0.24
libdbus-1.so.3                       libopencv_core.so.3.3.0              libtbb.so.2
libdbus-1.so.3.14.12                 libopencv_dpm.so.3.3                 libtbbmalloc.so.2
libdrm.so.2                          libopencv_dpm.so.3.3.0               libtbbmalloc_proxy.so.2
libdrm.so.2.4.0                      libopencv_face.so.3.3                libtiff.so.5
libdvbv5.so.0                        libopencv_face.so.3.3.0              libtiff.so.5.2.6
libdvbv5.so.0.0.0                    libopencv_features2d.so.3.3          libv4l
libelf-0.170.so                      libopencv_features2d.so.3.3.0        libv4l1.so.0
libelf.so.1                          libopencv_flann.so.3.3               libv4l1.so.0.0.0
libepoxy.so.0                        libopencv_flann.so.3.3.0             libv4l2.so.0
libepoxy.so.0.0.0                    libopencv_fuzzy.so.3.3               libv4l2.so.0.0.0
libexif.so.12                        libopencv_fuzzy.so.3.3.0             libv4l2rds.so.0
libexif.so.12.3.3                    libopencv_highgui.so.3.3             libv4l2rds.so.0.0.0
libexpat.so.1                        libopencv_highgui.so.3.3.0           libv4l2subdev.so.0
libexpat.so.1.6.5                    libopencv_img_hash.so.3.3            libv4l2subdev.so.0.0.0
libffi.so.6                          libopencv_img_hash.so.3.3.0          libv4lconvert.so.0
libffi.so.6.0.4                      libopencv_imgcodecs.so.3.3           libv4lconvert.so.0.0.0
libfontconfig.so.1                   libopencv_imgcodecs.so.3.3.0         libwebp.so.7
libfontconfig.so.1.9.4               libopencv_imgproc.so.3.3             libwebp.so.7.0.0
libfreetype.so.6                     libopencv_imgproc.so.3.3.0           libwebpdemux.so.2
libfreetype.so.6.14.0                libopencv_line_descriptor.so.3.3     libwebpdemux.so.2.0.2
libgailutil-3.so.0                   libopencv_line_descriptor.so.3.3.0   libwebpmux.so.3
libgailutil-3.so.0.0.0               libopencv_ml.so.3.3                  libwebpmux.so.3.0.0
libgdk-3.so.0                        libopencv_ml.so.3.3.0                libxcb-dri2.so.0
libgdk-3.so.0.2200.17                libopencv_objdetect.so.3.3           libxcb-dri2.so.0.0.0
libgdk_pixbuf-2.0.so.0               libopencv_objdetect.so.3.3.0         libxcb-glx.so.0
libgdk_pixbuf-2.0.so.0.3608.0        libopencv_optflow.so.3.3             libxcb-glx.so.0.0.0
libgio-2.0.so.0                      libopencv_optflow.so.3.3.0           libxcb-render.so.0
libgio-2.0.so.0.5200.3               libopencv_phase_unwrapping.so.3.3    libxcb-render.so.0.0.0
libglapi.so.0                        libopencv_phase_unwrapping.so.3.3.0  libxcb-shm.so.0
libglapi.so.0.0.0                    libopencv_photo.so.3.3               libxcb-shm.so.0.0.0
libglib-2.0.so.0                     libopencv_photo.so.3.3.0             libxcb.so.1
libglib-2.0.so.0.5200.3              libopencv_plot.so.3.3                libxcb.so.1.1.0
libgmodule-2.0.so.0                  libopencv_plot.so.3.3.0              libxml2.so.2
libgmodule-2.0.so.0.5200.3           libopencv_reg.so.3.3                 libxml2.so.2.9.4
libgobject-2.0.so.0                  libopencv_reg.so.3.3.0               opkg
libgobject-2.0.so.0.5200.3           libopencv_rgbd.so.3.3                python3.5
libgphoto2                           libopencv_rgbd.so.3.3.0              ssl
libgphoto2.so.6                      libopencv_saliency.so.3.3            systemd
root@ZturnTemplate:~#

2.2 配置xfOpenCV库

将编译rootfs时生成的rootfs.tar.gz文件复制到自己的一个文件夹中(/home/software/SDSoC/rootfs),解压后得到Zynq的文件系统中的文件。

图2-3 linux文件系统解压后的路径

将该路径添加到Linux系统的环境变量中:

sudo gedit ~/.bashrc

在最后一行添加:

export SYSROOT_arm64=/home/biac/software/SDSoC/rootfs

2.3 配置xfOpenCV库

在SDx IDE中,点击Xilinx -> SDx Libraries,点击下载Xilinx xfOpenCV Library。

图2-4 在SDx IDE中下载xfOpenCV

NOTE:下载的库可以被添加到任何工程中。

三、测试opencv库

新建一个SDSoC应用工程,命名为opencv_lab1。

添加main.cpp文件,编辑内容如下:

#include <iostream>
#include <opencv2/opencv.hpp>

// colordetect
// Description:
// Will detect the colors from the thresholds provided
// Inputs:
//	- in_img
//  - nLowThresh
//  - nHighThresh
// Output:
//  - out_img
void colordetect(cv::Mat &_src,
				cv::Mat &_dst,
				unsigned char nLowThresh[3][3],
				unsigned char nHighThresh[3][3]) {

	// Temporary matrices for processing
	cv::Mat mask1, mask2, mask3, _imgrange, _imghsv;

	// Convert the input to the HSV colorspace. Using BGR here since it is the default of OpenCV.
	// Using RGB yields different results, requiring a change of the threshold ranges
	cv::cvtColor(_src, _imghsv, cv::COLOR_BGR2HSV);

	// Get the color of Yellow from the HSV image and store it as a mask
	cv::inRange(_imghsv, cv::Scalar(nLowThresh[0][0], nLowThresh[0][1], nLowThresh[0][2]), cv::Scalar(nHighThresh[0][0], nHighThresh[0][1], nHighThresh[0][2]), mask1);

	// Get the color of Green from the HSV image and store it as a mask
	cv::inRange(_imghsv, cv::Scalar(nLowThresh[1][0], nLowThresh[1][1], nLowThresh[1][2]), cv::Scalar(nHighThresh[1][0], nHighThresh[1][1], nHighThresh[1][2]), mask2);

	// Get the color of Red from the HSV image and store it as a mask
	cv::inRange(_imghsv, cv::Scalar(nLowThresh[2][0], nLowThresh[2][1], nLowThresh[2][2]), cv::Scalar(nHighThresh[2][0], nHighThresh[2][1], nHighThresh[2][2]), mask3);

	// Bitwise OR the masks together (adding them) to the range
	_imgrange = mask1 | mask2 | mask3;

	cv::Mat element = cv::getStructuringElement( 0,cv::Size(3, 3), cv::Point(-1, -1));

	cv::erode(_imgrange, _dst, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT);

	cv::dilate(_dst, _dst, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT);

	cv::dilate(_dst, _dst, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT);

	cv::erode(_dst, _dst, element, cv::Point(-1, -1), 1, cv::BORDER_CONSTANT);
}

int main(int argc, char **argv)
{
	printf("Test for SDSoC platform\n");
	//Create the input/output cv::Mat objects
	cv::Mat in_img, out_img;
	cv::Mat imghsv, imgrange, imgerode, imgdilate1, imgdilate2;

	// Define the low and high thresholds
	// Want to grab 3 colors (Blue, Green, Orange) for teh input image
	unsigned char nLowThresh[3][3] = { { 110, 150, 20 }, // Lower boundary for Blue
                                      { 38, 0, 20 }, // Lower boundary for Green
                                      { 10, 150, 20 } }; // Lower boundary for Orange
	unsigned char nHighThresh[3][3] = { { 130, 255, 255 }, // Upper boundary for Blue
                                         { 75, 125, 255 }, // Upper boundary for Green
                                         { 25, 255, 255 } }; // Upper boundary for Orange
    // Read an image
	in_img = cv::imread("rock_landscape.jpg", 1);
	if (!in_img.data) {
         return -1;
	}

	// Create the output image to match the input image (CV_8U)
	int height = in_img.rows;
	int width = in_img.cols;
	out_img.create(height, width, CV_8U);

	// Run the input and thresholds into the colordect function
	colordetect(in_img, out_img, nLowThresh, nHighThresh);

	// Write out the input image and the output image
	cv::imwrite("output.png", out_img);
	cv::imwrite("input.png", in_img);

	return 0;
}

四、配置编译环境

下载完库文件之后需要将库路径添加到应用工程中。

点击Xilinx -> SDx Libraries,选中Xilinx xfOpenCV Library,点击Add to project下拉框,选择自己的应用工程即可。

图4-1 将SDx库添加到工程中

此时,所有的opencv头文件和库都将被复制到工程目录的libs目录下(工程目录中的libs文件夹中),所有需要设置的选项也相应的自动进行设置好了。

图4-2 添加xfOpencv库后的目录

在编译选项中,opencv_前缀的链接库都自动添加到工程的设置中。

图4-3 自动添加opencv链接库

添加路径:右键点击工程,选择Properties -> C/C++ General -> Paths and Symbols -> Includes,在GNU C和GNU C++中都添加xfopencv的include路径。如图1-9所示。

图4-4 添加xfopencv的库路径

添加链接:右键点击工程,选择Properties -> C/C++ Build -> Tool Settings -> SDSCC Compiler -> Inferred Options -> Software Platform

Software platform Inferred Flags中输入:

-I${SYSROOT_arm64}/usr/include -hls-target 1

Properties -> C/C++ Build -> Tool Settings -> SDS++ Compiler -> Inferred Options -> Software Platform中执行同样的操作。

Properties -> C/C++ Build -> Tool Settings -> SDS++ Linker -> Miscellaneous -> Linker Flags中添加:

--sysroot=${SYSROOT_arm64} -Wl,-rpath-link=${SYSROOT_arm64}/lib,-rpath-link=${SYSROOT_arm64}/usr/lib

编译工程。

可能出现错误,根据错误进行修改

错误提示

arm-linux-gnueabihf-g++.exe: error: unrecognized command line option '-mstrict-align'; did you mean '-Wstrict-aliasing'?

解决方法:在Properties -> C/C++ Build -> Settings -> SDSCC Compiler和 SDS++ Compiler中的Miscellaneous,删除other flags中的编译选项,只留-c -fmessage-length=0 -MT"$@" -hls-target 1。

编译成功后, 将sd_card目录中的所有文件复制到SD卡中,并将例程中的图片复制到SD卡中。

执行程序:

$ mount /dev/mmcblk0p1 /mnt/
$ cd /mnt/
$ ./opencv_lab1.elf
$ ls 
System Volume Information
UPDATE
image.ub
input.png
opencv_lab1.elf
output.png
rock_landscape.jpg
sds_trace_data.dat

执行成功后在SD卡中生成了两个图片文件: input.png和output.png。

图4-5 output.jpg

五、硬件加速opencv

以xilinx在xfopencv中提供的样例做测试,复制xfopencv/examples/histogram目录中的C文件到自己的SDx工程中,安装前文所讲配置编译环境。

图5-1 histogram工程文件结构

添加Hardware Functions:

展开libs/include/imgproc/xf_histogram.hpp/xf

右键选择calcHist函数,选择Toggle HW/SW,将dilate函数作为硬件实现的函数,默认时钟为100MHz。

图5-2 添加硬件加速函数

编译完成后,拷贝sd_card中所有文件到SD开根目录,执行程序:

mount /dev/mmcblk0p1 /mnt/
cd /mnt/
./opencv_lab1.elf im0.jpg
Start sw accel function
elapsed time 9366176
Start hw accel function
elapsed time 13883070

可以看到硬件加速的函数自行时间比软件还要长,后面讲分析原因。

参考资料

[1] ug1233-xilinx-opencv-user-guide.pdf

[2] https://github.com/Xilinx/Revision-Getting-Started-Guide/tree/2018.2-tutorials

[3] https://github.com/Xilinx/SDSoC-Tutorials/tree/master/opencv-to-xfopencv-migration-tutorial

[4] https://blog.csdn.net/lulugay/article/details/83305194


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值