啰唆几句
最近在研究人脸探测,人脸验证,人脸识别。在理论知识补充后就是要自己动手写code了。在写code之前基于不做“重复工作”的懒人思想在网上搜索了下现有的人脸识别开源项目,在对比过几种方法后发现了face_recognition这个项目,该项目使用dlib作为人脸探测,而在face_recognition中也提供了两种探测方式:HOG和CNN。探测到人脸后提取128维面部特征,这128维的数据作为一个unknown的嵌入(embedding)和已知(标记)的嵌入进行相似度比较,在接受的阈值范围内认定是同一个人,虽然其页面上没有详细说明是怎样判定距离的,从其程序运行反馈的一些结果上我猜测是使用了Siamese network。face_recognition虽然使用十分简单,但还是有一些概念需要提一下:
- HOG
刚才已经提到HOG是face_recognition使用的一种面部探测的方式,HOG是Histogram of Oriented Gradients的简称也就是方向梯度直方图。 - CNN
基于卷积神经网络的探测脸的方式原则上会比HOG的准确度高,其原理我会记录在后续的理论文章中,大致理解就是使用一个bounding box去扫描整张图片并查看每一个bounding box中是否有目标对象 - 其他
除了上述两种人脸探测的方式还有不少其他的方式比如opencv中所采用的Haar Cascades,其实用了adaboost的方法来分类(熟悉机器学习的朋友会心一笑,懂了。。。),但其效果理论上是比不上CNN的。当然也有更精确的人脸探测方式Multi-task CNN,在git上也有其python的实现facenet。
实现步骤
啰嗦了这么多我们来看下怎么快速的实现一个人脸识别
- dlib
dlib是关键,ubuntu和win上的安装很简单,先说ubuntu吧- ubuntu
apt-get install -y --fix-missing
build-essential
cmake
gfortran
git
wget
curl
graphicsmagick
libgraphicsmagick1-dev
libatlas-dev
libavcodec-dev
libavformat-dev
libgtk2.0-dev
libjpeg-dev
liblapack-dev
libswscale-dev
pkg-config
python3-dev
python3-numpy
software-properties-common
zip
&& apt-get clean
这样dlib所需的Cmake和boost就安装好了
mkdir -p dlib
git clone -b 'v19.9' --single-branch https://github.com/davisking/dlib.git dlib/
cd dlib
python setup.py install --yes USE_AVX_INSTRUCTIONS
以上就在ubuntu的环境中安装好了dlib,可以进入python 然后import dlib尝试下。
- win
mkdir CMAKE
cd CMAKE
cmake -G "Visual Studio 14 2015 Win64" -T host=x64 ..
cmake --build . --config Release
然后下载dlib,进入其folder
python setup.py install
在dlib安装好以后安装face_recognition
pip install face_recognition
开始人脸识别
import face_recognition
from PIL import Image, ImageDraw
#已知(标记)人脸照片读取
1_image = face_recognition.load_image_file("1.jpg")
1_face_encoding = face_recognition.face_encodings(1_image)[0]
2_image = face_recognition.load_image_file("2.jpg")
2_face_encoding = face_recognition.face_encodings(2_image)[0]
#embedding
known_face_encodings = [
1_face_encoding,
2_face_encoding
]
known_face_names = [
"张三",
"李四"
]
#输入未标记的照片
unknown_image = face_recognition.load_image_file("unknown.jpg")
unknown_face_locations = face_recognition.face_locations(unknown_image)
# unknown_face_locations = face_recognition.face_locations(unknown_image,number_of_times_to_upsample=0, model="cnn")如果电脑有N卡并安装了cuda,使用cnn
unknown_face_encodings = face_recognition.face_encodings(unknown_image, unknown_face_locations)
pil_image = Image.fromarray(unknown_image)
draw = ImageDraw.Draw(pil_image)
# 探测人脸并和已知人脸比对
for (top, right, bottom, left), unknown_face_encoding in zip(unknown_face_locations, unknown_face_encodings):
matches = face_recognition.compare_faces(known_face_encodings, unknown_face_encoding,tolerance=0.4)
# distance = face_recognition.face_distance(known_face_encodings, unknown_face_encoding)
print(matches)
name = "Unknown"
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
#if 之后代码部分能优化成选取distance小于tolerance中的最小的一个值
#draw bounding box并标记
draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255))
text_width, text_height = draw.textsize(name)
draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255))
draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255))
del draw
pil_image.show()
上述就实现了一个人脸识别,由于手头素材涉及同事照片就不把识别结果分享出来了,我个人实现的实际效果还不错。
参考
- dlib
- face_recognition
- Adam Geitgey