HLS圖像處理系列——膚色檢測


本博文採用Xilinx HLS 2014.4工具。實現一個膚色檢測的模塊。當中,本文重點是構建HLS圖像處理函數。

新建HLSproject的步驟,本博文不再詳述。

本project新建之后,僅僅加入了五個文件,例如以下圖所看到的。當中,top.cpp中的主函數終於會綜合生成HLS硬件圖像處理模塊。test.cpp是測試文件,調用測試圖片。測試top.cpp的圖像處理函數功能。


top.cpp的源代碼例如以下:

#include "top.h"
#include "imgprocess.h"
#include <string.h>

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)
{
	#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  src_mat(rows,cols);
	RGB_IMAGE  dst_mat(rows,cols);
	#pragma HLS dataflow
	hls::AXIvideo2Mat(input, src_mat);
	SkinColorDetect(src_mat,dst_mat, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper);
	hls::Mat2AXIvideo(dst_mat, output);
}
當中。ImgProcess_Top這個函數最后生成一個IP核,能夠放在圖像通路中使用。函數的接口例如以下:

input:視頻流輸入,axi-stream接口;

output:視頻流輸出,axi-stream接口;

rows,cols:可配置參數,圖像的行數、列數。

通過AXI-Lite接口,由PS配置。

y_lower,y_upper,cb_lower,cb_upper,cr_lower,cr_upper:可配置參數,膚色檢測的一些閾值。通過AXI-Lite接口。由PS配置。

上述代碼中,比較重要的一條優化指令為:#pragma HLS dataflow。

它使得任務之間為流水線方式,也就是hls::AXIvideo2Mat(input, src_mat);SkinColorDetect(src_mat,dst_mat, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper);hls::Mat2AXIvideo(dst_mat, output);這三個函數之間為流水線方式運行。

膚色檢測的核心函數為SkinColorDetect(src_mat,dst_mat, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper);它包括在imgprocess.h源代碼例如以下:

#ifndef ___IMAGEPROCESS__
#define ___IMAGEPROCESS__
#include "top.h"

u1 rgb2ycbcr(u8 B, u8 G, u8 R, int y_lower, int y_upper, int cb_lower, int cb_upper, int cr_lower, int cr_upper)
{
#pragma HLS PIPELINE
	u8 y, cr, cb;
	y = (76 * R.to_int() + 150 * G.to_int() + 29 * B.to_int()) >> 8;
	cb = 128 + ((128*B.to_int() -43*R.to_int() - 85*G.to_int())>>8);
	cr = 128 + ((128*R.to_int() -107*G.to_int() - 21 * B.to_int())>>8);

	if (y > y_lower && y < y_upper && cb > cb_lower && cb < cb_upper
			&& cr > cr_lower && cr < cr_upper)
		 return 1;
	else
		 return 0;
}

namespace hls {
template<int SRC_T, int DST_T,int ROW, int COL>
void ImgProcess(Mat<ROW, COL, SRC_T> &_src, Mat<ROW, COL, DST_T>	&_dst,
		int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
{
	loop_height: for(HLS_SIZE_T i= 0;i< ROW;i++)
	{
	#pragma HLS LOOP_TRIPCOUNT max=ROW
		loop_width: for (HLS_SIZE_T j= 0;j< COL;j++)
		{
		#pragma HLS LOOP_FLATTEN OFF
		#pragma HLS LOOP_TRIPCOUNT max=COL
		#pragma HLS DEPENDENCE array inter false
		#pragma HLS PIPELINE
			u8 r, g, b;
			u1 skin_region;

			HLS_TNAME(SRC_T) temp0=0;
			HLS_TNAME(SRC_T) temp1=0;
			HLS_TNAME(SRC_T) temp2=0;
			/***********stream input *********/
			_src.data_stream[0]>>temp0;
			_src.data_stream[1]>>temp1;
			_src.data_stream[2]>>temp2;

			b = temp0;
			g = temp1;
			r = temp2;
			/********detect skin region*******/
			skin_region = rgb2ycbcr(b, g, r,y_lower,y_upper,cb_lower,cb_upper,cr_lower,cr_upper);
			HLS_TNAME(DST_T) temp_dst0=0;
			HLS_TNAME(DST_T) temp_dst1=0;
			HLS_TNAME(DST_T) temp_dst2=0;

			temp_dst0= (skin_region == 1)? b : (u8)0;
			temp_dst1= (skin_region == 1)?

g : (u8)0; temp_dst2= (skin_region == 1)?

r : (u8)0; /***********stream output ********/ _dst.data_stream[0]<<temp_dst0; _dst.data_stream[1]<<temp_dst1; _dst.data_stream[2]<<temp_dst2; } } } template<int SRC_T, int DST_T,int ROW, int COL> void SkinColorDetect(Mat<ROW, COL, SRC_T> &_src,Mat<ROW, COL, DST_T> &_dst, int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper) { #pragma HLS INLINE ImgProcess(_src, _dst, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper); } } #endif


核心函數是rgb2ycbcr這個函數。關於膚色檢測有多種方式,本文的膚色檢測方法是將rgb轉換為ycbcr,然后設置閾值。

保存后,綜合。

綜合完成,打開分析工具:


點擊紅框里的內容:


能夠看到imgprocess.h中,ImgProcess這個函數的運行狀態:


然后點擊ImgProcess_Top_rgb2ycbcr,能夠看到例如以下圖:


我們發現,僅僅需一個時鍾周期就可以運行完成。這是由於rgb2ycbcr這個函數採用了流水線的優化指令:#pragma HLS PIPELINE。

綜合之后,就能夠測試了。

test.cpp內容例如以下:

#include "top.h"
#include "hls_opencv.h"
#include"iostream"
#include<time.h>
using namespace std;
using namespace cv;


int main (int argc, char** argv) {



    Mat src = imread("test.jpg");
	AXI_STREAM  src_axi, dst_axi;
	Mat dst(Size(640,480),CV_8UC3);

	resize(src,src,Size(640,480));
	//mat to axi video
	cvMat2AXIvideo(src, src_axi);
	//test function
	ImgProcess_Top(src_axi, dst_axi, 480, 640,0,255,80,135,131,185);
	//axi video to mat
	AXIvideo2cvMat(dst_axi, dst);

	imshow("src",src);
	imshow("dst_hls",dst);

	waitKey(0);

	return 0;
}
測試的圖像例如以下:

執行測試程序后。輸出圖像例如以下:

通過測試后,點擊hls界面工具欄的export RTLbutton,打包生成ip。最后的IP例如以下所看到的:




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM