python开源库dlib入门,并进行人脸检测,看看周杰伦和东尼大木到底有多相似?看完本文再不要说,周和东像。。
重点关注:强调一下,这里没有任何侮辱周董的意思,我也是一名Jay迷。只是为了学习,大家见谅。。源代码戳这里
开启dlib库的学习
第一步:首先得安装dlib库,这里建议直接下载dlib,不然用pip直接装,需要安装cmake..这里我提供的是python3.6的dlib。。下载地址:点我下载
接着安装 pip install dlib-19.8.1-cp36-cp36m-win_amd64.whl 就装好了。。
测试一下:
接下来做第一个练习:人脸检测。。代码很简单,我就不再赘述了,里面有详细的注释
import dlib
from imageio import imread
import glob
# glob使用来读取图片列表的,效率非常高
# 实例化一个人脸检测器
detector = dlib.get_frontal_face_detector()
# 获得一个窗口
win = dlib.image_window()
# 这里是批量读取图片,就是读取你在data目录下所有以jpg结尾的文件
paths = glob.glob('data/*.jpg') # 这里的路径需要改为你自己的路径
# paths返回的是一个列表。。就是每一张图片
# 接下来对每一张脸进行检测
for path in paths:
img = imread(path)
# 将读取的图片放进检测器中
dets = detector(img)
print(dets)
print("检测到%d个人脸"%(len(dets)))
for i, d in enumerate(dets):
print("{},左{},上{},右{},下{}".format(i, d.left(), d.top(), d.right(), d.bottom()))
win.clear_overlay()
win.set_image(img)
win.add_overlay(dets)
dlib.hit_enter_to_continue() # 设置按enter继续
运行代码:
接下来做第二个练习:除了检测人脸,还要检测出脸上的局部特征
做法:主要还是用练习一中的人脸检测,再加上一个特征检测,不用害怕,就是一个已训练好的模型,你只需要加载就行了,这个shape_predictor_68_face_landmarks.dat我放在github上。文章末尾给资源的链接
import dlib
from imageio import imread
import glob
detector = dlib.get_frontal_face_detector()
predictor_path = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(predictor_path)
# 实例化一个窗口
win = dlib.image_window()
# 把所有图片加载上来
paths = glob.glob('data/*.jpg')
for path in paths:
img = imread(path)
win.clear_overlay()
win.set_image(img)
# 1 表示将图片放大一倍,便于检测到更多的人脸
dets = detector(img)
print("检测到%d个人脸" % len(dets))
for i, d in enumerate(dets):
print("{}, 左{}, 上{}, 右{}, 下{}".format(i, d.left(), d.top(), d.right(), d.bottom()))
shape = predictor(img, d) # 这里传入的人脸检测的效果和原图
print('Part 0: {}, Part 1: {}'.format(shape.part(0), shape.part(1)))
win.add_overlay(shape)
win.add_overlay(dets)
dlib.hit_enter_to_continue()
运行结果 :
接下来做第三个练习:看看周杰伦和东尼大木到底有多像。。
我们的做法是:先通过人脸检测将人脸特征提取出来,再将人脸生成一个128维的向量,最后计算人脸之间的欧式距离
准备图片:东尼大木三张,周杰伦四张,我们还有一个test文件夹,里面放了两张测试图。等会看两张图距离这七张图的距离
代码走起:
这个代码在windows上运行完全没问题,但是在linux或者mac上,提取name的那一行代码需要改一下,主要是windows和mac的目录表示不同,一个是‘\’,一个是'/'。。
import dlib
from imageio import imread
import glob
import numpy as np
detector = dlib.get_frontal_face_detector()
predictor_path = 'shape_predictor_68_face_landmarks.dat'
predictor = dlib.shape_predictor(predictor_path)
face_rec_model_path = 'dlib_face_recognition_resnet_model_v1.dat'
facerec = dlib.face_recognition_model_v1(face_rec_model_path)
labeled = glob.glob('faces/*.jpg')
labeled_data = {}
unlabeled = glob.glob('faces/test/*.jpg')
# 定义一个计算距离的公式
def distance(a, b):
return np.linalg.norm(np.array(a) - np.array(b), ord=2)
# 读取标注图片并保存对应的128维向量
for path in labeled:
img = imread(path)
print(path)
name = path.split("\\")[1].rstrip('.jpg')
dets = detector(img, 1)
# 这里假设每张图只有一张脸, 计算脸映射的***向量
shape = predictor(img, dets[0]) # 其实咱们图片中也就一张脸
face_vector = facerec.compute_face_descriptor(img, shape)
# 保存人的名字与其对应的向量
labeled_data[name] = face_vector
# 把测试的两张图片读出来,计算与训练的那些图的距离
for path in unlabeled:
print(path)
img = imread(path)
name = path.split('/')[1].strip('\\')[1].rstrip('.jpg')
dets = detector(img, 1)
# 这里假设每张图只有一个人脸
shape = predictor(img, dets[0])
face_vector = facerec.compute_face_descriptor(img, shape)
matches = []
for key, value in labeled_data.items():
d = distance(face_vector, value)
if d < 0.6:
matches.append(key + ' %.2f' % d)
print('{}:{}'.format(name, ';'.join(matches)))
输出结果:
结果说明,东尼大木的测试图明显距离自己的那三张图距离小,距离周杰伦的那四张距离大。。而周杰伦距离自己的那四张图片距离明显很小,但是距离东尼大木的距离明显大。 总结:以后再别说周杰伦和东尼大木很像,作为Jay迷,我很气愤。。