HLS工具

以个人的理解,xilinx将HLS(高层次综合)定位于更方便的将复杂算法转化为硬件语言,通过添加某些配置条件HLS工具可以把可并行化的C/C++的代码转化为vhdl或verilog,相比于纯人工使用vhdl实现图像算法,该工具综合出的代码的硬件资源占用可能较多,但并没有相差太大(见论文:基于HLS的 SURF特征提取硬件加速单元设计与实现),而纯人工用硬件描述语言实现一个复杂的图像处理算法要求十分深厚的FPGA功底,下面简单总结下好早之前做的一个在zybo开发板上的HLS图像处理通路。

主要从三个工程分析

1.sobel边缘检测

头文件部分涉及到‘hls_video.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<,,,> > AXI_STREAM_IN;
typedef hls::stream<ap_axiu<,,,> > 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

主要函数的具体定义:

#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<,,>(img_0, img_1);//use Hls Sobel
//根据模板,<1,0,3>中前两个部分规定了x方向的检测还是y方向的检测,<1,0>表示的是y方向的检测,size=3代表sobel算子的维数规定。
//hls::Erode<>();//use Hls Sobel
hls::Mat2AXIvideo(img_1, output); //write the frames to video stream
}

除了优化部分以外,主要做的就是定义输入输出图像的内存空间,然后将输入的数据格式转换为mat格式,用于实现ip1image的处理,然后就是直接调用库里的sobel函数,最后图像转化为video-stream输出即可。

需要注意优化部分:视频输入输出接口优化为stream格式,将控制接口分配到AXI4 Lite接口,指定“rows”可通过AXI4-Lite接口进行访问并且声明在函数执行过程中 “rows”不会改变,其实这几句优化语句中最关键的一条指令为启用数据流优化:#pragma HLS dataflow,它使得任务之间以流水线的方式执行,还有就是#pragma HLS interface ap_ctrl_none port=return。

测试函数:

#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) //argc 是 argument count的缩写,表示传入main函数的参数个数;
//argv 是 argument vector的缩写,表示传入main函数的参数序列或指针,并且第一个参数argv[0]一定是程序的名称,并且包含了程序所在的完整路径,所以确切的说需要我们输入的main函数的参数个数应该是argc-1个;
{
IplImage* src = cvLoadImage(INPUT_IMAGE);//为输入图像定义好存储空间
IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);//为输出图像定义好存储空间
AXI_STREAM_IN src_axi;//定义输入输出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);
}//不加符号

注意头文件导入时路径的问题,思路是定义好图像空间后定义视频图像的变量,然后将输入的图像转换为视频流结构,用自己写的函数处理后,观察处理后的结果即可

最后生成IP核的摸样

2.skin-detect部分

头文件

#ifndef _TOP_H_
#define _TOP_H_ #include "hls_video.h"
// maximum image size
#define MAX_WIDTH 1920
#define MAX_HEIGHT 1080 typedef unsigned char uchar; // I/O Image Settings
#define INPUT_IMAGE "test.jpg"
#define OUTPUT_IMAGE "result_1080p.bmp"
#define OUTPUT_IMAGE_GOLDEN "test_img1.jpg" // typedef video library core structures
typedef hls::stream<ap_axiu<,,,> > AXI_STREAM;
typedef hls::Mat<MAX_HEIGHT, MAX_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Scalar<, unsigned char> RGB_PIXEL; //函数声明,,,用到了命名空间,这就是一个虚拟文件夹的意思
namespace hls
{
void hls_skin_dection(RGB_IMAGE& src, RGB_IMAGE& dst,int rows, int cols,
int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper);
} void ImgProcess_Top(AXI_STREAM& input, AXI_STREAM& output,int rows, int cols,
int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper); #endif

涉及到的mat以及scalar格式的数据结构可参考:

主要函数:

#include "top.h"
#include <string.h> void hls::hls_skin_dection(RGB_IMAGE& src, RGB_IMAGE& dst,int rows, int cols,
int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
{ LOOp_ROWS:for(int row = ; row < rows ; row++)
{
//#pragma HLS loop_flatten off
LOOp_COLS:for(int col = ; col < cols; col++)
{
#pragma HLS pipeline II=1 off //--------------------------优化指令1
//变量定义
RGB_PIXEL src_data;
RGB_PIXEL pix;
RGB_PIXEL dst_data;
bool skin_region; if(row < rows && col < cols) {
src >> src_data;
} //获取RGB图像通道数据
uchar B = src_data.val[];
uchar G = src_data.val[];
uchar R = src_data.val[]; //RGB-->YCbCr颜色空间转换
uchar y = ( * R + * G + * B) >> ;
uchar cb = ((*B -*R - *G)>>) + ;
uchar cr = ((*R -*G - * B)>>)+ ; //肤色区域判定
if (y > y_lower && y < y_upper && cb > cb_lower && cb < cb_upper && cr > cr_lower && cr < cr_upper)
skin_region = ;
else
skin_region = ;
//将肤色区域的值大小置为255,即白色
uchar temp0= (skin_region == )? (uchar): B;
uchar temp1= (skin_region == )? (uchar): G;
uchar temp2= (skin_region == )? (uchar): R; dst_data.val[] = temp0;
dst_data.val[] = temp1;
dst_data.val[] = temp2;
//复制处理完成后输出图像
dst << dst_data;
}
}
}
//该函数的作用主要是把上面的skin-detect函数的输入输出端口做一个封装,以便处理视频输入信号
void ImgProcess_Top(AXI_STREAM& input, AXI_STREAM& output,int rows, int cols,
int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
//定义该函数的功能用于将上面的肤色检测用AXI_STREAM结构封装端口
{
///*
#pragma HLS RESOURCE variable=input core=AXIS metadata="-bus_bundle INPUT_STREAM"
#pragma HLS RESOURCE variable=output core=AXIS metadata="-bus_bundle OUTPUT_STREAM" #pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=y_lower metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=y_upper metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cb_lower metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cb_upper metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cr_lower metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=cr_upper metadata="-bus_bundle CONTROL_BUS"
#pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS" #pragma HLS INTERFACE ap_stable port=rows
#pragma HLS INTERFACE ap_stable port=cols
#pragma HLS INTERFACE ap_stable port=y_lower
#pragma HLS INTERFACE ap_stable port=y_upper
#pragma HLS INTERFACE ap_stable port=cb_lower
#pragma HLS INTERFACE ap_stable port=cb_upper
#pragma HLS INTERFACE ap_stable port=cr_lower
#pragma HLS INTERFACE ap_stable port=cr_upper
///*/
RGB_IMAGE img_0(rows, cols);
RGB_IMAGE img_1(rows, cols); #pragma HLS dataflow
hls::AXIvideo2Mat(input,img_0);//将video图像数据结构转换为mat型(RGB图像)数据,以便于输入到下面的检测函数中。
hls::hls_skin_dection(img_0,img_1,rows,cols,y_lower,y_upper,cb_lower,cb_upper,cr_lower,cr_upper);
hls::Mat2AXIvideo(img_1, output);//将mat型(RGB图像)数据转换为video图像数据结构输出
}

我们对视频接口的约束如下:将src和dst指定为为以 “INPUT_STREAM” 命名的AXI4 Stream,将控制接口分配到AXI4 Lite接口,指定“rows”可通过AXI4-Lite接口进行访问并且声明在函数执行过程中 “rows”不会改变,其实这几句优化语句中最关键的一条指令为启用数据流优化:#pragma HLS dataflow,它使得任务之间以流水线的方式执行,即hls::AXIvideo2Mat(src,img_0);hls::skin_detect(img_0,img_1,rows,cols ,cb_lower,cb_upper,cr_lower,cr_upper);hls::Mat2AXIvideo(img_1, dst),这三个函数之间为流水线方式。

测试文件:思路也是导入图像文件,然后创建好保存结果的空间,然后定义视频流变量,将图像输入转换为axi-stream格式,然后用自己编写的函数处理后,输出转换为IplImage格式后,输出图像观察即可。

#include "top.h"
#include "hls_opencv.h"
#include "iostream"
#include <time.h> using namespace std;
using namespace cv; int main (int argc, char** argv)
{
//IplImage* src = cvLoadImage(INPUT_IMAGE);
IplImage* src = cvLoadImage("test.jpg");
//IplImage* src = cvLoadImage("test_img1.jpg");
IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels); AXI_STREAM src_axi, dst_axi;
IplImage2AXIvideo(src, src_axi); ImgProcess_Top(src_axi, dst_axi, src->height, src->width,,,,,,);
AXIvideo2IplImage(dst_axi, dst); cvShowImage("src",src);
cvShowImage("dst_hls",dst);
waitKey();//参数<=0时等待按键事件发生,按下键的话返回按键的值, 否则返回-1; return ;
}

下一篇介绍:

3.FFT的HLS实现

3.HOG实现部分https://www.cnblogs.com/zhazhiqiang/p/3595266.html

HLS图像处理总结(一)的更多相关文章

  1. HLS图像处理系列——肤色检測

    本博文採用Xilinx HLS 2014.4工具.实现一个肤色检測的模块.当中,本文重点是构建HLS图像处理函数. 新建HLSproject的步骤,本博文不再详述. 本project新建之后,仅仅加入 ...

  2. Zynq开发之HLS

    Zynq开发之HLS 由 FPGA菜鸟 于 星期三, 06/28/2017 - 11:53 发表 HLS简介 HLS(High Level Synthesis)即高层次综合,不同于以往的FPGA逻辑开 ...

  3. OpenCV2计算机编程手册(二)基于类的图像处理

    1. 在算法设计中使用策略(Strategy)模式 策略设计模式的目标是将算法封装在类中.因此,可以更容易地替换一个现有的算法,或者组合使用多个算法以拥有更复杂的处理逻辑.此外,该模式将算法的复杂度隐 ...

  4. HLS:OpenCV和RTL代码转换关系

    OpenCV 图像处理是基于存储器帧缓存而构建的, 它总是假设视频帧数据存放在外部 DDR 存储器中. 由于处理器的小容量高速缓存性能的限制, 因此, OpenCV 访问局部图像性能较差. 并且, 从 ...

  5. Java版流媒体编解码和图像处理(JavaCPP+FFmpeg)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. Python图像处理丨基于OpenCV和像素处理的图像灰度化处理

    摘要:本篇文章讲解图像灰度化处理的知识,结合OpenCV调用cv2.cvtColor()函数实现图像灰度操作,使用像素处理方法对图像进行灰度化处理. 本文分享自华为云社区<[Python图像处理 ...

  7. OpenCV图像处理与视频分析详解

    1.OpenCV4环境搭建 VS2017新建一个控制台项目 配置包含目录 配置库目录 配置链接器 配置环境变量 重新启动VS2017 2.第一个图像显示程序 main.cpp #include< ...

  8. Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉

    Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉 1.1. 按照当前流行的分类方法,可以分为以下三部分:三部分 图像处理 图像分析 计算机视觉1 1.2. 图像处理需要 ...

  9. Atitit 图像处理的摩西五经attilax总结

    Atitit 图像处理的摩西五经attilax总结 1. 数字图像处理(第三版)1 2. 图像处理基础(第2版)(世界著名计算机教材精选)1 3. 计算机视觉特征提取与图像处理(第三版)2 4. Op ...

随机推荐

  1. AXURE方便的功能

    (1)建立一个公共的页面,可以把一些常用的组建放进去,就和代码要封装方法一样,这样省区了用到一次画一次的麻烦. 其中可以包括:弹出框.图标.搜索框之类的. 当然还可以把经常用到的 登陆.注册.忘记密码 ...

  2. MySQL--通过.frm和.ibd对mysql数据恢复

    转载:http://bbs.csdn.net/topics/392114182 例如说 现在要恢复user表1.先建立和之前user表一样的表结构.就是执行create table user .... ...

  3. POJ 1860 Currency Exchange【bellman-Ford模板题】

    传送门:http://poj.org/problem?id=1860 题意:给出每两种货币之间交换的手续费和汇率,求出从当前货币s开始交换回到s,能否使本金增多. 思路:bellman-Ford模板题 ...

  4. 用户交互Scanner

    用户交互Scanner java.util.Scanner Scanner类可以获取用户的输入. Java 5 通过Scanner类的next()和nextLine()方法获取输入的字符串 在读取前我 ...

  5. jq监控滑动

    $(window).scroll(function () { if ($(window).scrollTop() == $(document).height() - $(window).height( ...

  6. 打水滴(BFS)

    在一个n行m列的网格中,某些位置存在一些水滴.嘟嘟进行q次打水滴操作,每次嘟嘟在某一个网格当中添加一个水滴,当某一网格中的水滴数量超过L时,该网格中的水滴变为四个水滴,并分别向上下左右四个方向飞出,每 ...

  7. 201312-1 出现次数最多的数Java

    import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Scanner; ...

  8. cookie保存

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  9. MySql数据库,查询数据导出时会出现重复的记录(数据越多越明显)

    在查询数据时,数据量多的时候,我们会使用分页功能. 每页显示多少数据. 这种情况下,一半看不出什么问题. 而导出数据时,有时就是通过分页的方法,逐步讲数据追加到导出文件中. 当全部数据都导出之后,就有 ...

  10. Python笔记_第一篇_面向过程第一部分_6.循环控制语句(while 和 for)_

    承接条件控制语句.条件控制语句像大树一样有很多的之差,那条路径通(也就是表达式判断为True)就会往哪一个树杈去运行,万涓溪水汇成大河.对于常用的程序结构形式,还有一种这篇文章就会讲解,那就是循环控制 ...