重点关注:强调一下,这里没有任何侮辱周董的意思,我也是一名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迷,我很气愤。。

源代码戳这里