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 平台
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
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的动态库文件,放在平台设计文件夹中即可。
用此镜像启动系统,查看/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的文件系统中的文件。
将该路径添加到Linux系统的环境变量中:
sudo gedit ~/.bashrc
在最后一行添加:
export SYSROOT_arm64=/home/biac/software/SDSoC/rootfs
2.3 配置xfOpenCV库
在SDx IDE中,点击Xilinx -> SDx Libraries,点击下载Xilinx xfOpenCV Library。
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 processingcv::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 rangescv::cvtColor(_src, _imghsv, cv::COLOR_BGR2HSV);// Get the color of Yellow from the HSV image and store it as a maskcv::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 maskcv::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 maskcv::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 objectscv::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 imageunsigned char nLowThresh[3][3] = { { 110, 150, 20 }, // Lower boundary for Blue{ 38, 0, 20 }, // Lower boundary for Green{ 10, 150, 20 } }; // Lower boundary for Orangeunsigned 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 imagein_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 functioncolordetect(in_img, out_img, nLowThresh, nHighThresh);// Write out the input image and the output imagecv::imwrite("output.png", out_img);cv::imwrite("input.png", in_img);return 0;
}
四、配置编译环境
下载完库文件之后需要将库路径添加到应用工程中。
点击Xilinx -> SDx Libraries,选中Xilinx xfOpenCV Library,点击Add to project下拉框,选择自己的应用工程即可。
此时,所有的opencv头文件和库都将被复制到工程目录的libs目录下(工程目录中的libs文件夹中),所有需要设置的选项也相应的自动进行设置好了。
在编译选项中,opencv_前缀的链接库都自动添加到工程的设置中。
添加路径:右键点击工程,选择Properties -> C/C++ General -> Paths and Symbols -> Includes,在GNU C和GNU C++中都添加xfopencv的include路径。如图1-9所示。
添加链接:右键点击工程,选择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。
五、硬件加速opencv
以xilinx在xfopencv中提供的样例做测试,复制xfopencv/examples/histogram目录中的C文件到自己的SDx工程中,安装前文所讲配置编译环境。
添加Hardware Functions:
展开libs/include/imgproc/xf_histogram.hpp/xf
右键选择calcHist函数,选择Toggle HW/SW,将dilate函数作为硬件实现的函数,默认时钟为100MHz。
编译完成后,拷贝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
ZYNQ学习之路19.在SDx中使用xfOpenCV图像加速处理相关推荐
- ZYNQ学习之路17.自定义SDSoC硬件平台
前言 在前面的学习中,我们已经学会了使用Vivado及SDK开发环境,熟悉了硬件开发与Linux软件驱动之间的联系及开发流程.本系列教程我们学习SDSoc的开发,在SDSoc IDE中,Xilinx为 ...
- ZYNQ学习之路13.创建PetaLinux工程
在前面的学习中,我们知道如何根据PetaLinux BSP设计去创建一个工程,现在,我们结合Vivado设计我们自己PetaLinux系统. 开发环境:Ubuntu16 64bit, PetaLinu ...
- alin的学习之路:在Qt中使用Oracle数据库
alin的学习之路:在Qt中使用Oracle数据库 1. 准备工作 在Qt中安装好Source插件,将其中的oci模块进行编译,注意要在oci.pro中指定数据块的动态库和头文件路径 需要在Qt项目文 ...
- ZYNQ学习之路16.SDSoC开发环境介绍
本节教程介绍如何使用SDSoC软件创建硬件平台,并且使用它来加速程序函数. 开发环境: 操作系统: windows10 64bit SDSOC:2018.2 串口: USB-TTL, CP210x 开 ...
- ZYNQ学习之路(三):自定义IP实现PL处理PS写入BRAM的数据
目录 一.实验简介 二.vivado部分处理 三.SDK编程 四.实验测试 五.总结 一.实验简介 ZYNQ系列嵌入式FPGA可以使PS将数据写入PL部分BRAM,PL可以将数据读取后再重新写入BRA ...
- ZYNQ学习之路4.ZYNQ通过GP口读取PL内部RAM数据
实验环境:window 7 64 bit, vivado 2017.1, ZTURN board. 参考手册:Xilinx Distributed Memory Generator 在ZYNQ开发中, ...
- ZYNQ学习之路3. 定制AXI IP核
ZYNQ最大的优点就是硬核A9处理器与FPGA的结合,处理器可以扩展出任何使用者想要的外设(数字逻辑外设),FPGA与处理器通过AXI高速总线进行连接,提供了处理器到FPGA的高速带宽(ZYNQ700 ...
- ZYNQ学习之路11.AXI DMA
一. AXI DMA简介 AXI DMA IP核提供了AXI4内存之间或AXI4-Stream IP之间的内存直接访问,可选为分散收集工作模式,初始化,状态和管理寄存器等通过AXI4-Lite 从机几 ...
- Linux学习总结(19)——Linux中文本编辑器vim特殊使用方法
1. vim比对功能 在linux的环境下 用于观察两个文件的一致性的时候我们一般用diff这个命令来比对,但是这个命令不能你特别详细的比对出 具体的位置或者行对比.这里就用到了vim的对比功能 vi ...
最新文章
- 第七章——DMVs和DMFs(1)
- 用pip安装tensorflow报错SyntaxError: invalid syntax
- MONO Design创建电信3D机房
- 使用glew和glad 新建窗口
- 使用计算机绘制景物图像的两个主要步骤是,计算机11考试.doc
- ListView与GridView优化
- Linux设备模型:kset, kobj, ktype
- iwrite提交不了作业_痛点!为什么开发了那么多软件,还是解决不了教学问题!...
- 合肥赛区结束,继续训练提升
- 树莓派4 PWM控制风扇转速
- matlab 有约束最小化,求解带等式约束和最小化目标的LMI
- 3DEC/PFC离散元入门篇
- 软件工程经济学工程认证作业整理
- 灵活用工系统开发|劳务派遣有风险吗?
- 漫画:什么是 “跳表” ?
- Linux系统安全基础
- OpenCV实战(12)——图像滤波详解
- springcloud集成sentinel 《微服务》
- Origin—对数据进行分类描述统计,包括总数,均值,标准差,总和,最小、最大值,中值。
- Windows Touch 输入
热门文章
- spss专题3:结果文件的基本操作(转载)
- 仪器仪表课程上的大作业——示波器的使用
- windows 8 pro vl_微软MSDN原版Windows10/8/7/XP系统镜像与office下载地址大全
- 【数论】欧几里得算法
- 【分享】优秀外国英文网站
- Java项目:SSH学生请假管理系统
- 黑暗爆炸 #1059. [ZJOI2007]矩阵游戏
- Android 判断是否安装应用宝,并跳到应用中去
- 遗传算法:交叉操作 Inver-over 算子
- vRealize Automation 8.0+安装配置