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. C++代码质量度量工具大阅兵

    姊妹篇:Java代码质量度量工具大阅兵: https://www.cnblogs.com/jiangxinnju/p/10010177.html cppcheck cppcheck: https:// ...

  2. MQL4编程—值传递和引用传递

    定义 简单的说就是给一个变量或者对象取一个别名(引用和被引用的共享存储单元,要用修饰符&). 引用的用法 在MQL4中通过调试只接受引用作为函数参数的用法,在函数参数传递过程中,有两种传递方式 ...

  3. dotnet core 链接mongodb

    导入命名空间 using MongoDB.Bson; using MongoDB.Driver; 测试示例: var client = new MongoClient("mongodb:// ...

  4. docker---安装docker

    今天开始要初步的学习 docker 了,这也是进入虚拟化方向的一个步骤,学习一个东西首先要从搭建环境开始,哈哈 安装环境及版本: 系统:Ubuntu18.04 STL Docker 版本:19.03. ...

  5. SaltStack中状态间关系unless、onlyif、require、require_in、watch、watch_in

    1.unless 检查的命令,仅当unless选项指向的命令返回值为false时才执行name定义的命令 cmd.run: {% "] %} - name: 'nohup sh /alida ...

  6. netty 百度网盘 密码

    netty基础 https://pan.baidu.com/s/1v_ME49LIef1Kwga8z2QbDw?spm=a1z09.2.0.0.680b2e8d5LI8S0   zb7u mina n ...

  7. 漫谈设计模式(二):单例(Singleton)模式

    1.前言 实际业务中,大多业务类只需要一个对象就能完成所有工作,另外再创建其他对象就显得浪费内存空间了,例如web开发中的servlet,这时便要用到单例模式,就如其名一样,此模式使某个类只能生成唯一 ...

  8. ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879

    ACM-ICPC Asia Beijing Regional Contest 2018 Reproduction hihocoder1870~1879 A 签到,dfs 或者 floyd 都行. #i ...

  9. Python笔记_第四篇_高阶编程_GUI编程之Tkinter_1.使用Python进行GUI编程的概述

    1. GUI概述: GUI全称为Graphical User Interface,叫做图形用户界面,也是一种交互方式(Interaction).早期计算机使用的命令行界面(command-line i ...

  10. tensorflow函数解析: tf.Session() 和tf.InteractiveSession()

    链接如下: http://stackoverflow.com/questions/41791469/difference-between-tf-session-and-tf-interactivese ...