【转】HLS图像处理系列——肤色检测

HLS图像处理系列——肤色检测

本博文采用Xilinx HLS 2014.4工具,实现一个肤色检测的模块。其中,本文重点是构建HLS图像处理函数。新建HLS工程的步骤,本博文不再详述。

本工程新建之后,只添加了五个文件,如下图所示。其中,top.cpp中的主函数最终会综合生成HLS硬件图像处理模块。test.cpp是测试文件,调用测试图片,测试top.cpp的图像处理函数功能。

top.cpp的源码如下:

 

  1.  
    #include "top.h"
  2.  
    #include "imgprocess.h"
  3.  
    #include <string.h>
  4.  
     
  5.  
    void ImgProcess_Top(AXI_STREAM& input, AXI_STREAM& output,int rows, int cols,
  6.  
    int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
  7.  
    {
  8.  
    #pragma HLS RESOURCE variable=input core=AXIS metadata="-bus_bundle INPUT_STREAM"
  9.  
    #pragma HLS RESOURCE variable=output core=AXIS metadata="-bus_bundle OUTPUT_STREAM"
  10.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=rows metadata="-bus_bundle CONTROL_BUS"
  11.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=cols metadata="-bus_bundle CONTROL_BUS"
  12.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=y_lower metadata="-bus_bundle CONTROL_BUS"
  13.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=y_upper metadata="-bus_bundle CONTROL_BUS"
  14.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=cb_lower metadata="-bus_bundle CONTROL_BUS"
  15.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=cb_upper metadata="-bus_bundle CONTROL_BUS"
  16.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=cr_lower metadata="-bus_bundle CONTROL_BUS"
  17.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=cr_upper metadata="-bus_bundle CONTROL_BUS"
  18.  
    #pragma HLS RESOURCE core=AXI_SLAVE variable=return metadata="-bus_bundle CONTROL_BUS"
  19.  
     
  20.  
    #pragma HLS INTERFACE ap_stable port=rows
  21.  
    #pragma HLS INTERFACE ap_stable port=cols
  22.  
    #pragma HLS INTERFACE ap_stable port=y_lower
  23.  
    #pragma HLS INTERFACE ap_stable port=y_upper
  24.  
    #pragma HLS INTERFACE ap_stable port=cb_lower
  25.  
    #pragma HLS INTERFACE ap_stable port=cb_upper
  26.  
    #pragma HLS INTERFACE ap_stable port=cr_lower
  27.  
    #pragma HLS INTERFACE ap_stable port=cr_upper
  28.  
    RGB_IMAGE src_mat(rows,cols);
  29.  
    RGB_IMAGE dst_mat(rows,cols);
  30.  
    #pragma HLS dataflow
  31.  
    hls::AXIvideo2Mat(input, src_mat);
  32.  
    SkinColorDetect(src_mat,dst_mat, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper);
  33.  
    hls::Mat2AXIvideo(dst_mat, output);
  34.  
    }
其中,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源码如下:

 

  1.  
    #ifndef ___IMAGEPROCESS__
  2.  
    #define ___IMAGEPROCESS__
  3.  
    #include "top.h"
  4.  
     
  5.  
    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)
  6.  
    {
  7.  
    #pragma HLS PIPELINE
  8.  
    u8 y, cr, cb;
  9.  
    y = (76 * R.to_int() + 150 * G.to_int() + 29 * B.to_int()) >> 8;
  10.  
    cb = 128 + ((128*B.to_int() -43*R.to_int() - 85*G.to_int())>>8);
  11.  
    cr = 128 + ((128*R.to_int() -107*G.to_int() - 21 * B.to_int())>>8);
  12.  
     
  13.  
    if (y > y_lower && y < y_upper && cb > cb_lower && cb < cb_upper
  14.  
    && cr > cr_lower && cr < cr_upper)
  15.  
    return 1;
  16.  
    else
  17.  
    return 0;
  18.  
    }
  19.  
     
  20.  
    namespace hls {
  21.  
    template<int SRC_T, int DST_T,int ROW, int COL>
  22.  
    void ImgProcess(Mat<ROW, COL, SRC_T> &_src, Mat<ROW, COL, DST_T> &_dst,
  23.  
    int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
  24.  
    {
  25.  
    loop_height: for(HLS_SIZE_T i= 0;i< ROW;i++)
  26.  
    {
  27.  
    #pragma HLS LOOP_TRIPCOUNT max=ROW
  28.  
    loop_width: for (HLS_SIZE_T j= 0;j< COL;j++)
  29.  
    {
  30.  
    #pragma HLS LOOP_FLATTEN OFF
  31.  
    #pragma HLS LOOP_TRIPCOUNT max=COL
  32.  
    #pragma HLS DEPENDENCE array inter false
  33.  
    #pragma HLS PIPELINE
  34.  
    u8 r, g, b;
  35.  
    u1 skin_region;
  36.  
     
  37.  
    HLS_TNAME(SRC_T) temp0=0;
  38.  
    HLS_TNAME(SRC_T) temp1=0;
  39.  
    HLS_TNAME(SRC_T) temp2=0;
  40.  
    /***********stream input *********/
  41.  
    _src.data_stream[0]>>temp0;
  42.  
    _src.data_stream[1]>>temp1;
  43.  
    _src.data_stream[2]>>temp2;
  44.  
     
  45.  
    b = temp0;
  46.  
    g = temp1;
  47.  
    r = temp2;
  48.  
    /********detect skin region*******/
  49.  
    skin_region = rgb2ycbcr(b, g, r,y_lower,y_upper,cb_lower,cb_upper,cr_lower,cr_upper);
  50.  
    HLS_TNAME(DST_T) temp_dst0=0;
  51.  
    HLS_TNAME(DST_T) temp_dst1=0;
  52.  
    HLS_TNAME(DST_T) temp_dst2=0;
  53.  
     
  54.  
    temp_dst0= (skin_region == 1)? b : (u8)0;
  55.  
    temp_dst1= (skin_region == 1)? g : (u8)0;
  56.  
    temp_dst2= (skin_region == 1)? r : (u8)0;
  57.  
     
  58.  
    /***********stream output ********/
  59.  
    _dst.data_stream[0]<<temp_dst0;
  60.  
    _dst.data_stream[1]<<temp_dst1;
  61.  
    _dst.data_stream[2]<<temp_dst2;
  62.  
     
  63.  
    }
  64.  
    }
  65.  
    }
  66.  
     
  67.  
     
  68.  
     
  69.  
    template<int SRC_T, int DST_T,int ROW, int COL>
  70.  
    void SkinColorDetect(Mat<ROW, COL, SRC_T> &_src,Mat<ROW, COL, DST_T> &_dst,
  71.  
    int y_lower,int y_upper,int cb_lower,int cb_upper,int cr_lower,int cr_upper)
  72.  
    {
  73.  
    #pragma HLS INLINE
  74.  
    ImgProcess(_src, _dst, y_lower, y_upper, cb_lower, cb_upper, cr_lower, cr_upper);
  75.  
    }
  76.  
     
  77.  
    }
  78.  
     
  79.  
     
  80.  
     
  81.  
    #endif

 

核心函数是rgb2ycbcr这个函数。关于肤色检测有多种方式,本文的肤色检测方法是将rgb转换为ycbcr,然后设置阈值。

保存后,综合。综合完毕,打开分析工具:

点击红框里的内容:

可以看到imgprocess.h中,ImgProcess这个函数的执行状态:

然后点击ImgProcess_Top_rgb2ycbcr,可以看到如下图:

我们发现,只需一个时钟周期即可执行完毕。这是因为rgb2ycbcr这个函数采用了流水线的优化指令:#pragma HLS PIPELINE。

综合之后,就可以测试了。test.cpp内容如下:

 

  1.  
    #include "top.h"
  2.  
    #include "hls_opencv.h"
  3.  
    #include"iostream"
  4.  
    #include<time.h>
  5.  
    using namespace std;
  6.  
    using namespace cv;
  7.  
     
  8.  
     
  9.  
    int main (int argc, char** argv) {
  10.  
     
  11.  
     
  12.  
     
  13.  
    Mat src = imread("test.jpg");
  14.  
    AXI_STREAM src_axi, dst_axi;
  15.  
    Mat dst(Size(640,480),CV_8UC3);
  16.  
     
  17.  
    resize(src,src,Size(640,480));
  18.  
    //mat to axi video
  19.  
    cvMat2AXIvideo(src, src_axi);
  20.  
    //test function
  21.  
    ImgProcess_Top(src_axi, dst_axi, 480, 640,0,255,80,135,131,185);
  22.  
    //axi video to mat
  23.  
    AXIvideo2cvMat(dst_axi, dst);
  24.  
     
  25.  
    imshow("src",src);
  26.  
    imshow("dst_hls",dst);
  27.  
     
  28.  
    waitKey(0);
  29.  
     
  30.  
    return 0;
  31.  
    }
测试的图像如下:

运行测试程序后,输出图像如下:

通过测试后,点击hls界面工具栏的export RTL按钮,打包生成ip。最后的IP如下所示:

posted @ 2018-07-13 15:34  巴渝男儿  阅读(317)  评论(0)    收藏  举报