云社区 博客 博客详情

【2020华为云AI实战营】第4章人脸检测作业1的拓展作业

qwertyuiopasdfg 发表于 2020-07-04 01:36:55 2020-07-04
0
2

【摘要】 对自己做的小数据集合,通过完成实践的简单代码分别用dlib、MTCNN、OpenCV这三种方法进行人脸的检测,对数据进行简单的统计与整理,并对结果进行简单的分析,从而更好的了解在默认参数下,三种不同人脸检测工具在不同检测场景下的的特点与区别。

注:都不太会的人一只...但是努力做了这个作业...其中很可能有很多很多很多不对地方,欢迎&&希望阅者能够指出.....

注:理论上说是作业...但是这个写的比较随意,感觉跟符合我的博客风格(u1s1,是幻想的风格 ..因为没写过博客qaq),就也发上来了,科科....这博客为啥照片自动拉宽到100%...有亿点丑...

1 摘要

2 实践环境

3 实践过程

3.1 数据准备

3.2 代码调整

3.3 运行测试

3.4 测试结果处理

3.5 结果分析

4 总结

5 附录 

5.1 附录一:致谢

5.2 附录二:实践数据下载指南

6 完结撒花


1 摘要


对自己做的小数据集合,通过完成实践的简单代码分别用dlib、MTCNN、OpenCV这三种方法进行人脸的检测,对数据进行简单的统计与整理,并对结果进行简单的分析,从而更好的了解在默认参数下,三种不同人脸检测工具在不同检测场景下的的特点与区别


2 实践环境


北京四 ModelArts notebook

image.png


3 实践过程


3.1 数据准备


在本章课程的作业打卡文档中,描述了人脸检测的不同测试场景

image.png

  • 个人感觉场景2)有点奇怪,因为这个“较小”是多小???....这个...不清楚啊...所以我决定不将其放到我的数据集合里面。

  • 受场景5)的启发,我决定找5个脸类型(Ⅰ类)【孩童,青少年,成人,老人,动画】,每个类型都找4种状态(Ⅱ类)【一个正脸5张,一个侧脸5张,多个脸3张,个人感觉会比较难的脸(比如说环境贼黯淡之类的)2张】,总共5*(5+5+3+2)=75张照片

  • 考虑到在动画人脸中有很多很夸张的人脸,难度比较大。而我们检测的工具都比较简单,应该不能完成对于夸张人脸的检测。所以为了我们的测试结果有意义,我选用了脸不是那么夸张的、感觉比较正常的《火影忍者》中的人脸。(个人并非火粉||影粉||忍粉||者粉....只是感觉这种脸相对比较不那么夸张....可能可以检测出来...

  • 用作检测的图片是在免费网站pexels(感谢不万能的知乎让我找到了这个网站)中寻找的。

  • 不出乎意料,没有在pexels中找到《火影忍者》的人脸图片.......所以这一部分的图片是从知乎上找的....

  • 最近美国的黑人权益问题比较火爆,在看浏览新闻的我“灵光”乍现---人脸检测会因为肤色而导致表现地有差异吗?偏黑肤色的人脸会被我们的检测方法漏过吗?。而我发现在图库中黑人的照片只占小部分,所以我又单独增加了一个肤色偏黑的类型。(这里只是觉得可能肤色偏黑会对我们的检测方法造成影响,并无其它任何意思....勿过度解读qaq...


至此,经过一个小多小时的图片欣赏...我的数据集合准备完成,共6*15=90张图片。

image.png

每张图片由三个数字命名,第一个表示脸的类型,第二个表示脸的状态,第三个表示在该类型、该状态下脸的编号。这样便于后期对于结果的分析统计。

  • 类型(Ⅰ类)对应数字编号:1-孩童 2-青少年 3-成人 4-老人 5-动画 6-肤色偏黑的人

  • 状态(Ⅱ类)对应数字编号:1-包含一个正脸 2-包含一个侧脸 3-包含多张脸 4-个人认为可能比较难的(例如曝光过度,失焦等)

举个栗子:231.jpg 即青少年类型中包含多张脸的编号为1的照片 


注意:不能下载pexels的大图直接用,不然在运行dlib检测时就会出现这个报错:

image.png

个人理解可能是图片像素太大了,然后内存吃不消(我原本以为最大的效果最好啦,所以都下载的最大的....结果不行...适得其反....

所以我是将所有图片固定横纵比之后第一个像素值调成500,这样正好还可以规定一下大概尺寸...如果用的不是gpu体验规格,可能或许大概可以直接跑......


3.2 代码调整


我们只需要把本章的人脸区域及关键点检测案例(dlib)人脸年龄预测案例(MTCNN)OpenCV实践指导进行调整即可食用。


  • 首先我们只进行人脸检测的测试,因此将什么关键点检测部分啊、什么年龄预测啊什么的以及其它没用必要的部分可以去除。公平起见,这里我们只测试默认参数的三种方法(因为我害怕我调一调参数之后结果一个比一个糟.....默认的感觉还公平友好些....


import cv2

缺少了个

as cv

不知道是不是老师们专门挖了个坑....咱不知道咱也不敢问qaq...


  • 而为了方便我们的进一步处理,所以我们用pic.save()的方式将结果全部以图片文件的形式输出出来。


  • 我们可以将每张图片的检测到的数目都记录下来,这样可以避免我们人工在后面查看结果时漏掉比较小的标注框。

考虑到数据后续的处理,baidu之后,借助xlwt,我将检测到的数目都预先存在一个excel里(现学现卖,嘻嘻嘻...

首先初始化并制作表头

# 创建一个workbook 设置编码
workbook = xlwt.Workbook(encoding = 'utf-8')
# 创建一个worksheet
worksheet = workbook.add_sheet('GRP_res')

# 写入excel
# 参数对应 行, 列, 值
worksheet.write_merge(0, 1, 0, 0, '名')
worksheet.write_merge(0, 1, 1, 1, 'Ⅰ类')
worksheet.write_merge(0, 1, 2, 2, 'Ⅱ类')
worksheet.write_merge(0, 0, 3, 6, 'dlib')
worksheet.write(1,3, label = '识别数')
worksheet.write(1,4, label = '正确数')
worksheet.write(1,5, label = '漏检数')
worksheet.write(1,6, label = '错检数')
worksheet.write_merge(0, 0, 7, 10, 'MTCNN')
worksheet.write(1,7, label = '识别数')
worksheet.write(1,8, label = '正确数')
worksheet.write(1,9, label = '漏检数')
worksheet.write(1,10, label = '错检数')
worksheet.write_merge(0, 0, 11, 14, 'OpenCv')
worksheet.write(1,11, label = '识别数')
worksheet.write(1,12, label = '正确数')
worksheet.write(1,13, label = '漏检数')
worksheet.write(1,14, label = '错检数')
a=1
b=1
c=0
ps=1
while ((a!=7)or(b!=1)or(c!=0)):
    ps+=1
    c+=1
    worksheet.write(ps,0, label = a*100+b*10+c)
    worksheet.write(ps,1, label = a)
    worksheet.write(ps,2, label = b)
    if((b==1)or(b==2)):
        if(c==5):
            c=0
            b+=1
    elif(b==3):
        if(c==3):
            c=0
            b+=1
    elif(b==4):
        if(c==2):
            c=0
            b+=1
    if(b==5):
        b=1
        a+=1

之后在每个图片检测之后用worksheet.write()将检测到的数目写入,最后workbook.save()保存即可


  • 本章的三个案例都是针对张图片的,baidu之后,借助glob调整成遍历某文件夹下所有的jpg图片,在检测时我们只需要把路径改变一下即可(现学现卖,嘻嘻嘻...

for index, filename in enumerate(glob.glob('GRP/my_data/' + '*.jpg')):
    image_path = filename
    #接下来进行检测和输出
    #......
    #......
    #......


注意:在人脸年龄预测案例(MTCNN)中,如果直接这样用for把检测部分包起来:

image.png

那么这部分运行时间会贼长(2min)

image.png

思考一下下(其实我思考了贼久的qaq...)就能发现,因为每次都要运行mtcnn(),而mtcnn()拖慢了速度

我们把它放到for外面

image.png

时间短了好多好多好多...(16s)

image.png


人脸区域及关键点检测案例(dlib)中的

res_img = cv2.rectangle(image, (rects[0].left(), rects[0].top()), (rects[0].right(), rects[0].bottom()), 0, 1)

调整成

    for x in rects:
        res_img = cv2.rectangle(image, (x.left(), x.top()), (x.right(), x.bottom()), (0,255,0),2)

人脸年龄预测案例(MTCNN)中的

res_img = cv2.rectangle(img, (box[0],box[1]),(box[0]+box[2],box[1]+box[3]), 0, 1)

调整成

    for x in detected:
        box = x["box"]
        res_img = cv2.rectangle(img, (box[0],box[1]),(box[0]+box[2],box[1]+box[3]),(0,255,0),2)


注意:这个调整后在人脸年龄预测案例(MTCNN)中得到的结果是这样的:

image.png

???好奇怪.....142和215怎么重复了????142中1代表的应该是个孩童照片,而4代表是我觉得可能有点难的...但这个图明显很简单的吧..所以真相只有一个==142错了

我们再来看一下相关代码

image.png

稍微一看(其实我当时琢磨了一晚上..呜呜呜)就会发现,大概是detected是空的,然后就没有走for循环,那么res_img就是上一张detected不为空的图片...

所以我在for循环前面加了这样一行代码来避免这个问题

res_img = img

果然,

image.png

142的detected是空的,没有任何标注框

ok,问题解决...........等等,如果res_img就是142上一张detected不为空的图片,那不是应该是141的图片吗???????

稍微一看(其实我当时琢磨了一早上....呜呜呜呜呜)就不难做出猜测,遍历的时候不是按字典序遍历的?

image.png

果然不是按字典序...142之前就是615,验证了我的猜测....(作为一个python没怎么系统学过的人...wow,感觉发现了新大陆....qaq

okok,问题解决


  • 接下来我们还要实现计时的功能,baidu之后,借助datetime记录始末时间,相减即可(现学现卖,嘻嘻嘻...

s=datetime.datetime.now()
e=datetime.datetime.now()
dt=e-s

那么这里要考虑一下从哪里开始计时,又从哪里停止计时,因为感觉整个程序的时长不太准确。每种测试过程都经历了安装相关的库什么的到遍历图片,将图片转换检测绘制输出并且将检测到的数目记录在excel中。考虑只记录检测时间,那么应该就在每个循环里面检测那一步前后记录时间...可是图像输入之后每种检测方式对于图像的转换处理都有所不同,我认为这个应该也算在时间里,那么就在每个循环开始处到检测完成计时....而我望着书桌上放的大物书籍封面,又"灵光”一现===依稀(有可能是我想错了qaq...)想起了当年高中物理老师说过什么逐差....那这个datetime.datetime.now()应该就像读数一样有偶然误差吧...那我调用的次数越多那结果岂不是误差就越大.......这可..如何是好....然后忽然恍然大悟,对于这三个过程中像什么输出结果写入excel之类的过程时间都是一样的,而时间不一样的过程就是安装库什么的,图片转换和检测这三个过程,考虑到实际情况下需要的库这些准备工作应当是提前完成的。那么就在准备工作完成后计时,最后结束时计时,时间相减就行了。这个时间应该比准确的时间要长一些,但是三个方式长的时间都一样,所以我们依然可以通过这三个时间来定性比较,而定量分析感觉其实并不需要。(搞了半天原来是在...瞎想...又浪费了coutless脑细胞...呜呜呜...


3.3 运行测试


.......就......

运行~运行~运行~运行~运行~运行~运行~运行~运行~运行~

即可


3.4 测试结果处理


根据我的程序,三个结果会存在三个不同的文件夹中


  • 首先需要将三种方法的各自九十个作答进行“批改”,将每个作答的正确数和漏检数都记录下来。(在此感谢妈给我当廉(mian)价(fei)劳动力,帮我数数....


小惊喜:在进行“批改”的时候,发现MTCNN有贼惊喜的效果

比如这两张图:

image.pngimage.png

是不是分别有2张和8张脸啊~~~

MTCNN的结果如下:

image.pngimage.png

咦!

image.pngimage.png

wow!这么模糊、小的脸都检测出来了....好好好好厉害啊啊啊...(u1s1,我在看dlib检测结果的时候当然就没发现这两个人脸...


  • 然后就可以运用Microsoft强大的excel计算出我们所需要的数据...

我这里认为我们需要可靠度和检出率(其实这俩名字是我自己编的qaq...)就可以啦。可靠度为正确数占识别数的百分比,用它来反映这个方法检测出来的结果是否可靠,它对于一些不进行人工核实或者实时大量很重要;检出数为正确数占总脸数的百分比,我用它来反映这个方法检测的是否全面,用于对检测结果要求尽可能全面的情况。


3.5 结果分析

image.png

  • 首先,我们来看一下时间。

dlib比Opencv慢一丢丢(1s左右)...但是这是90张图片时,如果是90000张图片,那就是差1000/60≈17min。而MTCNN比dlib慢了两丢丢(2s左右...),那90000张图片就是相差34min左右。而90000张对最快的Opencv来说需3小时,因此这样来看,速度差异还是有一些些意义的...(17分钟可以少睡个小午觉,40分钟都可以少看集电视剧了...


  • 其次,我们来看一下检测质量情况。

对于孩童的脸(Ⅰ类1)、肤色较黑的人的脸(Ⅰ类6)、以及一张侧脸(Ⅱ类2)的检测,dlib是胜出的

对于青少年的脸(Ⅰ类2),成人的脸(Ⅰ类3)、动画人脸(Ⅰ类5)以及多张脸(Ⅱ类3)的检测,mtcnn胜出。

剩下的,老年人的脸(Ⅰ类4)dlib和Mmtcnn都挺好的吧...而一张正脸(Ⅱ类1)和我认为可能有难度的脸(Ⅱ类4)以及合计(总)来看的话,dlib是可靠度更胜一筹而mtcnn检出率更好,而且更有意思的是这两种方法之间可靠度差多少检出率就差多少(难道这就是天机...滑稽...)。


  • 综合来说,我们在实际应用中还是要看对时间和质量的需求,当时间允许的时候当然是选择质量最好的。从实践中看出对于孩童的脸(Ⅰ类1)、肤色较黑的人的脸(Ⅰ类6)、一张侧脸(Ⅱ类2)以及老年人的脸(Ⅰ类4)来说,dlib是时间、质量两个角度来看都是最好的选择;对于质量情况中mtcnn胜出的就需要看时间情限制了;而剩下的不仅要看时间限制,还要看我们需要检测得更加可靠还是更加全面。总的来说,dlib时间更短更加可靠,而mtcnn更加全面。


  • 呀,等一下,好像漏了一个===Opencv.....他这效果相当“优秀”,这检出率大部分相当低。

  1. 首先,尝试让它更好一丢丢。

调整一下参数

image.png

将放大的倍数调小一丢丢,看能不能提高检出率

结果,,,,并没有,检出率没有提高,检错率提高了.....

例如:

image.png

你说像不像小绿框躲人的场面qaq....

    2.再观察一下我们的代码

image.png

frontalface......这前缀真的是我们小学二年级就学到的front吧...这莫非就只是正脸的检测??

看一下那个目录下还有啥

image.png

emnn...没找到侧脸....baidu一下

image.png

wow~怪不得Opencv在一张侧脸(Ⅱ类2)部分检出率奇差无比....

那按照这个思维,要检测一张照片要镜面翻转遍历2种可能每次都检测正脸和侧脸(因为脸极有可能是左脸又有可能是倒着的...)然后把结果合起来???

但是对于这个半侧脸,

image.png

Opencv的正脸检测也检测到了,那翻转之后又检测到右侧脸的话,那岂不是重了,所以还要去重.....

怎么去重呢...具体的不会.....我感觉去重的话首先得判断哪些是重的,那其实也不好说是重复的还是检错的....这个感觉对我来说太难了....

正如我曾经的提问中专家回复的

image.png

Opencv这个方法应该大概可能好像确实不太优秀:(


4 总结


这次通过实践的方式做了个自己认为满合理的小数据集合,通过“抄袭”课程代码、“过度”使用搜索引擎来完成了实践的简单代码,对数据进行了简单的统计与整理,并对结果进行了简单的分析,从而更好的了解了在默认参数下,三种人脸检测方法的区别与特点。这次实践有很多局限性,比如数据的类型还是不太科学,数据可能在挑选的时候我会不自觉地倾向于某一个我并不清楚的特点,均使用默认参数或许可能并不能够发挥出三种方法的真正实力,再者我对于结果的分析也比较简单,所以可能这个实践的结果其实也没啥实际意义。不过,个人的收获还是蛮多的,了解了很多东西(也不知道俺能记住多少...),也完成了我的第一篇网络小作qaq(本来写的是拓展作业,后来变成了博客类型,然后变成了流水账类型,最后就成了如今的随意随笔类型.....),感觉还是蛮有成就感的。


5 附录 


5.1 附录一:致谢


再次感谢妈给我当廉(mian)价(fei)劳动力,帮我数数....

感谢所有在做这个作业的时候看过的网络资料(包括未在文中标注链接的...一开始没想着写参考资料qaq....所以列不太出来......)

感谢你竟然看到了这里,感谢你的宽容qaq

感谢我自己竟然水了这么长一篇,明天要请自己吃个冰淇淋才行啊....


5.2 附录二:实践数据下载指南


1)在modelarts notebook里下载代码

import os
from modelarts.session import Session
sess = Session()
bucket_path="grp-homework/hobeter_ex.ipynb"
sess.download_data(bucket_path=bucket_path, path="./hobeter_ex.ipynb")

    其中hobeter_ex.ipynb即为代码


2)在modelarts notebook里下载数据集合

import os
from modelarts.session import Session
sess = Session()
bucket_path="grp-homework/GRP.tar.gz"
sess.download_data(bucket_path=bucket_path, path="./GRP.tar.gz")
# 使用tar命令解压资源包
os.system("tar -xf ./GRP.tar.gz")
# 清理压缩包
os.system("rm ./GRP.tar.gz")

    在GRP目录中my_data目录里是数据,其他数据均为空,可用于存放检测结果


3)在modelarts notebook里下载我的实践结果

import os
from modelarts.session import Session
sess = Session()
bucket_path="grp-homework/GGRRPP.tar.gz"
sess.download_data(bucket_path=bucket_path, path="./GGRRPP.tar.gz")
# 使用tar命令解压资源包
os.system("tar -xf ./GGRRPP.tar.gz")
# 清理压缩包
os.system("rm ./GGRRPP.tar.gz")

    在GGRRPP目录中, 

        GRP目录下为2)中数据集合加上程序运行的输出(三种方式的检测结果图在各自的res目录下以及一张初始化的excel表GRP_res.xls

        hobeter_ex为代码

        GRP_res.xls为处理过的excel表


:这个桶我设置成了公共读,但是没有实践过其他用户是否能下载,so..........


4)github

https://github.com/hobeter/grp-homework

其中有1)2)两个内容....(3有亿丢丢大.....不太会传qaq....


6 完结撒花


撒花~撒花~撒花~撒花~撒花~撒花~撒花~撒花~撒花~撒花~



hobeter               

2020/7/3            

2020/7/4            



登录后可下载附件,请登录或者注册

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请发送邮件至:huaweicloud.bbs@huawei.com;如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
评论文章 //点赞 收藏 2
点赞
分享文章到微博
分享文章到朋友圈

下一篇:【2020华为云AI实战营】第七章nlp 小白探索之HanLP初体验

评论 (0)


登录后可评论,请 登录注册

评论