HLS中相关数据类型的介绍:【传送门】
由于vivado hls中的mat类型,实际上为stream类型,只可以顺序存取,不可以随机存取,因此无法随便怼同一个数据进行复用。VIVADO HLS图像处理的一般步骤是将IplImage图像(Intel Image Processing Library,缩写Ipl)类型转化为AXI STREAM图像类型,再将AXI STREAM图像类型转化为HLS Video视频库可处理的MAT类型,输出部分逆转化成IplImage图像类型输出即可。其中AXI STREAM图像类型转化为MAT类型,MAT类型转化为AXI STREAM图像类型是可被综合的。
这个例子是HLS实现图像的二值化。
参照博客【传送门】完成的这个例程。
这个代码移植需要注意的地方:
源文件内容,命名为pixelBinary.cpp
,新建工程后将其添加到Source目录下(在这个文件中右键有添加文件的选项):
#include "pixelBinary.h"
#include
#include
using namespace std;
void hls::pixelBinary(GRAY_IMAGE &src, GRAY_IMAGE &dst)
{
uchar pixelValue;
GRAY_PIXEL src_data;
GRAY_PIXEL dst_data;
LOOP_ROW:
for(int idxRow = 0; idxRow < IMG_HEIGHT; idxRow++)
{
LOOP_COL:
for(int idxCol = 0; idxCol < IMG_WIDTH; idxCol++)
{
#pragma HLS PIPELINE II=1
src >> src_data;
pixelValue = src_data.val[0];
dst_data.val[0] = pixelValue > 128 ? 0 : 255;//二值化的关键语句,像素的值大于128时,赋值为0(黑色),小于时赋值为255(白色)
dst << dst_data;
}
}
}
void hlsMain(AXI_STREAM& src_axi, AXI_STREAM& dst_axi)
{
#pragma HLS INTERFACE axis port=src_axi bundle=INPUT_STREAM
#pragma HLS INTERFACE axis port=dst_axi bundle=OUTPUT_STREAM
GRAY_IMAGE img_src;
GRAY_IMAGE img_dst;
#pragma HLS dataflow
hls::AXIvideo2Mat(src_axi,img_src);//axi stream类型转化为HLS能处理的mat数据类型
hls::pixelBinary(img_src,img_dst);//调用自定义函数处理图片
hls::Mat2AXIvideo(img_dst,dst_axi);//输出结果图片需要将数据从mat类型转换为axi stream类型
}
头文件pixelBinary.h
的内容,添加到Source目录下:
#ifndef _PIXELBINARY_H_
#define _PIXELBINARY_H_
#include "hls_video.h"
#include "hls_math.h"
#include "ap_int.h"
#include "ap_fixed.h"
// maximum image size
#define IMG_WIDTH 1280//图片的宽
#define IMG_HEIGHT 1706//图片的高,不同的图片记得修改这两个参数
// I/O Image Settings
#define INPUT_IMAGE "input_image.png"
#define OUTPUT_IMAGE "output_image.png"
// typedef video library core structures
typedef unsigned char uchar;
typedef hls::stream<ap_axiu<8,1,1,1> > AXI_STREAM;
typedef hls::Mat<IMG_HEIGHT, IMG_WIDTH, HLS_8UC1> GRAY_IMAGE;
typedef hls::Scalar<1, uchar> GRAY_PIXEL;
// typedef HLS namespace
namespace hls
{
void pixelBinary(GRAY_IMAGE &src, GRAY_IMAGE &dst);
}
//top level function for HW synthesis
void hlsMain(AXI_STREAM& src_axi, AXI_STREAM& dst_axi);
#endif
有这两个文件其实已经可以进行综合了,综合前记得修改设置顶层函数,否则编译器不知道入口函数是哪一个,修改的方法:
Project -> Project Settings -> Synthesis -> 在Top Function那里选择hlsMain,点击OK进行确定
测试文件的内容tb.cpp,将其添加到工程的Test Bench中:
#include "iostream"
#include "hls_opencv.h"
#include "pixelBinary.h"
using namespace std;
using namespace cv;
int main()
{
//获取图像数据 CV_LOAD_IMAGE_GRAYSCALE
IplImage* src = cvLoadImage(INPUT_IMAGE,CV_LOAD_IMAGE_GRAYSCALE);//IplImage为结构体,将其指向结构体,结构体的内容可以进去看
//获取仿真图片并直接转为灰度图像
IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);//获取原始图像的大小
AXI_STREAM src_axi, dst_axi;
IplImage2AXIvideo(src, src_axi);
hlsMain(src_axi, dst_axi);
AXIvideo2IplImage(dst_axi, dst);
cvSaveImage(OUTPUT_IMAGE,dst);
//释放内存
cvReleaseImage(&src);
cvReleaseImage(&dst);
return 0;
}
点击仿真之后当前的目录下的\solution1\csim\build文件夹中后生成的输出图片output_image.png。
WARNING: Hls::stream 'hls::stream<ap_axiu<8, 1, 1, 1> >.2' is read while empty, which may result in RTL
最后想吐槽一下:HLS这个软件对写代码不太友好,反应有点迟钝,错误的代码修改过来之后还是显示错误,这个软件是采用java语言写的,是不是因为这个原因所以反应有点迟钝呢?目前这个问题没有想到好的方法解决。有没有什么好用的编辑器代替呢。最后的最后愿所有的程序员写的代码少些bug,一次通过。
参考:
【1】https://blog.csdn.net/weixin_50988214/article/details/116534049?ops_request_misc=&request_id=&biz_id=102&utm_term=hls::AXIvideo2Mat&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-7-116534049.142v44pc_rank_34_1&spm=1018.2226.3001.4187
【2】https://blog.csdn.net/qq_51474038/article/details/123472267
--晓凡 2022年9月2日于南宁书