zoukankan      html  css  js  c++  java
  • 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_ 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例如以下所看到的:



  • 相关阅读:
    查看用户密码
    OPM批次成本后台表
    查询物料事务处理历史记录脚本
    接收会计事件表和接收会计分录表
    为应付发票批添加ORG_ID
    项目环境配置剩余部分
    配置IDEA的基本设置操作
    NB: JAVA_HOME should point to a JDK not a JRE
    Windows10下的JAVA运行环境搭建 ——第一天
    python中的可变与不可变对象的区别
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6763744.html
Copyright © 2011-2022 走看看