matlab人脸识别_十一届华中赛人脸识别问题回顾

2018年五一没有出去玩,参加了我第一次数学建模,就是华中赛,当时的我屁都不懂(虽然现在也是),在组里就是端茶递水混子选手。这次建模最大的收获不是一等奖,而是认识了两个建模队友,也是我大学最好的朋友唐j和胡总。最近闲来无事,回顾一下,虽说已经做出来的东西再看意义不大了,但是代码却不是我写的,我的代码力一直是helloworld级别,正好从基础练起。也算是一种学习和生活的记录。

一起骂娘一起笑,一起挠头一起肝,这也许就是建模的魅力吧。

问题重述

随着信息时代的发展,新一代信息技术正在着力打造智慧生活,人工智能 在现代智慧生活中有着举足轻重的地位。什么是人工智能?简而言之就是,让 机器人能够学习并模仿人类行为,甚至能够像人一样思考。人工智能机器人认 识和接触这个世界最主要的途径是“看”和“听”,而第一步就是要让人工智能 机器人能够“看”。

特别地,人脸识别在人工智能中显得特别重要,机器人通 过人脸识别技术认识周围的人,和人们面对面打交道。 人脸识别除了在人工智能中有不少应用之外,这项技术走进了我们的日 常生活:美图秀秀等手机 APP 把人脸识别技术用于“一键美颜”; 有些手 机,自拍时你能看到有一个小方框框住了你的脸,你一动,小方框也会跟着 你动,在相册里,系统能够挑出照片里的各个人物,还能找到这个人物的其 他照片。比如说“How-old.Net”这个 APP,它能看脸猜年龄,曾经风靡了朋 友圈;学校和公司逐步安装了人脸识别考勤机;警方在刑事侦查时,也经常 采用人脸识别技术从海量信息中寻找犯罪嫌疑人;交互式机器人通过人脸识 别技术判断用户的心情…… 先介绍一种常用的人脸识别方法:第一步,确定人脸的位置;第二步, 对人脸做一些技术处理;第三步,提取人脸的细节特征。请建立数学模型, 解决下列三个问题:

(1)建立人脸位置判断的数学模型,判断人脸在照片中的大致位置,并在 图 1 和图 2 中用你设计的模型“框出”人脸的大致位置。

(2)在问题(1)的基础上,建立人脸精确识别的数学模型,判断图 2 中 各个人物的脸型、鼻型、眼型、唇形等。(提示:如果你在 DIY 过程中遇到了困 难,不妨降低要求,比如说鼻型可以分为“大鼻子”和“小鼻子”。)

(3)在问题(2)的基础上,建立人脸匹配的数学模型,判断图 2、图 3 中是否有人物与图 1 的人物是同一人,如果有,请在图片中框出具体是哪个人 物与图 1 的人物一样。

具体附件参见:http://www.saikr.com/vse/35651

问题一

要识别人脸,首先就要定位人脸,问题一就是这么回事。在图像处理中,要把脸部的像素和其他的像素区分开来,这是个分割问题,找阈值是关键。

查阅文献,人脸的肤色经典模型是Ycbcr色彩空间聚类模型,大致思路就是将RGB图片转换到为Ycbcr色彩空间里,分析人脸的聚类特征,从而识别出人脸。以附件一为例,转换后的情况如下:

0a662c5cc4dd2495da95ed8e010b732a.png
RGB到Ycbcr 的转换

之后就可以分析脸有什么特征了,说白了就是脸部的像素值大致在什么范围,为此我把易烊千玺的头“砍下来”了:

26d01cf1592a3d14a1c6a2c896370d65.png
将脸剪切出来

因为这张图大部分面积是脸部,分析这张帅脸的直方图可以发现脸部肤色的像素范围:

0b5d670c4617576f0a679ea880c87e41.png
肤色在Ycbcr的分布特性

可以看到在Cb纬度上,脸大致分布在110左右,在Cr上集中在150左右。可以设定阈值范围了,实际操作中阈值是一个不断微调的过程,不同阈值会有不同的结果,有好有坏,不过题目中说的是“人脸的大致范围”,那我们就知道出题人的意思了:就是说阈值不用太精细了,我们也做不到绝对的精确分割。

划定阈值之后,用“与”操作就可以得到二值图了,此时的二值图是非常粗糙的:

3d13237581b0e4c4ae46657920f4adf3.png

粗糙的图有很多不连续的点,那我们必须加工一下,让脸的信息更突出,最好是一整块白色连通域表示脸,其他黑色区域不是脸。首先是开闭操作填补缝隙去除毛刺:

7431d448a9e6c54196ae1c8ee21556b5.png

很好,最后的图至少没有不连续的点了,都变成一个个区域了。可以看到脸里面还有一块黑色,太丑了要抹掉,就用填充操作吧:

8d617651e3ffadd402d7fccace60e4d7.png

得到两个连通域了,左下角的手的肤色有影响,去掉就好了,连通域操作函数计算两个连通域的面积,把面积小的去掉即可:

d1435cd67d175a589b63d8876ea81898.png

这下就剩一张帅脸了,再用连通域操作函数求得包含连通域的最小矩形,最后在原图上画出这个矩形就ok了,连通域的一系列操作函数可以参考:https://blog.csdn.net/zhu_hongji/article/details/78703161

11552fee78e5dca98ca82f0368958a12.png

第一问就这么搞定了?附件2和3都是多人脸识别问题,场景更复杂,人脸更多,识别效果必定比不上单一人脸,代码也需要微调一下,根据实际选择各种参数,我们的模型只有在附件3中识别的时候有点瑕疵,不过可以写在模型改进里嘛。附件二的识别情况如下:

15a1def7b6f1518a3e765c454b851ff2.png

4f837b604a087f9b1ffd4a0a94d94681.png

801f4bc70e916eb675bc0a97f4e8ed82.png

9da29f56479b72e9a8c333d633d777b8.png

806b05466a190649ddeb728286da18da.png

dd28c840b61e9d608aee0ece3dd9f4b1.png

1b389adb8569cf7f0679f4df732c7e01.png

附件3最终定位了十一张脸,最下面那个连通域始终去除不了,不过有瑕疵在建模中是正常的:

004577e78cd271346a1a7dafa9a3d51d.png

ce8629effacce7b9733aacecd96b0ac9.png

问题一matlab代码如下:

%--------首先完成RGB空间到Ycbcr空间的转换-----------
I=imread('附件_图1.jpg');
I=imresize(I,[400 300],'nearest');
I_ycbcr=rgb2ycbcr(I);
figure(1);
subplot(121),imshow(I),title('RGB空间');
subplot(122),imshow(I_ycbcr),title('Ycbcr空间');

%将脸裁剪出来,分析肤色在cb,cr的分布情况
%-------------------------------------------------
I_2=imread('face_1.png');
I_2=rgb2ycbcr(I_2);
y=I_2(:,:,1);
cb=I_2(:,:,2);
cr=I_2(:,:,3);
figure(2);
subplot(121),imhist(cb);title('Cb分布情况');
subplot(122),imhist(cr);title('Cr分布情况');
%发现Cb大致分布在115左右,Cr大致分布在130左右

%--------------------------------------------------
I_3=(I_ycbcr(:,:,2)>=110)&(I_ycbcr(:,:,2)<=122);
figure;
subplot(121),imshow(I_3),title('Cb提取情况');
I_4=(I_ycbcr(:,:,3)>=140)&(I_ycbcr(:,:,3)<=155);
subplot(122),imshow(I_4),title('Cr提取情况');
I_5=I_4&I_3;
figure;
imshow(I_5);title('粗略二值图')
%--得到的图有不连续点,可通过膨胀腐蚀(开闭运算)去除毛刺--

SE=strel('square',7);
I_5=imclose(I_5,SE);    %首先,闭运算填补缝隙
figure;
subplot(121),imshow(I_5),title('闭运算');
se=strel('disk',6)
I_6=imopen(I_5,SE);     %然后开运算
subplot(122),imshow(I_6),title('开运算');

%--------------下面填充处理形成连通域---------------------
I_6=imfill(I_6,'holes');
figure;
imshow(I_6),title('填充处理');
%-------------------------------------------------------

%--------------接下来连通域处理(去除左下角手的影响)-----
[L,num]=bwlabel(I_6);%L为标注矩阵
s=regionprops(L,'Area');
%算出两个连通区域面积信息,一个为371,一个为4582,设定阈值372删除小的连通域即可
BW=bwareaopen(I_6,372);%该函数删除小于372的连通域
figure;
imshow(BW),title('最终脸部情况');
%----------------------------------------------------------

%----------最后把包含该连通域的矩形画出来即可,注意要在原图上画
s2=regionprops(BW,'BoundingBox');%该函数获取包含连通域的最小矩形
location=s2.BoundingBox;
figure;
imshow(I),title('人脸定位');
hold on
rectangle('Position',location,'LineWidth',2,'Edgecolor','g');
%----至于图二图三,多人脸识别问题需要相应调整代码--------------

问题二,三稍作修改即可,附件2如下:

%--------首先完成RGB空间到Ycbcr空间的转换-----------
I=imread('附件_图2.jpg');
I=imresize(I,[400 300],'nearest');
I_ycbcr=rgb2ycbcr(I);
figure(1);
subplot(121),imshow(I),title('RGB空间');
subplot(122),imshow(I_ycbcr),title('Ycbcr空间');
%--------------------------------------------------
I_3=(I_ycbcr(:,:,2)>=110)&(I_ycbcr(:,:,2)<=122);
figure;
subplot(121),imshow(I_3),title('Cb提取情况');
I_4=(I_ycbcr(:,:,3)>=140)&(I_ycbcr(:,:,3)<=155);
subplot(122),imshow(I_4),title('Cr提取情况');
I_5=I_4&I_3;
figure;
imshow(I_5);title('粗略二值图')
%--得到的图有不连续点,可通过膨胀腐蚀(开闭运算)去除毛刺--

SE=strel('square',7);
I_5=imclose(I_5,SE);    %首先,闭运算填补缝隙
figure;
subplot(121),imshow(I_5),title('闭运算');
se=strel('disk',6)
I_6=imopen(I_5,SE);     %然后开运算
subplot(122),imshow(I_6),title('开运算');

%--------------下面填充处理形成连通域---------------------
I_6=imfill(I_6,'holes');
figure;
imshow(I_6),title('填充处理');
%-------------------------------------------------------

%--------------接下来连通域处理(去除左下角手的影响)-----
[L,num]=bwlabel(I_6);%L为标注矩阵
s=regionprops(L,'Area');
%三个最大的连通域就是脸部,分别为1774,1830,1855
BW=bwareaopen(I_6,1773);%该函数删除小于1774的连通域
figure;
imshow(BW),title('最终脸部情况');
%----------------------------------------------------------

%----------最后把包含该连通域的矩形画出来即可(三个),注意要在原图上画
s2=regionprops(BW,'BoundingBox');%该函数获取包含连通域的最小矩形
location_1=s2(1).BoundingBox;
location_2=s2(2).BoundingBox;
location_3=s2(3).BoundingBox;%三个矩形信息
figure;
imshow(I),title('人脸定位');
hold on
rectangle('Position',location_1,'LineWidth',2,'Edgecolor','g');
hold on
rectangle('Position',location_2,'LineWidth',2,'Edgecolor','g');
hold on
rectangle('Position',location_3,'LineWidth',2,'Edgecolor','g');

附件3代码:

%--------首先完成RGB空间到Ycbcr空间的转换-----------
I=imread('附件_图3.jpg');
I=imresize(I,[400 300],'nearest');
I_ycbcr=rgb2ycbcr(I);
figure(1);
subplot(121),imshow(I),title('RGB空间');
subplot(122),imshow(I_ycbcr),title('Ycbcr空间');
%--------------------------------------------------
I_3=(I_ycbcr(:,:,2)>=115)&(I_ycbcr(:,:,2)<=125);
figure;
subplot(121),imshow(I_3),title('Cb提取情况');
I_4=(I_ycbcr(:,:,3)>=135)&(I_ycbcr(:,:,3)<=150);
subplot(122),imshow(I_4),title('Cr提取情况');
I_5=I_4&I_3;
figure;
imshow(I_5);title('粗略二值图')
%--得到的图有不连续点,可通过膨胀腐蚀(开闭运算)去除毛刺--

SE=strel('square',4);
I_5=imclose(I_5,SE);    %首先,闭运算填补缝隙
figure;
subplot(121),imshow(I_5),title('闭运算');
se=strel('disk',4)
I_6=imopen(I_5,SE);     %然后开运算
subplot(122),imshow(I_6),title('开运算');

%--------------下面填充处理形成连通域---------------------
I_6=imfill(I_6,'holes');
figure;
imshow(I_6),title('填充处理');
%-------------------------------------------------------

%--------------接下来连通域处理(去除左下角手的影响)-----
[L,num]=bwlabel(I_6);%L为标注矩阵
s=regionprops(L,'Area');
BW=bwareaopen(I_6,600);%该函数删除小于600的连通域
figure;
imshow(BW),title('最终脸部情况');
%----------------------------------------------------------

%----------最后把包含该连通域的矩形画出来即可,注意要在原图上画
s2=regionprops(BW,'BoundingBox');%该函数获取包含连通域的最小矩形
figure;
imshow(I),title('人脸定位');
%------最终识别出11个连通域,正确应该是10张脸
for i=1:1:11
    rectangle('Position',s2(i).BoundingBox,'LineWidth',2,'Edgecolor','g');
hold on
end
%------第一问解决------------------------------

至此第一问圆满解决。插个分割线以后再更(以我拖沓的作风也许不会再更哈哈哈)


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值