肤色是人类皮肤重要特征之一,在检测人脸或手等目标时常采用肤色检测的方法,将相关区域从图像中分割出来。
肤色检测方法有很多,但无论是基于不同的色彩空间还是不同的肤色模型,其根本出发点在于肤色分布的聚集性,即肤色的颜色分量一般聚集在某个范围内。通过大量的肤色样本进行统计,找出肤色颜色分量的聚集范围或用特殊的分布模型去模拟肤色分布,进而实现对任意像素颜色的判别。
本例主要采用肤色颜色分量分布范围的方法,简要介绍肤色模型的概念。
肤色模型是根据大量样本的统计数据建立以确定肤色的分布规律,进而判断像素的色彩是否属于肤色或与肤色相似程度的模型。常用的有阙值模型、高斯模型和椭圆模型。
1)阈值模型
國值模型是用数学表达式明确肤色分布范围的建模方法。这类方法依据肤色分布范围进行检测,判断简单、明确、快捷,但需要选择合适的颜色空间及合适的参数。
2)高斯肤色模型
利用高斯函数模拟肤色在CbCr色度空间的分布
为色度向量的均值和协方差矩阵,可通过多种方式获取,数值略有区别,本例选择
得到肤色分布的概率图后,确定阈值T,如果p>T,则对应像素点为肤色点﹔反之,为非像素点。可以看出,肤色检测的精确度依赖于阈值的选择
在下面示例中,不讨论最佳阈值的确定,采用固定阈值的方法,实施效果因不同图像而异;
3)椭圆模型
将图像从RGB转换到YCbCr彩色空间,并进行非线性分段色彩变换,变换后肤色的CbCr分布近似椭圆,经实验可确定椭圆表达式的参数。对于待判断的颜色,经同样的变换,若在椭圆内,则可以判断其为肤色,否则为非肤色
肤色检测程序实例
clear,clc,close all;
Image=imread('foreman004.jpg');
figure,imshow(Image),title('原图');
r=double(Image(:,:,1)); % 提取红色分量并转化为高精度
g=double(Image(:,:,2));
b=double(Image(:,:,3));
[N,M]=size(r); % 提取矩阵r的大小 NxM
miu=[117.4361 156.5599]'; % 高斯肤色模型均值
sigma=[160.1301 12.1430;12.1430 299.4574]; % 高斯肤色模型协方差矩阵
cbcr=zeros(2,1); % 生成 2x1矩阵
SkinCbCrG=zeros(N,M); % 生成所有值为0的 NxM矩阵用于存放处理后图像
SkinRGB=zeros(N,M);
SkinHSV=zeros(N,M);
SkinCbCr=zeros(N,M);
thresh=0.35; % 肤色概率二值化阙值
for i=1:M % 循环图像每一个像素点 列循环
for j=1:N % 行循环
R=r(j,i); % 将图像红色分量中(j,i)点值赋值给R
G=g(j,i);
B=b(j,i);
if (R>95 && G>40 && B>20 && (R-G)>15 && R-B>15) || ... % RGB空间肤色检测
(R>220 && G>210 && B>170 && R-B<=15 && R>B && G>B) % 符合RGB肤色检测条件的像素点值置1则为白色,其他不符合条件的像素点为0黑色
SkinRGB(j,i)=1;
end
maxRGB=max(max(R,G),B); % 取三分量中同一点最大值
minRGB=min(min(R,G),B); % 取三分量中同一点最小值
C=maxRGB-minRGB; % 取最大差值
V=maxRGB; % 最大值赋值给参数V
if V==0 % 比较最大值是否等于零
S=0;
else
S=C/V; % 最大值不等于零则 C最大差值/V最大值
end
if maxRGB==R % 如果该点最大值==红色分量值;作如下处理
H=60*mod((G-B)/C,6);
elseif maxRGB==G % 如果该点最大值==绿色分量值;作如下处理
H=60*((B-R)/C+2);
elseif maxRGB==B % 如果该点最大值==蓝色分量值;作如下处理
H=60*((R-G)/C+4);
end % 符合HSV肤色检测 将该点值置1
if ((H>=0 && H<=25) || (H>=335 && H<=360)) && (S>=0.2 && S<=0.6) && V>=0.4
SkinHSV(j,i)=1; % 优化 HSV 效果增强?如何改?为什么这样改?
end
R=R/255;G=G/255;B=B/255; % RGB 转 YCrCb 公式
Cb=224*(-0.1687*R-0.3313*G+0.5*B)+128;
Cr=224*(0.5*R-0.4187*G-0.0813*B)+128;
if Cb>=77 && Cb<=127 && Cr>=133 && Cr<=173 % 符合 YCrCb肤色检测 将该点值置1
SkinCbCr(j,i)=1;
end
cbcr= [Cb Cr]'; % YCbCr空间基于高斯模型的肤色检测
p=exp(-0.5*((cbcr-miu)')*(inv(sigma))*(cbcr-miu)); % 高斯模型函数
if p>thresh % p > 阙值0.35 值置1
SkinCbCrG(j,i)=1;
end
end
end
figure,imshow(SkinRGB),title('RGB空间肤色检测');
figure,imshow(SkinHSV),title('HSV空间肤色检测');
figure,imshow(SkinCbCr),title('YCbCr空间范围肤色检测');
figure,imshow(SkinCbCrG),title('YCbCr空间高斯模型肤色检测');
imwrite(SkinRGB,'skinrgb3.jpg');
imwrite(SkinHSV,'skinhsv3.jpg');
imwrite(SkinCbCr,'skincbcr3.jpg');
imwrite(SkinCbCrG,'skinCbCrG3.jpg');
效果分析
从运行结果可以看出,利用各个彩色空间肤色分布范围能够检测出肤色,HSV空间检测的结果比较零散。总体来讲,基于肤色分布范围的检测方法的准确率不高;基于高斯模型的检测结果相对较好,若采用动态阈值方法﹐会进一步提高检测准确性;
下面会以HSV模型为例进行优化:
files=dir('11.jpg'); %读入图片
for i=1:length(files) %循环
s=files(i).name;
I=imread(s); %得到三维矩阵
I1=rgb2hsv(I); %RGB转换为HSV
H=I1(:,:,1);
S=I1(:,:,2);
V=I1(:,:,3);
id=H>=0.0196&H<=0.0791&S>=0.0754&S<=0.6093&V>=0.4706&V<=0.9882; %阈值
figure,subplot(2,1,1),imshow(I), %显示原始图像
subplot(2,1,2),imshow(id)
end
效果比较
(1)HSV空间肤色检测示例一;(2)HSV空间肤色检测示例二;
很明显第一张比第二张肤色检测零散,第二张更为集中;优化效果明显