【一 HLS】HLS学习之图像的二值化处理

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

	--晓凡   202292日于南宁书  

你可能感兴趣的:(FPGA学习之路,学习,fpga开发,HLS)