本博客涉及到的所有代码和图片都可以到GitHub上进行下载。将其中所有文件下载到同一个目录下,在matlab中运行main.m即可。
1 问题描述
该博客来源于斯坦福大学2002-2003年春季的”数字图像处理课程“,题目就是"Face Detection"。这个项目提供了七张训练图片和对应的Ground Truth。如下,展示的是其中一张测试图片和对应的Ground Truth。
图1 测试图片 | 图2 Ground Truth |
图2中白色的部分表示男生的人脸,红色表示女生的人脸。该博客不涉及性别识别,所以不考虑这个区别。
七张训练图片中包含的人都大体相同,只是每个人的位置和图片的背景有所区别。除了七张训练图片外,这个项目还提供了一张测试图片和对应的Ground Truth,要做的就是根据所有的训练图片找出测试图片中的人脸。
2 算法描述
2.1 颜色分割
利用颜色分割的方式进行人脸分割是一种非常成熟的方法,常见的颜色模型有RGB、HSV、YIQ和YCbCr等。该实验要处理的图片都是基于RGB模型,但是RGB图片三个通道之间的关联性很强并且容易受到不同光照的影响,不太适合于图片阈值分割。
该实验采用YCbCr颜色模型,其中Y分量包含亮度信息,Cb和Cr分量包含色度信息,因此去掉Y分量就可以减少不同亮度条件下对人脸检测的影响。
RGB转换到YCbCr的公式如下式(1)。
(1) [ Y C b C r ] = [ 0.299 0.587 0.114 − 0.169 − 0.331 0.500 0.500 − 0.419 − 0.081 ] [ R G B ] \begin{bmatrix} Y \\ Cb \\ Cr \end{bmatrix} = \begin{bmatrix} 0.299 & 0.587 & 0.114 \\ -0.169 & -0.331 & 0.500 \\ 0.500 & -0.419 & -0.081 \end{bmatrix} \begin{bmatrix} R \\ G \\ B \end{bmatrix} \tag{1} ⎣⎡YCbCr⎦⎤=⎣⎡0.299−0.1690.5000.587−0.331−0.4190.1140.500−0.081⎦⎤⎣⎡RGB⎦⎤(1)
在Matlab中自带了rgb2ycbcr的函数,可以方便地实现颜色空间转换,但是并没有按照式(1)进行转换,最终的结果都是无符号数。我自己按照上式重新完成了ycbcr.m的函数。
function ycc = ycbcr(rgb)
% function ycc = rgb2ycc(rgb)
% convert rgb image to ycc image
% Inputs:
% rgb - rgb image
%
% Outputs:
% ycc - ycc image
% reshape image to 2d matrix
rgb = double(rgb);
[m, n, p] = size(rgb);
rgb_2d = reshape(rgb, m*n, p);
% convert parameters
origT = [0.299 0.587 0.114;...
-0.169 -0.331 0.5; ...
0.5 -0.419 -0.081];
% rgb to ycc
ycc_2d = origT*rgb_2d';
y = ycc_2d(1, :)';
cb = ycc_2d(2, :)';
cr = ycc_2d(3, :)';
y = reshape(y, m, n);
cb = reshape(cb, m, n);
cr = reshape(cr, m, n);
ycc = cat(3, y, cb, cr);
end
cbcrPlate.m调用ycbcr.m,可以得到所有训练图片中的人脸在Cb-Cr坐标系下的分布,如下图3。
图3 Cb-Cr分布
cbcrPlate.m可以得到人脸在Cb-Cr坐标系下的均值和标准差,如下式(2)。
(2) [ c b _ m e a n c b _ s t d c r _ m e a n c r _ s t d ] = [ − 11.7334 5.6738 23.3290 7.1929 ] \begin{bmatrix} cb\_mean & cb\_std \\ cr\_mean & cr\_std \end{bmatrix} = \begin{bmatrix} -11.7334 & 5.6738 \\ 23.3290 & 7.1929 \end{bmatrix} \tag{2} [cb_meancr_meancb_stdcr_std]=[−11.733423.32905.67387.1929](2)
图3中绿框是根据实验得到的经验范围,以cb_mean和cr_mean为中点,宽为4倍的cb_std,高为2倍的cr_std。
2.2 人脸分割
根据式(2)得到的Cb-Cr阈值,对测试图像进行二值化处理,可以初步得到图4的结果。
图4 Cb-Cr阈值分割
从图4的结果开始,多次进行填补背景、去掉小面积前景、腐蚀、边缘提取,从而去掉大部分非皮肤的部分。最后利用统计信息去掉手、胳膊和腿部的皮肤。流程如下图5。
图5 人脸分割流程图
其中去掉小面积前景的阈值设置为500像素,这是多次实验的结果,既可以去掉大部分无关的区域,又可以保留大多的人脸区域。腐蚀采用的是5*5的全1矩阵,两次使用腐蚀可以去掉小面积的前景并且有效的分开重叠的人脸。在第二次腐蚀之前需要进行边缘提取,这样可以提取出大部分人脸的轮廓。该实验采用的是参数为0.1的Roberts算子,这样既可以保证准确性,也可以保证提取速度,边缘提取结果如下图6。
图6 边缘提取结果
通过流程图所示的处理之后,可以得到二值化图7以及效果图8。
图7 二值化图
图8 效果图
从图中可以看出仍有部分手和胳膊被标记成了人脸,可以根据统计信息来去掉这些扰乱信息。统计信息主要包括标记区域的长、宽以及长宽比。通过实验可以得出当宽高比小于0.75或者大于3,或者宽小于40像素并且高小于50像素的情况下基本是非人脸区域,如图9。人脸检测的最终结果如图10。
图9 标记区域统计结果
图10 人脸检测最终结果
3 总结
该博客来源于斯坦福大学2002-2003年春季“数字图像处理”课程,题目就是"Face Detection"。评价标准包括正确检出数、错误检出数和人脸合并数。所有训练图片和测试图片的检测如下表1。当然目前存在的问题还有很多,比如漏检、错检、人脸合并、同一张人脸检测成多张等问题,需要进一步改善。
测试图片 | 图片人脸数 | 检出区域 | 正确检出数 | 错误检出数 | 人脸合并数 |
---|---|---|---|---|---|
TestImage.jpg | 23 | 23 | 21 | 2 | 1 |
表1 检测结果