MATLAB 图像处理 简单人脸检测(详细,你上你也行)
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('二值化')
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('把空洞填了')
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);
最后为了循环过程中提升运算速度,将数据类型更改为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:divy1 = 1;y2 = c;%对应列初始化for j=1:divloc = 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 <=100BW(x1:x2,y1:y2) = 0;end%imshow(BW)elseif rate <=25BW(x1:x2,y1:y2) = 1;end%imshow(BW)end%下一列y1 = y1 + c;y2 = y2 + c;end%下一行x1 = x1 + r;x2 = x2 + r;
end
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。
第一行计算长宽比,得到的pickshape向量的每一行对应每个方框的长宽比。由于有的方框明显过于扁平或者过于狭长,这种方框应该是要扔掉的。
所以第二行,通过逻辑表达式从BB内筛选出尺寸比例合格的方框,存在shapeind里面。
剩下的尺寸符合要求的方框里面要选出面积最大的那个,最后一行,得到面积最大的方框对应的索引。
3 检测结果
以看到边界被成功提取了出来,在人脸部形成了一个比较大的连通域
可以看到,进行边界加粗和空洞添补之后,眼睛部分的黑块被消除了,这使得脸部连通域更大了
注意观察图片左边的相分离的白块,在纵向闭操作之后连在了一起,同时脸部连通域进一步扩大,然后横向腐蚀在尽量维持脸部连通域大小的情况下减小了图片下方连通域。
---%%%完整代码
rgb = imread('f.jpg');
I = rgb2gray(rgb);
[n1,n2] = size(I);
%灰度图
figure,imshow(I),title('灰度图')
tic
h = ones(9)/81;
I = uint8(conv2(I,h));
figure,imshow(I),title('线性均值滤波')
BW = imbinarize(I);
figure,imshow(BW),title('二值化')
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('把空洞填了')
%进行形态学运算
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);%%将数据载入gpu可以加速,电脑不一定支持%最小化背景
%细分
div = 10;
r = floor(n1/div);%分成10块 行
c = floor(n2/div);%分成10块 列
x1 = 1;x2 = r;%对应行初始化
s = r*c;%块面积
%判断人脸是否处于图片四周,如果不是就全部弄黑
%figure
for i=1:divy1 = 1;y2 = c;%对应列初始化for j=1:divloc = 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 <=100BW(x1:x2,y1:y2) = 0;end%imshow(BW)elseif rate <=25BW(x1:x2,y1:y2) = 1;end%imshow(BW)end%下一列y1 = y1 + c;y2 = y2 + c;end%下一行x1 = x1 + r;x2 = x2 + r;
endfigure
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('人脸检测')
toc
MATLAB 图像处理 简单人脸检测(详细,你上你也行)相关推荐
- 人脸检测技术即matlab的实现,人脸检测研究及MATLAB实现.doc
摘要:随着计算机视觉技术的不断发展,各种识别技术已经成功投入使用,服务于我们的日常生活中,其中对于人脸的识别技术应用最为广泛.人脸检测作为识别领域最为重要的一个分支,其应用领域十分广阔.人脸检测通过对 ...
- Java 图像处理教程(人脸检测,添加水印,图像颜色转换)
Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 文章目录 Java 图像处理教程(人脸检测,添加水印,图像颜色转换) 1:图片的读和写 2:彩色图像转换成灰度图像 3:彩色图像转换成负图像 ...
- 人脸检测:史上最详细人脸检测libfacedetection讲解-网络详解--第二节
以下是关于我个人对libfacedetection(人脸检测-pytorch)的所有见解,如有错误欢迎大家在评论区指出,我将会第一时间纠正.据说,人脸检测速度可以达到1000FPS,到底结果如何,我们 ...
- 基于matlab实现的人脸检测
作为一个图像处理的初学者,一直想写一个人脸检测的程序,经过多次尝试,发现不管是在C站上找的开源代码,还是自己手撸的代码,总是那么不尽人意.后来经过查阅资料,发现matlab内置有一个人脸检测的检测器函 ...
- 图像处理------简单脸谱检测算法
介绍基于皮肤检测之后的,寻找最大连通区域,完成脸谱检测的算法.大致的算法步骤如下: 原图如下: 每步处理以后的效果: 程序运行,加载选择图像以后的截屏如下: 截屏中显示图片,是适当放缩以后,代码如下: ...
- MATLAB学习笔记 人脸检测
需要安装计算机视觉系统工具箱 Computer Vision Toolbox - MATLAB & Simulinkhttps://ww2.mathworks.cn/products/comp ...
- 一种用于人脸检测的设备上的深度神经网络
欢迎大家前往云加社区,获取更多腾讯海量技术实践干货哦~ 译者:QiqiHe 苹果公司开始在iOS 10中使用深度学习进行人脸检测.随着Vision框架的发布,开发人员现在可以在他们的应用程序中使用这种 ...
- 大小仅1MB,超轻量级通用人脸检测模型登上GitHub趋势榜
机器之心报道 项目作者:Linzaer 近日,用户 Linzaer 在 Github 上推出了一款适用于边缘计算设备.移动端设备以及 PC 的超轻量级通用人脸检测模型,该模型文件大小仅 1MB,320 ...
- OpenCV实现简单人脸检测
用OpenCV实现简单的人脸识别,基于静态图像. 1.材料准备:找到OpenCV提供的人脸训练模型文件.可以通过 https://github.com/opencv/opencv/tree/maste ...
- 2 找图像连通域_MATLAB--数字图像处理 简单人脸识别
简单人脸识别 思路 找到图像中连通域面积最大的那块连通域. i=imread('face.jpg'); I=rgb2gray(i); BW=im2bw(I); %利用阈值值变换法将灰度图像转换成二进制 ...
最新文章
- Postgresql:删除及查询字段中包含单引号的数据
- 天下苦同行评审久矣,要不我们把它废除掉?
- linux鼠标触摸屏应用程序,在Ubuntu环境下实现插入鼠标自动关闭触摸板
- [RabbitMQ]工作队列原理_代码实现
- go https client
- Kubernetes知识体系-从入门到精通
- world: 对比两个文档
- 【渝粤教育】电大中专计算机职业素养 (6)作业 题库
- SQL动态配置,动态解析SQL
- IAR基础教程之函数跳转
- 珍藏的Android开发必备网站和工具(开发工具总结)
- unity学习笔记-Avpro和安卓结合
- 高等数学期末总复习DAY12.复合函数的链式求导、隐函数求导、
- java filer,java – Filer的原始元素是否有用?
- 笔记-Java基础语法-二进制
- stackoverflow愚人节彩蛋效果
- 打工与创业的有什么区别,丨国仁网络资讯
- Logstash 算术运算操作
- flink source 同步_网易云音乐基于 Flink + Kafka 的实时数仓建设实践
- 函数定义与调用,自己实现pow()函数对整数的运算