TA的每日心情 | 开心 2021-12-13 22:32 |
---|
签到天数: 4 天 连续签到: 1 天 [LV.2]偶尔看看I
|
肤色作为人的体表显著特征之一,尽管人的肤色因为人种的不同有差异,呈现出不同的颜色,但是在排除了亮度和视觉环境等对肤色的影响后,皮肤的色调基本一致,这就为利用颜色信息来做肤色分割提供了理论的依据。在肤色识别中,常用的颜色空间为 YCbCr 颜色空间。在 YCbCr 颜色空间中,Y 代表亮度,Cb 和 Cr分别代表蓝色分量和红色分量,两者合称为色彩分量。 YCbCr 颜色空间具有将色度与亮度分离的特点,在 YCbCr 色彩空间中,肤色的聚类特性比较好,而且是两维独立分布,能够比较好地限制肤色的分布区域,并且受人种的影响不大。对比 RGB 颜色空间和 YCbCr 颜色空间,当光强发生变化时,RGB 颜色空间中(R,G,B)会同时发生变化,而 YCbCr 颜色空间中受光强相对独立,色彩分量受光强度影响不大,因此 YCbCr 颜色空间更适合用于肤色识别。
由于肤色在 YCbCr 空间受亮度信息的影响较小,本算法直接考虑 YCbCr 空间的 CbCr 分量,映射为两维独立分布的 CbCr 空间。在 CbCr 空间下,肤色类聚性好,利用人工阈值法将肤色与非肤色区域分开,形成二值图像。
RGB 转 YCbCr 的公式为:
Y = 0.257*R+0.564*G+0.098*B+16
Cb= -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128
对肤色进行判定的条件常使用如下判定条件:
Cb > 77 && Cb < 127
Cr > 133 && Cr < 173
检测算法实现:
Step1:打开 HLS,按照之前介绍的方法,创建一个新的工程,命名为 Skin_Dection。
Step2:右单击 Source 选项,选择 New File,创建一个名为 Top.cpp 的文件。
Step3:在打开的编辑区中,把下面的程序拷贝进去:
- #include "top.h"
- #include <string.h>
- void hls::hls_skin_dection(RGB_IMAGE& src, RGB_IMAGE& dst,int rows,
- int cols,
- int y_lower,int y_upper,int cb_lower,int cb_upper,int
- cr_lower,int cr_upper)
- {
- LOOp_ROWS:for(int row = 0; row < rows ; row++)
- {
- LOOp_COLS:for(int col = 0; col < cols; col++)
- {
- //变量定义
- RGB_PIXEL src_data;
- RGB_PIXEL pix;
- RGB_PIXEL dst_data;
- bool skin_region;
- if(row < rows && col < cols) {
- src >> src_data;
- }
- //获取RGB通道数据
- uchar B = src_data.val[0];
- uchar G = src_data.val[1];
- uchar R = src_data.val[2];
- //RGB-->YCbCr颜色空间转换
- uchar y = (76 * R + 150 * G + 29 * B) >> 8;
- uchar cb = ((128*B -43*R - 85*G)>>8) + 128 ;
- uchar cr = ((128*R -107*G - 21 * B)>>8)+ 128 ;
- //肤色区域判定
- if (y > y_lower && y < y_upper && cb > cb_lower && cb <
- cb_upper && cr > cr_lower && cr < cr_upper)
- skin_region = 1;
- else
- skin_region = 0;
- uchar temp0= (skin_region == 1)? (uchar)255: B;
- uchar temp1= (skin_region == 1)? (uchar)255: G;
- uchar temp2= (skin_region == 1)? (uchar)255: R;
- dst_data.val[0] = temp0;
- dst_data.val[1] = temp1;
- dst_data.val[2] = temp2;
- dst << dst_data;
- }
- }
- }
- 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)
- {
- RGB_IMAGE img_0(rows, cols);
- RGB_IMAGE img_1(rows, cols);
- #pragma HLS dataflow
- hls::AXIvideo2Mat(input,img_0);
- hls::hls_skin_dection(img_0,img_1,rows,cols,y_lower,y_upper,cb_lower,cb_upp
- er,cr_lower,cr_upper);
- hls::Mat2AXIvideo(img_1, output);
- }
复制代码 Step4:在 Test Bench 中,用同样的方法添加一个名为 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)
- {
- //IplImage* src = cvLoadImage(INPUT_IMAGE);
- IplImage* src = cvLoadImage("test.jpg");
- //IplImage* src = cvLoadImage("test_img1.jpg");
- IplImage* dst = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
- AXI_STREAM src_axi, dst_axi;
- IplImage2AXIvideo(src, src_axi);
- ImgProcess_Top(src_axi, dst_axi, src->height,
- src->width,0,255,75,125,131,185);
- AXIvideo2IplImage(dst_axi, dst);
- cvShowImage("src",src);
- cvShowImage("dst_hls",dst);
- waitKey(0);
- return 0;
- }
复制代码 Step6:在 Test Bench 中添加一张名为 test.jpg 的测试图片,完整的工程如下图所示
代码综合:
算法的关键就是进行 RGB 到 YCbCr 颜色空间的转换,其关键算法如下,可以发现其实算法只需要几十行就可以很容易的实现检测算
法,不过需要大家注意的是因为使用 C++进行开发,那么为了程序的通用性以及方便团队合作开发,建议大家使用 namespace 命名空间,这样可以很好的解决重名问题,而且可以增加程序的可读性:
代码综合。
Step1:单击 Project—project settings 命令。
Step2:在弹出的窗口中选择综合选项,然后在顶层函数设置区中单击右边的 Browse„按钮
Step3:选择 ImgProcess_Top 为顶层函数,然后单击两次 OK,完成工程的设置
Step4:单击综合快捷按钮开始代码综合
代码优化
仿真测试:
通过对比发现基于颜色空间转换加阈值进行判断能在一定程度上进行检测,但是存在的检测误差较大的,在实际的项目应用中,需要对算法本身进行优化,,虽然最后发现基于颜色空间转换加阈值进行肤色检测的结果又一点误差,但我们完全可以对算法进行优化,减小误差。
|
|