第一個HLS實現的圖像處理算法

  最近在學習HLS語言,所以就自己摸索嘗試了用HLS實現了圖像二值化,把這個內容總結一下,分享出來。

  首先打開HLS,然後新建一個Project,之後再在Source欄點擊右鍵,選擇New File…,創建名爲pixelBinary.cpp和pixelBinary.h這兩個文件。

  這個是pixelBinary.cpp文件的內容:

#include "pixelBinary.h"
#include <stdio.h>
#include <iostream>

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 ? 255 : 0;
			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);
	hls::pixelBinary(img_src,img_dst);
	hls::Mat2AXIvideo(img_dst,dst_axi);
}

  這個是pixelBinary.h文件的內容:

#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 184
#define IMG_HEIGHT 273

// 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進行確定。然後點擊HLS界面的C Synthesis,如下是綜合完的結果。
HLS綜合之後的結果
  從綜合結果可知,pixelBinary的Latency和Interval的值是一樣的,都是50235,我們的圖片尺寸是184*273 = 50232,Latency和Interval的值比圖片像素數多3,關於Latency和Interval具體的含義,我還是沒有很明白,這兩個值到底是怎麼來進行計算的,等弄明白了再來分享。

  這是一個綜合的結果,也就是把我們的HLS代碼綜合成了Verilog或者VHDL代碼了,你再solution下面的syn文件夾下就可以看到生成的Verilog或者VHDL代碼了。

  然後接下去是仿真,在TestBench下新建文件,文件名爲testbench.cpp,代碼爲:

#include "iostream"
#include "hls_opencv.h"
#include "pixelBinary.h"

using namespace std;
using namespace cv;

int main()
{
	//獲取圖像數據
	IplImage* src = cvLoadImage(INPUT_IMAGE,CV_LOAD_IMAGE_GRAYSCALE);
	//獲取仿真圖片並直接轉爲灰度圖像
	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;
}

  這個仿真代碼的意思就是讀取圖像,然後進行處理,並將處理完的結果輸出,爲了能夠仿真,需要在TestBench下添加圖像文件,圖像文件名爲input_image.png,最後會輸出output_image.png這麼一個圖像。如下分別爲輸入圖像數據和輸出圖像數據,最終生成的圖像數據在 .\solution_pixelBinary\sim\wrapc文件夾下

輸入圖像數據 輸出圖像數據
  但其實呢,我覺得這樣的testbench並不好,看過Example裏的TestBench,寫法都是Software的結果和Hardware的結果進行對比,如果能對上,就說明寫的代碼沒問題,不過圖像處理的話,直接看處理後的圖像差不多也行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章