计算机视觉作为人工智能领域一个最火的应用点,最近几年被媒体宣传的沸沸扬扬,像商汤、旷视、海康威视等等基于计算机视觉技术的公司都是各种投资者的宠儿。上个月旷视科技获得了微软举办的COCO Challenge 2017的冠军更是让“计算机视觉”重新成为了媒体报道的热点。
人脸识别作为计算机视觉中的一个已经很成熟的应用点,在很多行业外的人眼中往往披了一层神秘的面纱。那么“人脸识别”真的很困难吗?其实未必,以一种稍微抽象点的方式理解的话,“人脸识别”就如同小品里说的将大象装进冰箱一样简单:1)将冰箱打开;2)把大象装进去;3)把冰箱门关上
同样的,“人脸识别”也能分三步实现
1)将图片中的人脸找出来;2)对找出来的人脸进行特征转换(可以简单理解为转换成计算机能更好理解的格式);3)对转换后的特征进行识别,看看是谁的脸。这其中每一步都能使用不同的机器学习算法来进行处理
下边我将针对开源人脸识别框架 openface 中的源码进行解析帮助大家更好的理解人脸识别背后的分析逻辑到底是什么。openface的安装过程请参照Mac上开源人脸识别软件OPENFACE安装全流程教程
OpenFace开源框架提供了许多的 demo 脚本,这能帮助我们更好的理解如何使用这个框架。下边是调用demo脚本进行一个人脸识别的具体过程:
mkdir -p classify-test/raw/{lennon,clapton}
cp images/examples/lennon-* classify-test/raw/lennon
cp images/examples/clapton-* classify-test/raw/clapton
./util/align-dlib.py classify-test/raw align outerEyesAndNose classify-test/aligned --size96
./batch-represent/main.lua -outDir classify-test/features -data classify-test/aligned
./demos/classifier.py train classify-test/features
./demos/classifier.py infer ./classify-test/features/classifier.pkl images/examples/{carell,adams,lennon}*
下边我将通过分别解析上边的openface使用语句,帮助大家理解openface是如何“将大象装进冰箱里”的:
0)准备训练样本
mkdir -p classify-test/raw/{lennon,clapton}
cp images/examples/lennon-* classify-test/raw/lennon
cp images/examples/clapton-* classify-test/raw/clapton
这里作者在 classify-test/raw 文件目录下放置好训练数据,将要进行训练的数据按照类别在 raw 下分别创建子目录。这里我创建了 Lennon 和 clapton 两个类别,然后将这两个人的照片分别放进子文件夹中
1)利用dlib开源包,对图片中的人脸进行识别
./util/align-dlib.py classify-test/raw align outerEyesAndNose classify-test/aligned --size96
这里 align-dliv.py 从 classify-test/raw 原始图片文件夹中对里边的每个图片进行识别,然后将识别出来的人脸放入 classify-test/aligned 文件夹中。这里 align-dlib.py 很智能,对 raw 文件夹下的所有子文件夹都会对应的在 aligned 下进行创建
2)对识别出来的人脸进行抽象
./batch-represent/main.lua -outDir classify-test/features -data classify-test/aligned
这里 main.lua 对 aligned 文件夹下的人脸进行特征转化,形成两个文件 reps.csv 和 labels.csv。reps.csv 中的每一行代表 aligned 文件夹下的一张图片的特征值,而 labels.csv 中的每一行对应的是每一张图片的类别标签(这个案例只有 lennon 和 clapton 两类,各位可以根据自己需要放置数据)
3)对抽象出的特征进行分类
第一步,用 2)中提取的特征值和标签对模型进行训练,并将训练好的模型存在 classify-test/features 文件夹下,一般存为 classifier.pkl。值得注意的是这里特征提取使用的是一个已经训练好了的神经网络模型,其置于 models/openface/nn4.small2.v1.t7
./demos/classifier.py train classify-test/features
第二步,用训练好的分类模型 classifier.pkl 对新的图片进行分类
./demos/classifier.py infer ./classify-test/features/classifier.pkl images/examples/{carell,adams,lennon}*
理解了人脸识别的套路,那么如何一站式的实现人脸识别呢?比如利用摄像头对人脸进行捕捉,然后动态的进行人脸识别。这样的话,我们就能将它应用在门禁系统、安检系统中了。
不用担心,openface 的 demo/classifier_webcam.py 就是这个场景的一个简单实践,让我们过一遍
首先,将人脸识别所需要的模型准备好:
align = openface.AlignDlib(args.dlibFacePredictor) # 人脸检测模型 dlib
net = openface.TorchNeuralNet( # 特征抽象模型 神经网络
args.networkModel,
imgDim=args.imgDim,
cuda=args.cuda)
其次,调用 opencv 的视频流接口来使用摄像头摄取的图形进行实时监测
# Capture device. Usually 0 will be webcam and 1 will be usb cam.
video_capture = cv2.VideoCapture(args.captureDevice)
video_capture.set(3, args.width) # 设定视频窗口的长和宽
video_capture.set(4, args.height)
confidenceList = []
whileTrue: # 不断循环读取视频流中的图像
ret, frame = video_capture.read() # 循环读取图片
……
然后,对每张读取到的图像进行人脸识别:
persons, confidences = infer(frame, args)
这里程序调用了函数 infer,将读取到的图像 frame 和程序设定的参数 args(主要是分类模型的位置)作为参数输入函数中,返回分类预测结果和结果的置信度
接着,让我们进入 infer 函数中,看看其到底做了什么吧
[1] 将分类标签和分类器读入内存
with open(args.classifierModel,'r') as f:
(le, clf) = pickle.load(f)# le - label and clf - classifer
[2] 进行图像预处理
—> 将输入图像进行颜色转换
rgbImg = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
—> 调用之前准备好的 dlib 模型 align 将图像进行对图像中的人脸进行识别,并截取出来
bb = align.getAllFaceBoundingBoxes(rgbImg)
alignedFaces = []
for box in bb:
alignedFaces.append(
align.align(
args.imgDim,
rgbImg,
box,
landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE))
—> 对识别出来的人脸,使用之前准备好的神经网络模型 net 进行特征转换
reps = []
for alignedFace in alignedFaces:
reps.append(net.forward(alignedFace))
[3] 对处理好的图像特征值进行分类预测
for rep in reps:
try:
rep = rep.reshape(1, -1) # 对特征值的形式进行转换,将其转换成一行
except: # 当 rep 为空时,跳出
print("No Face detected")
return(None,None)
predictions = clf.predict_proba(rep).ravel() # 对 rep 进行预测
maxI = np.argmax(predictions) # 找出预测概率最大的那个结果的下标
# max index
persons.append(le.inverse_transform(maxI)) # 找到这个最大预测值所对应的人名
#(类别),并放入 persons 数组中
confidences.append(predictions[maxI]) # 将最大预测概率的值放入
# confidences 数组中
最后我们来总结一下,人脸识别的逻辑十分简单,即将人脸从图片中识别出来,抽象转换为计算机更容易理解的结构,并通过分类算法对训练数据进行训练,然后用训练好的模型进行分类。
由于人脸识别的应用已经很多年了,第一步中的人脸提取算法十分成熟,我们甚至都不需要知道其中的具体细节,只要懂得如何调用 dlib 工具对人脸进行提取即可,而要在人脸识别上获得很好的效果,除了需要足够的训练数据之外,就在于第二步和第三步模型算法的选择和调优上了。但这不是这篇的重点,我们下次再说