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. vue 动画原理 part1

    Vue动画原理 增加和删除css增加样式实现一个过渡效果也就是动画效果 1.需要动画效果的标签外包裹一个transition标签 会被自动分析css样式,然后自动构建一个动画流程 transition ...

  2. Spring Cloud Hystrix熔断器隔离方案

      Hystrix组件提供了两种隔离的解决方案:线程池隔离和信号量隔离.两种隔离方式都是限制对共享资源的并发访问量,线程在就绪状态.运行状态.阻塞状态.终止状态间转变时需要由操作系统调度,占用很大的性 ...

  3. 题解 P2981 【[USACO10FEB]奶牛在冰Cows on Ice】

    楼上的思路都是从一个石头找跳到另一个石头的路径,但其实这题可以对于上下左右四个方向分别做一个虚拟节点,然后只需要找虚拟节点左边的虚拟节点就行了 问题是:不会用set怎么办??? 其实可以发现用vect ...

  4. 个人训练记录(UPD 9.16)

    本文章记录一些较难的题,摘自自己的blog中的其他文章.也有些单独成章有点浪费的题也写在里面了. 2019.7.15-2019.7.21 1182F(2900) 题意:求在区间 \([a,b]\) 中 ...

  5. 第一行代码近期bug及解决

    Android学习笔记(5)----启动 Theme.Dialog 主题的Activity时程序崩溃的解决办法https://www.cnblogs.com/dongling/p/6476308.ht ...

  6. 2019-2020-1 20199324《Linux内核原理与分析》第九周作业

    第八章 进程的切换和系统的一般执行过程 1.进程调度的时机 硬中断和软中断 中断:在本质上都是软件或者硬件发生了某种情形而通知处理器的行为,处理器进而停止正在运行的指令流(当前进程),对这些通知做出相 ...

  7. 吴裕雄--天生自然 PYTHON3开发学习:循环语句

    n = 100 sum = 0 counter = 1 while counter <= n: sum = sum + counter counter += 1 print("1 到 ...

  8. TPO9-2Reflection in Teaching

    Teachers, it is thought, benefit from the practice of reflection, the conscious act of thinking deep ...

  9. 场景实践篇一:Nginx负载均衡配置

    code1   code2    code3  三个文件夹, 每个文件夹下面一个 index.html 的文件夹 cd /etc/nginx/conf.d/  下面新建   server1.conf  ...

  10. 查询Redis缓存

    package me.zhengjie.monitor.rest; import me.zhengjie.common.aop.log.Log; import me.zhengjie.monitor. ...