综述

爬坑一天,整出来一套还行的方案,特此分享爬坑心得~

因为整体代码结构和上篇手写数字的文章里代码结构比较相似,所以这里只贴出部分代码

网络结构

目前采用的两套模型是普通cnn以及vgg,效果不错,其他模型可能后续还会尝试。

CNN

# cnn
def convolutional_neural_network(image, type_size):# 第一个卷积--池化层conv_pool_1 = fluid.nets.simple_img_conv_pool(input=image,# 输入图像filter_size=3,# 滤波器的大小num_filters=32,# filter 的数量。它与输出的通道相同pool_size=2,# 池化层大小2*2pool_stride=2,# 池化层步长act='relu') # 激活类型# Dropout主要作用是减少过拟合,随机让某些权重不更新  # Dropout是一种正则化技术,通过在训练过程中阻止神经元节点间的联合适应性来减少过拟合。# 根据给定的丢弃概率dropout随机将一些神经元输出设置为0,其他的仍保持不变。drop = fluid.layers.dropout(x=conv_pool_1, dropout_prob=0.5)# 第二个卷积--池化层conv_pool_2 = fluid.nets.simple_img_conv_pool(input=drop,filter_size=3,num_filters=64,pool_size=2,pool_stride=2,act='relu')# 减少过拟合,随机让某些权重不更新                                                   drop = fluid.layers.dropout(x=conv_pool_2, dropout_prob=0.5)# 第三个卷积--池化层conv_pool_3 = fluid.nets.simple_img_conv_pool(input=drop,filter_size=3,num_filters=64,pool_size=2,pool_stride=2,act='relu')# 减少过拟合,随机让某些权重不更新                                                   drop = fluid.layers.dropout(x=conv_pool_3, dropout_prob=0.5)# 全连接层fc = fluid.layers.fc(input=drop, size=512, act='relu')# 减少过拟合,随机让某些权重不更新                                                   drop =  fluid.layers.dropout(x=fc, dropout_prob=0.5)                                                   # 输出层 以softmax为激活函数的全连接输出层,输出层的大小为图像类别type_size个数predict = fluid.layers.fc(input=drop,size=type_size,act='softmax')return predict

VGG

1.首先定义了一组卷积网络,即conv_block。卷积核大小为3x3,池化窗口大小为2x2,窗口滑动大小为2,groups决定每组VGG模块是几次连续的卷积操作,dropouts指定Dropout操作的概率。所使用的img_conv_group是在paddle.networks中预定义的模块,由若干组 Conv->BN->ReLu->Dropout 和 一组 Pooling 组成。

2.五组卷积操作,即 5个conv_block。 第一、二组采用两次连续的卷积操作。第三、四、五组采用三次连续的卷积操作。每组最后一个卷积后面Dropout概率为0,即不使用Dropout操作。

3.最后接两层512维的全连接。

4.通过上面VGG网络提取高层特征,然后经过全连接层映射到类别维度大小的向量,再通过Softmax归一化得到每个类别的概率,也可称作分类器。

# vgg
def vgg_bn_drop(image, type_size):  def conv_block(ipt, num_filter, groups, dropouts):return fluid.nets.img_conv_group(input=ipt, # 具有[N,C,H,W]格式的输入图像pool_size=2,pool_stride=2,conv_num_filter=[num_filter] * groups, # 过滤器个数conv_filter_size=3, # 过滤器大小conv_act='relu',conv_with_batchnorm=True, # 表示在 Conv2d Layer 之后是否使用 BatchNormconv_batchnorm_drop_rate=dropouts,# 表示 BatchNorm 之后的 Dropout Layer 的丢弃概率pool_type='max') # 最大池化conv1 = conv_block(image, 64, 2, [0.0, 0])conv2 = conv_block(conv1, 128, 2, [0.0, 0])conv3 = conv_block(conv2, 256, 3, [0.0, 0.0, 0])conv4 = conv_block(conv3, 512, 3, [0.0, 0.0, 0])conv5 = conv_block(conv4, 512, 3, [0.0, 0.0, 0])drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)fc1 = fluid.layers.fc(input=drop, size=512, act=None)bn = fluid.layers.batch_norm(input=fc1, act='relu')drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.0)fc2 = fluid.layers.fc(input=drop2, size=512, act=None)predict = fluid.layers.fc(input=fc2, size=type_size, act='softmax')return predict

数据集

本次实验数据集的基础是paddlepaddle人脸识别公开学习项目的数据集,在此基础上作者加入了作者本人大头自拍100余张,共组成四组图片集。由此训练集训练的模型训练大概可以到70-80%左右的准确率,更多并没有进行尝试。

不过作者直接用该数据集训练得到的结果更像是对整张照片进行分类,即人脸+背景,有点偏离了实验的主题——“人脸识别”,由此决定对数据集进行增强,即在原照片的基础上把人脸抠出来作为新的数据集。

实现这一目标的手法可以有很多,比如自己实现一个网络进行人脸检测,或者直接调用第三方接口直接获取请求结果。室友某段姓玩家就采用前者用了一个自己以前写的检测网络……

作者这里采用了百度AI平台的人脸检测开放接口:http://ai.baidu.com/tech/face/detect

没有用过的同学可以查阅一下官网教程自己试一下,这里贴出关键代码:

# 调用百度AI人脸检测API用于检测人脸box,方便裁剪以增强数据集host = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=【你的ak】&client_secret=【你的sk】'
request = urllib.request.Request(host)
request.add_header('Content-Type', 'application/json; charset=UTF-8')
response = urllib.request.urlopen(request)
content = response.read()
content = json.loads(bytes.decode(content).strip())
access_token = content['access_token']# 获取路径为img的人脸box
def get_face(img):request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect" #请求地址with open(img,"rb") as f:base64_data = base64.b64encode(f.read())params = {"image":str(base64_data,encoding='UTF8'),"image_type":"BASE64"}params = urllib.parse.urlencode(params).encode(encoding='UTF8')request_url = request_url + "?access_token=" + access_tokenrequest = urllib.request.Request(url=request_url, data=params)request.add_header('Content-Type', 'application/json')response = urllib.request.urlopen(request)content = response.read()content = json.loads(str(content,encoding='UTF8')) #解析请求结果face_location = content['result']['face_list'][0]['location']return(face_location)

这里封装了get_face以为指定路径的图片提供人脸box

后续调用时识别完不要忘记裁剪及保存

face_location = get_face(name_path)
# (left, upper, right, lower)
box = (face_location['left'],face_location['top'],face_location['left']+face_location['width'],face_location['top']+face_location['height'])
img = img.crop(box)
img.save(face_path) #保存裁剪完的人脸图片

为了制作数据集这里每10张图片取1张图片塞进测试集,其余塞进训练集

if class_sum % 10 == 0:   # 每10张图片取一个做测试数据test_sum += 1                                       #test_sum测试数据的数目with open(data_list_path + "test.list", 'a') as f:f.write(face_path + "\t%d" % class_label + "\n") #class_label 标签:0,1,2,3
else:trainer_sum += 1        #trainer_sum测试数据的数目with open(data_list_path + "trainer.list", 'a') as f:f.write(face_path + "\t%d" % class_label + "\n") #class_label 标签:0,1,2,3
class_sum += 1                                          #每类图片的数目
all_class_images += 1                                   #所有类图片的数目

最终人脸裁剪完的数据集部分效果如下:

结果

增强数据集后cnn的效果可以得到明显提升

不过vgg的效果并不尽如人意,同样的训练轮数下表现的远不如cnn理想,有待调参或使用其他增强数据集的手段

爬坑指南

其实还是有一些可能会浪费很多时间的坑,举几个例子:

将自己的照片做进数据集中再上传、解压、使用,整个过程中大家一定要注意路径(如果你并不想改原代码的一些路径的话)

苹果用户拍出来的照片格式为heic,即使用一些网盘之类的工具传输到win本后格式变成了jpg,实际上也是打不开的,编码格式根本不是jpg,所以也就导致代码会抛出异常,一些函数并不能处理这种图片。建议使用微信传输一下,再右键保存,微信传图可以自动把heic转换为正确的jpg。

此外百度AI开放平台有些教程描述的其实是不太清晰的,这里贴出了请求的代码可以帮助大家少走弯路,中间涉及json封装、base64转换、response里正确关键字的提取等官方文档并没有做详细说明的坑点。

以及数据集里有一张图片是gif,强烈建议大家用函数转换为其他格式图片或者直接忽略掉这张,因为代码里的paddle.dataset.image.simple_transform函数并不支持对gif格式的动图进行处理。这个巨坑浪费了我四个小时debug!!!(不过我现在并不太想的明白为什么修改数据集前不会导致这个问题)

其他并没有什么特别的地方,基本上大家完成解压后都可以直接把fork的项目顺利的跑起来。这里基本是完成一些工作后简单写的一篇博客,如果有精力的话还可以有大量工作可以做,比如尝试更多的模型、调参以及对数据集进一步增强等~

paddlepaddle 人脸识别爬坑指南相关推荐

  1. JWT 入坑爬坑指南

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | 公众号「程序新世界」 越来越多的开发者开始学习 ...

  2. 从《编程之美》买票找零问题说起,娓娓道来卡特兰数——兼爬坑指南

    转自:从<编程之美>买票找零问题说起,娓娓道来卡特兰数--兼爬坑指南 引子: 大约两个月前,我在练习一些招聘的笔试题中,有一道和卡特兰数相关.那时还没来得及开始仔细看<编程之美> ...

  3. 蓝牙BLE(BlueTooth BLE)入门及爬坑指南

    前言 最近比较忙,两三周没有更新简书了,公司正好在做蓝牙BLE的项目,本来觉得挺简单的东西从网上找了个框架,就咔咔地开始搞,搞完以后才发现里面还有不少坑呢,故而写一篇蓝牙BLE入门及爬坑指南,旨在帮助 ...

  4. Insightface项目爬坑指南+使用本地数据集训练流程(MXNET版)

    其实半年多前就已经把insightface训练等一系列环节弄熟了,不得不说IBUG组的这个模型确实是开源界的翘楚,但是还是存在一些问题在某些程度上和商汤云从等大厂存在一点差距,这不妨碍大部分人日常人脸 ...

  5. 微信公众号JS-SDK多图上传爬坑指南

    一.wx.chooseImage爬坑 出现的问题: 安卓将chooseImage 方法返回的 localId 放在img标签的src属性下能够显示图片 IOS将chooseImage 方法返回的 lo ...

  6. iOS-通俗易懂的微信支付接入和爬坑指南,十分钟轻松搞完

     现在基本所有的App都会接入支付宝支付以及微信支付,也有很多第三方提供给你 SDK帮你接入,但是这种涉及到支付的东西还是自己服务器搞来的好一些,其实搞懂了 逻辑非常的简单,下面直接给大家说说下基本流 ...

  7. pb 调用虹软_记C# 调用虹软人脸识别 那些坑

    上一个东家是从事安防行业的,致力于人工智能领域,有自主人脸识别.步态识别的算法.C++同事比较称职有什么问题都可以第一时间反馈,并得到合理的处理,封装的DLL 是基于更高性能的GPU算法,可支持更多线 ...

  8. android 人脸识别踩坑实录

    随着AI技术的发展,人脸识别的应用场景越来越多,提供技术支持的API也有好多可以选择,但是大部分都是需要收费的,或者免费试用.由此可见人脸识别算法确实是核心技术,不是随便就可以获取到的.经过多次尝试, ...

  9. 记C# 调用虹软人脸识别 那些坑

    原文地址:https://www.cnblogs.com/Sientuo/p/11762245.html 正常使用肯定时作为类库调用,在项目中新建一类库,将Demo中需要用到的类文件拷贝,再将初始化引 ...

最新文章

  1. 旷视5号员工陈可卿:1991生于绍兴、10岁买电脑改变命运,信息奥赛金牌保送清华...
  2. Ubuntu 16.04 下安装VMware Tools(三行命令搞定,亲测好使)
  3. H2Database 转义符
  4. Angular自学笔记(?)属性型指令
  5. 大数据从哪里来?| 技术头条
  6. 如何利用ThoughtWorks.QRCode 生成二维码
  7. Fatal error: Uncaught Error: Call to undefined function gzinflate()
  8. PMP更新教材了,怎么备考?
  9. Putty工具使用教程
  10. java程序cpu突然飚高_fullGC 频繁导致CPU飙高
  11. 【HDL系列】Brent-Kung树形加法器原理与设计
  12. Rk 平台显示屏调试
  13. MotionEvent和TouchSlop
  14. 能领取拼多多优惠券的微信小程序
  15. 男人29岁发奋能成功吗
  16. 凸优化第一【凸集与凸优化简介】
  17. 乔布斯在困境中的关键一战
  18. Go 调用系统默认浏览器打开链接
  19. C1任务-10:域名解析
  20. timewait php,timewait是什么意思

热门文章

  1. Springcloudalibaba整合es!实现相关性排序,集成完代码真香
  2. 键盘各个键所对应的键值
  3. Unity中的UI相关组件
  4. 生命的枯榮竟是如此慘厲
  5. 心理测评软件的心理测试法的优缺点,心理测试的优缺点
  6. CSS表格与浮动定位
  7. 2020最难求职年,程序员职场面试 “防坑指南” ,全员必备!
  8. Vue3笔记_02setup与常用的Composition API(组合式API)
  9. Java实现 LeetCode 623 在二叉树中增加一行(遍历树)
  10. runtime error python怎么解决_RuntimeError: Python is not installed as a framework 错误解决方案...