使⽤卷积神经⽹络(CNN)做⼈脸识别的⽰例代码
上回书说到了对⼈脸的检测,这回就开始正式进⼊⼈脸识别的阶段。
关于⼈脸识别,⽬前有很多经典的算法,当我⼤学时代,我的⽼师给我推荐的第⼀个算法是特征脸法,原理是先将图像灰度化,然后将图像每⾏⾸尾相接拉成⼀个列向量,接下来为了降低运算量要⽤PCA降维,最后进分类器分类,可以使⽤KNN、SVM、神经⽹络等等,甚⾄可以⽤最简单的欧⽒距离来度量每个列向量之间的相似度。OpenCV中也提供了相应的EigenFaceRecognizer库来实现该算法,除此之外还有FisherFaceRecognizer、LBPHFaceRecognizer以及最近⼏年兴起的卷积神经⽹络等。
卷积神经⽹络(CNN)的前级包含了卷积和池化操作,可以实现图⽚的特征提取和降维,最近⼏年由于计算机算⼒的提升,很多⼈都开始转向这个⽅向,所以我这次打算使⽤它来试试效果。
⽼规矩,先配置下编程的环境:
系统:windows / linux
解释器:python 3.6
依赖库:numpy、opencv-python 3、tensorflow、keras、scikit-learn
pip3 install numpy
pip3 install opencv-python
pip3 install keras
pip3 install scikit-learn
pip3 install tensorflow
如果⼿中有⼀块⽀持Cuda加速的GPU建议安装GPU版本:
pip3 install tensorflow-gpu
上次⽂章有位读者评论说:
所以,为了照顾初学者,这⾥简单介绍下Anaconda的安装⽅法,Anaconda是⼀个开源的Python发⾏版本,其包含了Conda、Python等180多个科学包及其依赖项。因为包含了⼤量的科学包,Anaconda 的下载⽂件⽐较⼤,所以有python包安装基础的⼈还是建议通过pip来安装所需的依赖。
这⾥根据⾃⼰的电脑系统来选择相应的系统选项,⾄于是64位还是32位要根据⾃⼰电脑的内存⼤⼩和系统位数来选择,python版本选择3.6。
下载完成安装,打开程序,切换左侧菜单到Environment,选择all,输⼊想要安装的模块并搜索,选中后点击右下⾓的Apply就开始安装了。
基本思路:
我的设计思路是这样的,先⽤上节讲到的⼈脸检测⽅法来检测出⼈脸位置,然后根据返回的坐标、尺⼨把脸⽤数组切⽚的⽅法截取下来,然后把截取的⼩图⽚送进训练好的卷积神经⽹络模型,得出⼈脸的分类结果,最后在原图⽚上打上包围框并且把结果写在包围框的上端:
原谅我拙劣的绘画技巧
当然了,实现这⼀步骤的前提就是要有⼀个训练好的可以做⼈脸识别的模型,所以本⽂的主要内容都会放在训练上⾯。
深度学习框架的选择:
卷积神经⽹络是深度学习在图像⽅⾯的应⽤,所以最⾼效的⽅法就是选择合适的深度学习框架来实现它,现在市⾯上有很多深度学习框架可供选择,⽐如基于 C++ 的 Caffe 、基于 Python 的TensorFlow、Pytorch、Theano、CNTK 以及前两天⼀个好友提到的她正在⽤来做推荐算法的 MXNET 。
这些都是搭建深度学习框架不错的选择,不过搭建的步骤会⽐较繁琐,会让很多初学者瞬间放弃,还好世界上出现了Keras,它可以使⽤TensorFlow、Theano、CNTK作为后端运算引擎,提供了⾼层的,更易于使⽤的函数,可以让不太了解深度学习原理的⼈也能快速上⼿,⽤通俗的话说就是:“ Keras 是为⼈类⽽不是天顶星⼈设计的API ”。
本⽂所使⽤后端运算引擎为TensorFlow,简称 TF (掏粪)。
⼈脸收集:
我的⽬的是希望在很多⼈中可以识别出⾃⼰的脸,所以对这个系统的要求是:
不能把别⼈识别成我
要能在我出现的时候识别出我
于是我需要⾃⼰的⼀些图照⽚,来教会神经⽹络,这个就是我,以及⼀堆其他⼈的照⽚来告诉它,这些不是我,或者说这些⼈分别是谁。
现在需要去采集⼀些其他⼈的图⽚,这些数据集可以⾃⼰⽤相机照、或者写个爬⾍脚本去⽹上爬,不过由于⼈脸识别早在⼏⼗年前就⼀直有前辈在研究,很多⼤学和研究机构都采集并公布了⼀些⼈脸数据集专门⽤作图像识别算法的研究和验证⽤,像耶鲁⼤学的Yale⼈脸库,剑桥⼤学的ORL⼈脸库以及美国国防部的FERET⼈脸库等,我在这⾥⽤了耶鲁⼤学的Yale⼈脸库,⾥⾯包含15个⼈,每⼈11张照⽚,主要包括光照条件的变化,表情的变化,接下来我会把⾃⼰的⼏张照⽚混进去,看看训练过后能不能被神经⽹络良好的识别。
头像提取:
提取⾃⼰照⽚使⽤的是上篇⽂章提到的⽅法:
获取⽂件夹下所有图⽚⽂件 -> 检测⼈脸位置 -> 根据⼈脸位置及尺⼨剪裁出⼈脸 -> 保存。
这是我的⽬录结构:
代码:
# _*_ coding:utf-8 _*_
import cv2
import os
CASE_PATH = "haarcascade_l"
RAW_IMAGE_DIR = 'me/'
DATASET_DIR = 'jm/'
face_cascade = cv2.CascadeClassifier(CASE_PATH)
def save_feces(img, name,x, y, width, height):
image = img[y:y+height, x:x+width]
cv2.imwrite(name, image)
image_list = os.listdir(RAW_IMAGE_DIR) #列出⽂件夹下所有的⽬录与⽂件
count = 166
for image_path in image_list:
image = cv2.imread(RAW_IMAGE_DIR + image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray,
scaleFactor=1.2,
minNeighbors=5,
minSize=(5, 5), )
for (x, y, width, height) in faces:
save_feces(image, '%ss%d.bmp' % (DATASET_DIR, count), x, y - 30, width, height+30)
count += 1
得到了还蛮不错的效果:
尺⼨变换:
现在有了所有的图⽚,可以开始训练了,不过Yale⼈脸库⾥⾯所有照⽚都是100*100的尺⼨,所以将要构建的卷积神经⽹络的输⼊就是100*100,⽽我新⽣成的图⽚样本形状都是不规则的,为了使它可以顺利进⼊卷积层,第⼀步就要对图⽚做尺⼨变换,当然不能暴⼒的resize成100*100,否则会引起图⽚的变形,所以这⾥采⽤了⼀种数字图像处理中常⽤的⼿段,就是将较短的⼀侧涂⿊,使它变成和⽬标图像相同的⽐例,然后再resize,这样既可以保留原图的⼈脸信息,⼜可以防⽌图像形变:
def resize_without_deformation(image, size = (100, 100)):
height, width, _ = image.shape
longest_edge = max(height, width)
top, bottom, left, right = 0, 0, 0, 0
if height < longest_edge:
height_diff = longest_edge - height
top = int(height_diff / 2)
bottom = height_diff - top
elif width < longest_edge:
width_diff = longest_edge - width
left = int(width_diff / 2)
right = width_diff - left
image_with_border = pyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = [0, 0, 0])
resized_image = size(image_with_border, size)
return resized_image
调⽤了该函数出现了下⾯的效果:
爬虫可以干什么下⾯是读取照⽚的函数,可以传⼊尺⼨,默认尺⼨是100*100,返回了两个列表,第⼀个列表中每⼀个元素都是⼀张图⽚,第⼆个列表中则对应存储了图⽚的标签,这⾥⽤1、2、3.......来指代,因为我根本不知道这些⼈的名字是什么:
def read_image(size = None):

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。