⽬录
1.⼈脸检测原理框图
2 步骤
2.1 均值滤波
2.2 ⼆值化
2.4 纵向闭合与横向腐蚀
2.5 消除边界多余连通域
2.6 寻最⼤连通域并画框
3 检测结果
1.⼈脸检测原理框图
整体思路是寻图⽚中最⼤的连通域,将其认定为⼈脸。
第⼀个环节均值滤波,是为了减弱图像的相关细节部分,以免⽑刺影响后期连通域的形成,⼆值化⽅便形态学处理,减少运算量。考虑到⼈脸有⿊⼈和⽩⼈黄种⼈,⿊⼈肤⾊较深,在⼆值化之后⾯部区域不容易形成较⼤的连通域,如果采取形态学边界提取的办法,就可以避免这个问题,形态学边界提取,只要结构元素够⼤,也可以形成较⼤的封闭连通域。 然后就是纵向闭合操作,这⼀步我选择采⽤竖向长条状的结构元素进⾏闭合运算,因为⼈的脸部和颈部以及头发和⾐物等等都是纵向分布的,在进⾏形态学边界提取的时候,容易将这些靠近的成分割裂开来,这对连通域的判断极为不利,所以⽤竖向长条状的结构元素在在纵向进⾏闭合运算,将脸部上下部的区域重新连接起来。
紧接着我⼜⽤横向长条状结构元素进⾏横向腐蚀运算,这是因为,⼈的头部以下的⾝体部分存在有⼤量连通域的时候,容易对最⼤连通域的判决产⽣⼲扰,⼜因为下半部分,多半呈纵向分布,通过横向腐蚀可以将这些⼤块的连通域割裂开来,但是要注意的是,割裂程度不应太⼤,否则会使得上⼀步闭合操作丧失意义。
接着,由于背景杂物等因素,同样也会产⽣⼤量连通域,这会对最后结果的判决产⽣⼲扰,因此要予以剔除。
进⾏了层层筛选之后,在剩下的连通域⾥⾯挑⼀个最⼤的连通域,并且尺⼨形状满⾜要求的⽤矩形框框起来作为⼈脸检测结果。
2 步骤
2.1 均值滤波
h = ones(9)/81;
I = uint8(conv2(I,h));
figure,imshow(I),title('线性均值滤波')
采⽤9x9模板进⾏线性均值滤波,因为后⾯调⽤gpuArray()函数转换对输⼊数据有要求,所以在进⾏了⼆维卷积之后重新将数据格式转换成8位⽆符号整形数据。
2.2 ⼆值化
BW = imbinarize(I);
figure,imshow(BW),title('⼆值化')
直接调⽤imbinarize对图像进⾏⼆值化
2.3.形态学边界提取
B = ones(21);%结构元素
BW = -imerode(BW,B) + BW;
figure,imshow(BW),title('形态学边界提取')
BW = bwmorph(BW,'thicken');
figure,imshow(BW),title('加粗边界')
BW = not(bwareaopen(not(BW), 300));
figure,imshow(BW),title('把空洞填了')
结构元素采⽤21x21⼤⼩的全1矩阵,先调⽤imrode()进⾏腐蚀,再⽤原图减去腐蚀结果,得到边界。为了让边界更加明显,调⽤bmworph函数,传
⼊'thicken'参数,意在将边界加粗加厚。最后为了把空洞就是连续的⼩⿊⾊块填满,调⽤bwareaopen()函数,该函数是去除⾯积⼩于300的⽩块,为了去除⿊块,先调⽤not(BW)给原来的⼆值图像取反,去掉取反后⾯积⼩于300的⽩块,再次取反,达到去掉⾯积⼩于300的⿊块的⽬的。
采摘网2.4 纵向闭合与横向腐蚀
%进⾏形态学运算
B = strel('line',50,90);
BW = imdilate(BW,B);
BW = imerode(BW,B);
figure,imshow(BW),title('再闭操作之后')
B = strel('line',10,0);
BW = imerode(BW,B);
活动看台figure,imshow(BW),title('闭操作之后再腐蚀')
BW = gpuArray(BW);
调⽤strel()函数⽣成特定的结构元素,第⼀步调⽤strel(‘line',50,90),意思是调⽤直线型结构元素,长度为50,⾓度90度,也就是竖直的长条形结构元素。接着利⽤B调⽤imdilate和imerode,先进⾏膨胀再进⾏腐蚀完成闭操作运算。下⼀步,继续⽣成横向长条形结构元素,进⾏腐蚀操作,注意这⾥的结构元素不宜⾯积太⼤,长度太长,否则会过度影响上⼀步的结果
最后为了循环过程中提升运算速度,将数据类型更改为gpuArray(),可以在GPU上进⾏计算,节省时间。
2.5 消除边界多余连通域
%最⼩化背景
%细分
div = 10;
r = floor(n1/div);%分成10块⾏
c = floor(n2/div);%分成10块列
x1 = 1;x2 = r;%对应⾏初始化
s = r*c;%块⾯积
%判断⼈脸是否处于图⽚四周,如果不是就全部弄⿊
%figure
for i=1:div
y1 = 1;y2 = c;%对应列初始化
for j=1:div
loc = find(BW(x1:x2,y1:y2)==0);%统计这⼀块⿊⾊像素的位置
num = length(loc);
rate = num*100/s;%统计⿊⾊像素占⽐
if (y2<=0.2*div*c||y2>=0.8*div*c)||(x1<=r||x2>=r*div)
if rate <=100
BW(x1:x2,y1:y2) = 0;
end
%imshow(BW)
else
if rate <=25
BW(x1:x2,y1:y2) = 1;
型采end
%imshow(BW)
end%下⼀列
y1 = y1 + c;
y2 = y2 + c;
end%下⼀⾏
打包交易x1 = x1 + r;
x2 = x2 + r;
end
对于周围多余的杂物产⽣的连通域,我选择先将整幅图像划分为很多⼩块,对⼀部分在图像边缘的⼩块全部置成⿊⾊,对不在边缘的通过计算其中⿊⾊像素⽐例来判定是否应该全部给成⽩⾊。因为图⽚中央可能还会存在⼀些细⼩空洞,这些空洞在每⼀⼩块占⽐不是很⼤但有可能影响连通性,如果⼀个⼩块⾥⾯⼤部分是⽩⾊就全部给成⽩⾊,⽅便后期判定最⼤连通域。
Div是均分⽐例,我这⾥设置成10,也就是将整个图像划分成100个⼩块。r就是在⾏⽅向上⼀个⼩块占多少像素,c就是在列⽅向上⼀个⼩块有多少像素。⽤两层循环来遍历每个⼩块,通过find(x1:x2,y1:y2)==0返回所有满⾜要求的像素的索引,索引长度就是⿊⾊像素的个数。
通过条件判断是否在边界。
2.6 寻最⼤连通域并画框
figure
subplot(1,2,1)
imshow(BW)
title('最终处理')
L = bwlabel(BW,8);%利⽤belabel函数对8连通域区间进⾏标号
短信发技术BB = regionprops(L,'BoundingBox');%得到矩形框,框柱每⼀个连通域
BB = cell2mat(struct2cell(BB));
[s1,s2] = size(BB);
BB = reshape(BB,4,s1*s2/4)';
pickshape = BB(:,3)./BB(:,4);%
shapeind = BB(0.3<pickshape&pickshape<3,:);%筛选掉尺⼨⽐例不合格
[~,arealind] = max(shapeind(:,3).*shapeind(:,4));
subplot(1,2,2)
imshow(rgb)
hold on
rectangle('Position',[shapeind(arealind,1),shapeind(arealind,2),shapeind(arealind,3),shapeind(arealind,3)],...
'EdgeColor','g','Linewidth',2)
title('⼈脸检测')
经过消除边界多余连通域后得到的BW中剩下的连通域内存在着我们需要的那个对应⼈脸的连通域。⼀般情况下,对应⼈脸的那个连通域会是最⼤的连通域。
调⽤bwlabel(BW,8)函数给所有连通域标记,其中邻域规则采⽤8邻域,返回⼀个被标记过连通域的图像,第k个被标记的连通域所有像素值为k。
箱包手把调⽤regionprops(L,'BoundingBox')函数,传⼊参数L和'BoundingBox',该函数⽤于获取图像的各种属性,传⼊'BoundingBox'返回的是⼀个结构体,每⼀个结构体内都包含了⼀个能框柱其对应连通域的最⼩⽅框。⼀个⽅框,⽤⼀个序列来描述[x,y,width,height],这个序列包含了⽅框左上⾓像素的坐标以及长和宽。
这三条语句,第⼀条⽤来将结构体转换成矩阵向量,⽅便计算。第⼆⾏获取这个矩阵的维度。由于BB刚转换成向量的时候,是⼀个⾏向量,每4个元素1组对应⼀个⽅框。为了后续计算⽅便,使⽤reshape()函数,将BB重构成⼀个矩阵,这个矩阵有4列,每⼀列对应⽅框的⼀个参数,⽐如坐标,长宽等等。每⼀⾏对应⼀个⽅框。
第⼀⾏计算长宽⽐,得到的pickshape向量的每⼀⾏对应每个⽅框的长宽⽐。由于有的⽅框明显过于扁平或者过于狭长,这种⽅框应该是要扔掉的。
所以第⼆⾏,通过逻辑表达式从BB内筛选出尺⼨⽐例合格的⽅框,存在shapeind⾥⾯。
剩下的尺⼨符合要求的⽅框⾥⾯要选出⾯积最⼤的那个,最后⼀⾏,得到⾯积最⼤的⽅框对应的索引。
把⽅框画出来。
3 检测结果
图 15rgb图像转换成灰度图像图 16线性均值滤波结果
可以看到,均值滤波使得图像变模糊了细节减少
图 17⼆值化结果图 18形态学边界提取结果
以看到边界被成功提取了出来,在⼈脸部形成了⼀个⽐较⼤的连通域
可以看到,进⾏边界加粗和空洞添补之后,眼睛部分的⿊块被消除了,这使得脸部连通域更⼤了
注意观察图⽚左边的相分离的⽩块,在纵向闭操作之后连在了⼀起,同时脸部连通域进⼀步扩⼤,然后横向腐蚀在尽量维持脸部连通域⼤⼩的情况下减⼩了图⽚下⽅连通域。
可以看到效果还可以。还有其他的测试结果
图 24测试样例
图 25测试样例