前言
在前面的博客中介绍了,如何使用dlib标定人脸(python dlib学习(一):人脸检测),提取68个特征点(python dlib学习(二):人脸特征点标定)。这次要在这两个工作的基础之上,将人脸的信息提取成一个128维的向量空间。在这个向量空间上,同一个人脸的更接近,不同人脸的距离更远。度量采用欧式距离,欧氏距离计算不算复杂。
二维情况下:
distance=(x1−x2)2+(y1−y2)2−−−−−−−−−−−−−−−−−−√
distance=(x1−x2)2+(y1−y2)2

三维情况下:
distance=(x1−x2)2+(y1−y2)2+(z1−z2)2−−−−−−−−−−−−−−−−−−−−−−−−−−−−√
distance=(x1−x2)2+(y1−y2)2+(z1−z2)2

将其扩展到128维的情况下即可。
通常使用的判别阈值是0.6,即如果两个人脸的向量空间的欧式距离超过了0.6,即认定不是同一个人;如果欧氏距离小于0.6,则认为是同一个人。这个距离也可以由自己定,只要效果能更好。
实验中使用了两个模型:

shape_predictor_68_face_landmarks.dat:
http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2

dlib_face_recognition_resnet_model_v1.dat:
http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2

文件夹目录:

两个模型放在model文件夹中,测试图片放在faces中,图片自己随便下几张就行。

完整工程下载链接:
http://pan.baidu.com/s/1boCDZ7T

程序1
不说废话了,直接上代码。

# -*- coding: utf-8 -*-
import sys
import dlib
import cv2
import os
import glob

current_path = os.getcwd() # 获取当前路径
# 模型路径
predictor_path = current_path + "\\model\\shape_predictor_68_face_landmarks.dat"
face_rec_model_path = current_path + "\\model\\dlib_face_recognition_resnet_model_v1.dat"
#测试图片路径
faces_folder_path = current_path + "\\faces\\"

# 读入模型
detector = dlib.get_frontal_face_detector()
shape_predictor = dlib.shape_predictor(predictor_path)
face_rec_model = dlib.face_recognition_model_v1(face_rec_model_path)

for img_path in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
print("Processing file: {}".format(img_path))
# opencv 读取图片,并显示
img = cv2.imread(img_path, cv2.IMREAD_COLOR)
# opencv的bgr格式图片转换成rgb格式
b, g, r = cv2.split(img)
img2 = cv2.merge([r, g, b])

dets = detector(img, 1) # 人脸标定
print("Number of faces detected: {}".format(len(dets)))

for index, face in enumerate(dets):
print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom()))

shape = shape_predictor(img2, face) # 提取68个特征点
for i, pt in enumerate(shape.parts()):
#print('Part {}: {}'.format(i, pt))
pt_pos = (pt.x, pt.y)
cv2.circle(img, pt_pos, 2, (255, 0, 0), 1)
#print(type(pt))
#print("Part 0: {}, Part 1: {} ...".format(shape.part(0), shape.part(1)))
cv2.namedWindow(img_path+str(index), cv2.WINDOW_AUTOSIZE)
cv2.imshow(img_path+str(index), img)

face_descriptor = face_rec_model.compute_face_descriptor(img2, shape) # 计算人脸的128维的向量
print(face_descriptor)

k = cv2.waitKey(0)
cv2.destroyAllWindows()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
程序1结果

部分打印结果:

F:\Python\my_dlib_codes\face_recognition>python my_face_recogniton.py
Processing file: F:\Python\my_dlib_codes\face_recognition\faces\jobs.jpg
Number of faces detected: 1
face 0; left 184; top 64; right 339; bottom 219
-0.179784
0.15487
0.10509
-0.0973604
-0.19153
0.000418252
-0.0357536
-0.0206766
0.129741
-0.0628359
....
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
后面的那一堆数字就是人脸在128维向量空间上的值。

程序2
前面只是测试了一下,把要用的值给求到了。这里我封装了一下,把比对功能实现了。没加多少东西,所以不做赘述了。

# -*- coding: utf-8 -*-
import sys
import dlib
import cv2
import os
import glob
import numpy as np

def comparePersonData(data1, data2):
diff = 0
# for v1, v2 in data1, data2:
# diff += (v1 - v2)**2
for i in xrange(len(data1)):
diff += (data1[i] - data2[i])**2
diff = np.sqrt(diff)
print diff
if(diff < 0.6):
print "It's the same person"
else:
print "It's not the same person"

def savePersonData(face_rec_class, face_descriptor):
if face_rec_class.name == None or face_descriptor == None:
return
filePath = face_rec_class.dataPath + face_rec_class.name + '.npy'
vectors = np.array([])
for i, num in enumerate(face_descriptor):
vectors = np.append(vectors, num)
# print(num)
print('Saving files to :'+filePath)
np.save(filePath, vectors)
return vectors

def loadPersonData(face_rec_class, personName):
if personName == None:
return
filePath = face_rec_class.dataPath + personName + '.npy'
vectors = np.load(filePath)
print(vectors)
return vectors

class face_recognition(object):
def __init__(self):
self.current_path = os.getcwd() # 获取当前路径
self.predictor_path = self.current_path + "\\model\\shape_predictor_68_face_landmarks.dat"
self.face_rec_model_path = self.current_path + "\\model\\dlib_face_recognition_resnet_model_v1.dat"
self.faces_folder_path = self.current_path + "\\faces\\"
self.dataPath = self.current_path + "\\data\\"
self.detector = dlib.get_frontal_face_detector()
self.shape_predictor = dlib.shape_predictor(self.predictor_path)
self.face_rec_model = dlib.face_recognition_model_v1(self.face_rec_model_path)

self.name = None
self.img_bgr = None
self.img_rgb = None
self.detector = dlib.get_frontal_face_detector()
self.shape_predictor = dlib.shape_predictor(self.predictor_path)
self.face_rec_model = dlib.face_recognition_model_v1(self.face_rec_model_path)

def inputPerson(self, name='people', img_path=None):
if img_path == None:
print('No file!\n')
return

# img_name += self.faces_folder_path + img_name
self.name = name
self.img_bgr = cv2.imread(self.current_path+img_path)
# opencv的bgr格式图片转换成rgb格式
b, g, r = cv2.split(self.img_bgr)
self.img_rgb = cv2.merge([r, g, b])

def create128DVectorSpace(self):
dets = self.detector(self.img_rgb, 1)
print("Number of faces detected: {}".format(len(dets)))
for index, face in enumerate(dets):
print('face {}; left {}; top {}; right {}; bottom {}'.format(index, face.left(), face.top(), face.right(), face.bottom()))

shape = self.shape_predictor(self.img_rgb, face)
face_descriptor = self.face_rec_model.compute_face_descriptor(self.img_rgb, shape)
# print(face_descriptor)
# for i, num in enumerate(face_descriptor):
# print(num)
# print(type(num))

return face_descriptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
程序2结果
测试代码1:

import face_rec as fc
face_rec = fc.face_recognition() # 创建对象
face_rec.inputPerson(name='jobs', img_path='\\faces\\jobs.jpg') # name中写第一个人名字,img_name为图片名字,注意要放在faces文件夹中
vector = face_rec.create128DVectorSpace() # 提取128维向量,是dlib.vector类的对象
person_data1 = fc.savePersonData(face_rec, vector ) # 将提取出的数据保存到data文件夹,为便于操作返回numpy数组,内容还是一样的

# 导入第二张图片,并提取特征向量
face_rec.inputPerson(name='jobs2', img_path='\\faces\\jobs2.jpg')
vector = face_rec.create128DVectorSpace() # 提取128维向量,是dlib.vector类的对象
person_data2 = fc.savePersonData(face_rec, vector )

# 计算欧式距离,判断是否是同一个人
fc.comparePersonData(person_data1, person_data2)
1
2
3
4
5
6
7
8
9
10
11
12
13
如果data文件夹中已经有了模型文件,可以直接导入:

import face_rec as fc
face_rec = fc.face_recognition() # 创建对象
person_data1 = fc.loadPersonData(face_rec , 'jobs') # 创建一个类保存相关信息,后面还要跟上人名,程序会在data文件中查找对应npy文件,比如这里就是'jobs.npy'
person_data2 = fc.loadPersonData(face_rec , 'jobs2') # 导入第二张图片
fc.comparePersonData(person_data1, person_data2) # 计算欧式距离,判断是否是同一个人
1
2
3
4
5
程序2结果
Python 2.7.10 |Anaconda 2.3.0 (64-bit)| (default, May 28 2015, 16:44:52) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://binstar.org
>>> import face_rec as fc
>>> face_rec = fc.face_recognition()
>>> face_rec.inputPerson(name='jobs', img_path='\\faces\\jobs.jpg')
>>> vector = face_rec.create128DVectorSpace()
Number of faces detected: 1
face 0; left 184; top 64; right 339; bottom 219
>>> person_data1 = fc.savePersonData(face_rec, vector )
Saving files to :F:\Python\my_dlib_codes\face_recognition\data\jobs.npy
>>> face_rec.inputPerson(name='jobs2', img_path='\\faces\\jobs2.jpg')
>>> vector = face_rec.create128DVectorSpace()
Number of faces detected: 1
face 0; left 124; top 39; right 253; bottom 168
>>> person_data2 = fc.savePersonData(face_rec, vector )
Saving files to :F:\Python\my_dlib_codes\face_recognition\data\jobs2.npy
>>> fc.comparePersonData(person_data1, person_data2)
0.490491048429
It's the same person
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
官方例程
#!/usr/bin/python
# The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
#
# This example shows how to use dlib's face recognition tool. This tool maps
# an image of a human face to a 128 dimensional vector space where images of
# the same person are near to each other and images from different people are
# far apart. Therefore, you can perform face recognition by mapping faces to
# the 128D space and then checking if their Euclidean distance is small
# enough.
#
# When using a distance threshold of 0.6, the dlib model obtains an accuracy
# of 99.38% on the standard LFW face recognition benchmark, which is
# comparable to other state-of-the-art methods for face recognition as of
# February 2017. This accuracy means that, when presented with a pair of face
# images, the tool will correctly identify if the pair belongs to the same
# person or is from different people 99.38% of the time.
#
# Finally, for an in-depth discussion of how dlib's tool works you should
# refer to the C++ example program dnn_face_recognition_ex.cpp and the
# attendant documentation referenced therein.
#
#
#
#
# COMPILING/INSTALLING THE DLIB PYTHON INTERFACE
# You can install dlib using the command:
# pip install dlib
#
# Alternatively, if you want to compile dlib yourself then go into the dlib
# root folder and run:
# python setup.py install
# or
# python setup.py install --yes USE_AVX_INSTRUCTIONS
# if you have a CPU that supports AVX instructions, since this makes some
# things run faster. This code will also use CUDA if you have CUDA and cuDNN
# installed.
#
# Compiling dlib should work on any operating system so long as you have
# CMake and boost-python installed. On Ubuntu, this can be done easily by
# running the command:
# sudo apt-get install libboost-python-dev cmake
#
# Also note that this example requires scikit-image which can be installed
# via the command:
# pip install scikit-image
# Or downloaded from http://scikit-image.org/download.html.

import sys
import os
import dlib
import glob
from skimage import io

if len(sys.argv) != 4:
print(
"Call this program like this:\n"
" ./face_recognition.py shape_predictor_68_face_landmarks.dat dlib_face_recognition_resnet_model_v1.dat ../examples/faces\n"
"You can download a trained facial shape predictor and recognition model from:\n"
" http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2\n"
" http://dlib.net/files/dlib_face_recognition_resnet_model_v1.dat.bz2")
exit()

predictor_path = sys.argv[1]
face_rec_model_path = sys.argv[2]
faces_folder_path = sys.argv[3]

# Load all the models we need: a detector to find the faces, a shape predictor
# to find face landmarks so we can precisely localize the face, and finally the
# face recognition model.
detector = dlib.get_frontal_face_detector()
sp = dlib.shape_predictor(predictor_path)
facerec = dlib.face_recognition_model_v1(face_rec_model_path)

win = dlib.image_window()

# Now process all the images
for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")):
print("Processing file: {}".format(f))
img = io.imread(f)

win.clear_overlay()
win.set_image(img)

# Ask the detector to find the bounding boxes of each face. The 1 in the
# second argument indicates that we should upsample the image 1 time. This
# will make everything bigger and allow us to detect more faces.
dets = detector(img, 1)
print("Number of faces detected: {}".format(len(dets)))

# Now process each face we found.
for k, d in enumerate(dets):
print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(
k, d.left(), d.top(), d.right(), d.bottom()))
# Get the landmarks/parts for the face in box d.
shape = sp(img, d)
# Draw the face landmarks on the screen so we can see what face is currently being processed.
win.clear_overlay()
win.add_overlay(d)
win.add_overlay(shape)

# Compute the 128D vector that describes the face in img identified by
# shape. In general, if two face descriptor vectors have a Euclidean
# distance between them less than 0.6 then they are from the same
# person, otherwise they are from different people. Here we just print
# the vector to the screen.
face_descriptor = facerec.compute_face_descriptor(img, shape)
print(face_descriptor)
# It should also be noted that you can also call this function like this:
# face_descriptor = facerec.compute_face_descriptor(img, shape, 100)
# The version of the call without the 100 gets 99.13% accuracy on LFW
# while the version with 100 gets 99.38%. However, the 100 makes the
# call 100x slower to execute, so choose whatever version you like. To
# explain a little, the 3rd argument tells the code how many times to
# jitter/resample the image. When you set it to 100 it executes the
# face descriptor extraction 100 times on slightly modified versions of
# the face and returns the average result. You could also pick a more
# middle value, such as 10, which is only 10x slower but still gets an
# LFW accuracy of 99.3%.

dlib.hit_enter_to_continue()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
吐槽:
dlib的确很方便,不用花多少时间就能自己做到一些目标功能。官方文档讲的很详细,很容易入门。看这个文档(dlib python api)差不多就能学会用了。导师已经安排了研究生阶段的学习任务了,后面也要忙起来了。dlib的学习虽然是我10月份才开的坑,为了善始善终我也要尽快整理完这些东西。以后要回到”泡馆”生活了。

原文链接:https://blog.csdn.net/hongbin_xu/article/details/78390982

python dlib学习(五):比对人脸的更多相关文章

  1. Python基础学习五

    Python基础学习五 迭代 for x in 变量: 其中变量可以是字符串.列表.字典.集合. 当迭代字典时,通过字典的内置函数value()可以迭代出值:通过字典的内置函数items()可以迭代出 ...

  2. 【Python基础学习五】列表,元祖,字典

    1.列表(list) 列表是Python的一种内置数据类型,list是一种有序的集合,可以随时添加和删除其中的元素,就像动态数组一样.获取list中的元素用角标获取,角标可以使用正角标,也可以使用负角 ...

  3. Python Tutorial 学习(五)--Data Structures

    5. Data Structures 这一章来说说Python的数据结构 5.1. More on Lists 之前的文字里面简单的介绍了一些基本的东西,其中就涉及到了list的一点点的使用.当然,它 ...

  4. Python基础学习五 内置模块

    time 模块 1 >>> import time 2 >>> time.time() 3 1491064723.808669 4 >>> # t ...

  5. Python基础学习五 内置函数

    1.函数补充: 1)函数返回值return可以有多个 2)补充示例: nums = [0,1,2,3,4,5,6,7,8] #如何将list里面的元素变为字符串类型 new_nums = [str(x ...

  6. Python 3 利用 Dlib 19.7 实现摄像头人脸识别

    0.引言 利用python开发,借助Dlib库捕获摄像头中的人脸,提取人脸特征,通过计算欧氏距离来和预存的人脸特征进行对比,达到人脸识别的目的: 可以自动从摄像头中抠取人脸图片存储到本地: 根据抠取的 ...

  7. Python 3.6.3 利用Dlib 19.7库进行人脸识别

    0.引言 自己在下载dlib官网给的example代码时,一开始不知道怎么使用,在一番摸索之后弄明白怎么使用了: 现分享下 face_detector.py 和 face_landmark_detec ...

  8. !!对python列表学习整理列表及数组详细介绍

    1.Python的数组分三种类型:(详细见 http://blog.sina.com.cn/s/blog_6b783cbd0100q2ba.html) (1) list 普通的链表,初始化后可以通过特 ...

  9. 《Python爬虫学习系列教程》学习笔记

    http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多.学习过程中我把一些学习的笔记总结下来,还记录了一些自己 ...

随机推荐

  1. 2007英语CET6四6级资料六级大学单词

    anticipation n. 预期,期望 appreciation n. 感谢,感激 array n. 陈列,一系列 assurance n. 保证 emergency n. 紧急情况 encour ...

  2. 使用composer命令加载vendor中的第三方类库

    1.首先下载需要的第三方类库,放在TP框架下的vendor文件夹下 2.给第三方类库SDK写上命名空间,命名空间为该类库的文件夹对应的名字 3.在composer.json文件中添加需要加载的第三方类 ...

  3. centos 修改默认启动内核,及删除无用内核

    #使用cat /boot/grub2/grub.cfg |grep menuentry 查看系统可用内核 [root@bigapp-slave27 ~]# cat /boot/grub2/grub.c ...

  4. JVM&G1 GC 学习笔记(一)

    在入门学习JVM的过程中,我们需要先了解关于JVM的知识中有哪些关键词或关键术语,今天在看完书后我想记录下来. Xms64mb    虚拟机初始化时设置内存大小为64mb Xmx256mb  设定虚拟 ...

  5. CentOS7 编译安装MySQL5.6.38(一)

    一.下载MySQL5.6.38安装包 下载地址:https://www.mysql.com/downloads/  打开网站之后选择Archives 然后再选择开源版本 选择我们要下载的版本: htt ...

  6. FFLIB

    用于分布式程序的c++类库,封装了socket.rpc.lua.CQRS框架.算法等组件,适于SNS.WEBGAME.MMO后台程序, about C++,linux https://github.c ...

  7. Spring Boot 2实现分布式锁——这才是实现分布式锁的正确姿势!

    参考资料 网址 Spring Boot 2实现分布式锁--这才是实现分布式锁的正确姿势! http://www.spring4all.com/article/6892

  8. .dxf文件

    DXF 是 AutoCAD 与其它软件之间进行 CAD 数据交换的开放矢量数据文件格式,可以分为两类:ASCII 格式和二进制格式:ASCII 具有可读性好的特点,但占用的空间较大:二进制格式则占用的 ...

  9. java 8 学习三(Stream API)

    集合讲的是数据,流讲的是计算. 流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如filter. map. reduce. find. match. sort等. 流操作可以顺 ...

  10. Wooden Signs Gym - 101128E (DP)

    Problem E: Wooden Signs \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 给出一个\(n\),接下来\(n+1\)个数, ...