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例如以下所看到的:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTFpZMjcyOTQyNTE4/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
HLS图像处理系列——肤色检測的更多相关文章
- 图像处理之Canny边缘检測
图像处理之Canny 边缘检測 一:历史 Canny边缘检測算法是1986年有John F. Canny开发出来一种基于图像梯度计算的边缘 检測算法,同一时候Canny本人对计算图像边缘提取学科的发展 ...
- 爱国者布局智能硬件,空探系列PM2.5检測仪“嗅霾狗”大曝光
随着6月1日史上最严禁烟令的正式实施,国内包含北京.上海.成都等大中型城市已经在公共场所全面禁烟.众所周知,实施禁烟令的根本在于促进空气的净化,实现环境的改善,要达到这个目的,光有禁烟令是远远 ...
- Python图像处理(8):边缘检測
快乐虾 http://blog.csdn.net/lights_joy/ 欢迎转载,但请保留作者信息 此前已经得到了单个区域植株图像,接下来似乎应该尝试对这些区域进行分类识别.通过外形和叶脉进行植物种 ...
- OpenCV图像处理篇之边缘检測算子
3种边缘检測算子 灰度或结构等信息的突变位置是图像的边缘,图像的边缘有幅度和方向属性.沿边缘方向像素变化缓慢,垂直边缘方向像素变化剧烈.因此,边缘上的变化能通过梯度计算出来. 一阶导数的梯度算子 对于 ...
- 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...
- Matlab图像处理系列2———空间域平滑滤波器
注:本系列来自于图像处理课程实验,用Matlab实现最主要的图像处理算法 本文章是Matlab图像处理系列的第二篇文章.介绍了空间域图像处理最主要的概念----模版和滤波器,给出了均值滤波起和中值滤波 ...
- 【OpenCV新手教程之十七】OpenCV重映射 & SURF特征点检測合辑
本系列文章由@浅墨_毛星云 出品.转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/30974513 作者:毛星云(浅墨) ...
- 目标检測的图像特征提取之(一)HOG特征
1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检測的特征描写叙述子.它通过计算和统计图像局部区 ...
- AIX下RAC搭建 Oracle10G(一)检測系统环境
AIX下RAC搭建系列 环境 节点 节点1 节点2 小机型号 IBM P-series 630 IBM P-series 630 主机名 AIX203 AIX204 交换机 SAN光纤交换机 存储 S ...
随机推荐
- PairRDD中算子aggregateByKey图解
PairRDD 有几个比较麻烦的算子,常理解了后面又忘记了,自己按照自己的理解记录好,以备查阅 1.aggregateByKey aggregate 是聚合意思,直观理解就是按照Key进行聚合. 转化 ...
- 解析:SO_REUSEADDR bind: address in use
http://blog.sina.com.cn/s/blog_53a2ecbf010095db.html socket中的SO_REUSEADDR Q: 我正在写一个unix server程序,不是d ...
- 修改 login的串口重定向
1 在console-telnet 使用vi工具编辑 /etc/inittab 文件 vi /etc/inittab (回车)2 按 i 进入编辑模式:3 将文件中的ttyS0 改为 ttyS3 ...
- BUS Matrix
ARM的BUS Matrix就是多主(Core,DMA等).多从(内部RAM,APB,外部总线等)的交联和仲裁.目的是为了提高不同主机访问不同外设情况下的带宽,另外一个就是简化Bus Master的协 ...
- git不能上传空目录和设备文件
git不能上传空目录和设备文件:目录和设备文件不能完成校验. 使用命令校验: sha1sum console
- VMware网络连接失败
假如你碰到了VMware 网络被断开, 明明已经分配了适配器, 客户端却显示网络断开没有连接. 可用恢复默认的方法重置所有网卡及服务. 进主工具首页.点击: 虚拟网络编辑器,然后点击下面的恢复默认. ...
- WF追忆
前一阵子学习了一下工作流,现在写个总结记录一下这个过程.要弄工作流,首先就要有个界面来画图,做web的,没办法,只能选择javascript和silverlight,找来找去,最后用了Shareide ...
- 记录日志框架:log4net使用
一.log4net简介 Log4net是Apache下一个开放源码的项目,我们可以控制日志信息的输出目的地.Log4net中定义了多种日志信息输出模式.在做项目的时候最头疼的是在程序发布到正式环境之后 ...
- 二、Linux 静态IP,动态IP配置
Linux 静态IP,动态IP配置 第一步:激活网卡 系统装好后默认的网卡是eth0,用下面的命令将这块网卡激活. # ifconfig eth0 up 第二步:设置网卡进入系统时启动 想要每次开机就 ...
- js学习笔记19----getElementsByClassName函数封装
js里面的getElementsByClassName()方法可通过某个class名获取到元素,在标准浏览器下可使用,在非标准浏览器下不可用.为了能够让这个方法兼容所有的浏览器,可以封装成如下函数: ...