【ZYNQ-7000开发之十五】Vivado HLS和OpenCV_下

本篇文章在上篇文章【ZYNQ-7000开发之十四】的基础上,利用OpenCV HLS的函数,hls::Sobel,编写边缘检测算法,仿真测试,创建IP,最后在vivado里测试Sobel IP,此外本篇文章的实验还要基于 【ZYNQ-7000开发之十】TGP+VDMA+HDMI搭建视频通路,把做好的HLS Sobel IP添加到此工程,进行测试,当然这个不是必须的,大家可以使用测试自己的方法

关于HLS详细内容请参考官方文献ug902-vivado-high-level-synthesis
*本文主要参考文献:
how_to_accelerate_opencv_applications_using_vivado_hls
xapp890-zynq-sobel-vivado-hls*

*本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2*
需要准备HDMI显示器和串口线一条

sobel算子原理简介

计算机视觉领域的一种重要处理方法。主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。在技术上,它是一个离散的一阶差分算子,用来计算图像亮度函数的一阶梯度之近似值。在图像的任何一点使用此算子,将会产生该点对应的梯度矢量或是其法矢量。
Sobel 算子有两个,一个是检测水平边缘的 ;另一个是检测垂直边缘的 。所以该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。公式如下:
这里写图片描述

Sobel测试效果的图像(摘自wikipedia,本文使用TPG产生的动态视频进行测试的,效果没那么明显)
这里写图片描述
这里写图片描述

建立HLS工程

建好之后,在新建头文件

top.h源码

#ifndef _TOP_H_
#define _TOP_H_
#include"hls_video.h" //这里调用可以综合的视频库
// maximum image size
#define MAX_WIDTH 1920
#define MAX_HEIGHT 1080
// I/O Image Settings
#define INPUT_IMAGE "test_1080p.jpg"
#define OUTPUT_IMAGE "result_1080p.jpg"
#define OUTPUT_IMAGE_GOLDEN "result_1080p_golden.jpg"
// typedef video library core structures
typedef hls::stream<ap_axiu<24,1,1,1> > AXI_STREAM_IN;
typedef hls::stream<ap_axiu<24,1,1,1> > AXI_STREAM_OUT;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
// top level function for HW synthesis
void hls_sobel(AXI_STREAM_IN& src_axi, AXI_STREAM_OUT& dst_axi, int rows, int cols);

#endif

hls_sobel.cpp源码


#include "top.h"
void hls_sobel(AXI_STREAM_IN& input, AXI_STREAM_OUT& output, int rows, int cols) {
#pragma HLS RESOURCE variable=input core=AXI4Stream metadata="-bus_bundle INPUT_STREAM"
#pragma HLS RESOURCE variable=output core=AXI4Stream metadata="-bus_bundle OUTPUT_STREAM"
#pragma HLS INTERFACE ap_none port=cols
#pragma HLS INTERFACE ap_none port=rows
//AP_CONTROL_BUS_AXI(CONTROL_BUS);
//set_directive_interface -mode ap_ctrl_none hls_sobel
#pragma HLS interface ap_ctrl_none port=return

RGB_IMAGE img_0(rows, cols);
RGB_IMAGE img_1(rows, cols);
#pragma HLS DATAFLOW // must use data flow to stream the data
hls::AXIvideo2Mat(input, img_0); //read video stream by frames
hls::Sobel<1,0,3>(img_0, img_1);//use Hls Sobel
hls::Mat2AXIvideo(img_1, output); //write the frames to video stream
}

C综合

点击Solution -> Run C Synthesis -> Active Solution

test.cpp源码

#include "top.h"
#include "opencv/cv.h"
#include "opencv/cxcore.h"
#include "opencv/highgui.h"
#include "hls_opencv.h"
int main (int argc, char** argv) {
    IplImage* src = cvLoadImage(INPUT_IMAGE);
    IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
    AXI_STREAM_IN src_axi;
    AXI_STREAM_OUT dst_axi;
    IplImage2AXIvideo(src, src_axi); //将图像转为视频流结构
    hls_sobel(src_axi, dst_axi, src->height, src->width);
    AXIvideo2IplImage(dst_axi, dst);
    cvSaveImage(OUTPUT_IMAGE, dst);
    cvReleaseImage(&src);
    cvReleaseImage(&dst);
}

运行test.cpp C仿真测试

点击Project -> Run C simulation,弹出的对话框按照如图所示设置
这里写图片描述
在弹出的Debug界面,点击resume(左上角有个快捷按钮),
到相应的路径下查找测试输出的图片(我的是XXX\sobel\solution1\csim\build)

测试结果

点击
原图像:
这里写图片描述
进行Sobel 滤波的图像:
这里写图片描述

生成IP

点击 Solution -> export -> Solution
按照如下配置
这里写图片描述
完成后,会在(xxx\sobel\solution1\impl\ip)路径下产生IP Core

在vivado调用HLS

打开以前做好的HDMI工程( 【ZYNQ-7000开发之十】TGP+VDMA+HDMI搭建视频通路)

连接方式,如图

这里写图片描述
TPG配置方式:
这里写图片描述

上板测试

结果……视频截图(动态的),不是很漂亮啊,中间一条黑色的不知道怎么回事,原图就不传了,编译一次时间太久了
这里写图片描述
大家可以加入摄像头试下,测试效果
原书图(手机直接拍摄的):
这里写图片描述
测试效果(目前bit数有点低):
这里写图片描述

猜你喜欢

转载自blog.csdn.net/RZJMPB/article/details/50858149