51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Python face_recognition Package

face_recognition 是一个基于 dlib 库的人脸识别工具包。主要包括:

  1. 标注人脸位置
  2. 计算人脸特征
  3. 人脸信息编码
  4. 人脸信息匹配

该 Python 工具包使用起来也比较简单,我们就通过几个例子来了解下使用方法。也可以直接参考文档,下联链接已经给出:

Document: https://face-recognition.readthedocs.io/en/latest/readme.html

  1. Face Recognition 安装 {#title-0} =================================

安装要求:

  • Python 3.3+ or Python 2.7
  • macOS or Linux (Windows not officially supported, but might work)
pip install face_recognition

详细按照文档:https://face-recognition.readthedocs.io/en/latest/readme.html#requirements

  1. 标注人脸位置 {#title-1} ====================

人脸识别使用的接口为:

face_locations(img, number_of_times_to_upsample=1, model="hog")
  • img 为要进行人脸检测的输入图像
  • number_of_times_to_upsample 在进行人脸检测时,face_locations 函数使用了一个基于 HOG 特征的人脸检测算法。这种算法对于输入的图像分辨率有一定的要求,因为低分辨率的图像往往难以检测出人脸。为了解决这个问题 face_locations 函数会先对输入图像进行上采样,提高其分辨率,然后再进行人脸检测。具体来说,它表示对输入图像进行几次上采样。每次上采样都会使图像的分辨率翻倍,因此上采样的次数越多,图像的分辨率就越高,人脸检测的精度也会相应提高。但是,上采样次数越多,计算时间也会相应增加。因此,在设置这个参数时需要根据实际需求进行平衡。
  • model 使用何种人脸检测模型,可选的值有:hog 和 cnn,hog 的准确率低一些,但是更快。cnn 是深度模型,有着更好的准确率,但是检测速度要慢一些,使用时,可能需要 GPU 加速模型计算以便能够获得更好的实时性能
  • 返回值:该函数将会返回一个列表,列表中的每个元素都是一个包含了 4 个位置值 (top, right, bottom, left) 的元组,用于表示人脸的位置

接下来,我们使用该 API 检测下面输入图像中的人脸位置,下面是示例代码(test03 为 cv2 中的检测器示例):

import face_recognition
import matplotlib.pyplot as plt
import cv2
import time


# 获得人脸坐标
def test01():

    # 1. 读取要识别的图像
    image = face_recognition.load_image_file('1.jpg', mode='RGB')
    print('图片尺寸:', image.shape)

    # 2. 使用 hog 检测人脸位置
    start = time.time()
    face_locations = face_recognition.face_locations(image, model='hog')
    print('HOG 检测时间:', time.time() - start)

    # 3. 绘制人脸位置
    for top, right, bottom, left in face_locations:
        cv2.rectangle(image, (left, top), (right, bottom), color=(255, 0, 255), thickness=2)
        plt.title('HOG')
        plt.imshow(image)
    plt.show()


def test02():

    # 1. 读取要识别的图像
    image = face_recognition.load_image_file('1.jpg', mode='RGB')
    print('图片尺寸:', image.shape)

    # 2. 使用 cnn 检测人脸位置
    start = time.time()
    face_locations = face_recognition.face_locations(image, model='cnn')
    print('CNN 检测时间:', time.time() - start)

    # 3. 绘制人脸位置
    for top, right, bottom, left in face_locations:
        cv2.rectangle(image, (left, top), (right, bottom), color=(255, 0, 255), thickness=2)
        plt.title('CNN')
        plt.imshow(image)
    plt.show()


def test03():
    # 1. 读取要识别的图像
    image = cv2.imread('1.jpg', cv2.IMREAD_COLOR)
    print('图片尺寸:', image.shape)

    # 2. 使用 cv2 检测人脸位置
    model = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
    # 检测之前先将图像转换为灰度图
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    start = time.time()
    # 返回: x, y, width, height
    face_locations = model.detectMultiScale(gray_image)
    print('CV2 检测时间:', time.time() - start)

    # 3. 绘制人脸位置
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    for x, y, width, height in face_locations:
        cv2.rectangle(image, (x, y), (x + width, y + height), color=(255, 0, 255), thickness=2)
        plt.title('CV2')
        plt.imshow(image)
    plt.show()


if __name__ == '__main__':
    test01()
    test02()
    test03()

程序输出结果:

图片尺寸: (432, 658, 3)
HOG 检测时间: 0.11088299751281738
图片尺寸: (432, 658, 3)
CNN 检测时间: 2.421550750732422
图片尺寸: (432, 658, 3)
CV2 检测时间: 0.06716680526733398

上述输出的检测时间都是在 CPU 上的计算结果。

  1. 计算人脸特征 {#title-2} ====================

人脸特征即提取下巴(chin)、左眉(left_eyebrow)、右眉(right_eyebrow)、鼻梁(nose_bridge)、鼻尖(nose_tip)、左眼(left_eye)、右眼(right_eye)、上唇(top_lip)、下唇(bottom_lip)共计 72 个关键位置特征。

如果将 face_landmarks 函数的 model 参数设置为 small,则只输出鼻尖(nose_tip)、左眼(left_eye)、右眼(right_eye)这三个部位共计 5 位置特征

import face_recognition
import matplotlib.pyplot as plt


def test():

    image = face_recognition.load_image_file('1.jpg', mode='RGB')

    # [(51, 365, 149, 267)]  => top, right, bottom, left
    face_locations = face_recognition.face_locations(image, model='hog')

    # 获得人脸特征
    facial_features = face_recognition.face_landmarks(image, face_locations, model='large')
    print(facial_features)

    # 绘制人脸特征
    for facial_feature in facial_features:
        for key, features in facial_feature.items():
            for feature in features:
                cv2.circle(image, feature, radius=2, color=(0, 255, 12))

    plt.imshow(image)
    plt.show()


if __name__ == '__main__':
    test()

程序输出结果:

[{'chin': [(278, 92), (278, 104), (279, 117), (281, 130), (284, 142), (290, 154), (298, 164), (306, 173), (318, 175), (332, 173), (344, 165), (355, 156), (365, 146), (371, 133), (374, 119), (375, 105), (376, 91)], 'left_eyebrow': [(283, 85), (289, 79), (297, 79), (305, 81), (313, 84)], 'right_eyebrow': [(323, 83), (332, 80), (342, 78), (352, 80), (359, 86)], 'nose_bridge': [(318, 91), (318, 99), (317, 108), (316, 117)], 'nose_tip': [(309, 122), (313, 124), (317, 125), (322, 124), (327, 123)], 'left_eye': [(292, 90), (296, 87), (302, 87), (307, 91), (302, 92), (296, 92)], 'right_eye': [(333, 91), (338, 88), (344, 88), (349, 91), (344, 93), (338, 93)], 'top_lip': [(306, 143), (309, 138), (313, 135), (317, 137), (322, 136), (328, 139), (333, 144), (330, 144), (322, 141), (317, 141), (314, 141), (309, 143)], 'bottom_lip': [(333, 144), (328, 151), (322, 154), (318, 154), (313, 153), (309, 149), (306, 143), (309, 143), (313, 144), (317, 145), (322, 144), (330, 144)]}]

  1. 人脸信息编码 {#title-3} ====================

我们在做人脸匹配时,比较的就是两个人脸的编码距离。face_encodings 函数如下:

face_encodings(face_image, known_face_locations=None, num_jitters=1, model="small")
  • face_image 输入的检测图像
  • known_face_locations 为 face_locations 函数检测到的多个人脸位置
  • model 可选的值为 large、small,表示用多少个人脸特征来构造人脸编码,small 更快
  • num_jitters 它指定了在提取人脸特征时进行多少次随机扰动(jitter),随机扰动指的是将输入的人脸图像进行随机的微小变换,例如旋转、裁剪、亮度变换等,从而生成多个略微不同的人脸图像。在进行人脸特征提取时,将这些略微不同的图像进行特征提取,并将得到的特征向量进行平均或取中位数,可以提高人脸识别的精度,但计算时间也会相应增加。

示例代码:

import face_recognition
import matplotlib.pyplot as plt


def test():
    # 读取输入图像
    image = face_recognition.load_image_file('1.jpg', mode='RGB')
    # 计算人脸位置
    face_locations = face_recognition.face_locations(image, model='hog')
    # 人脸信息编码
    face_encodings = face_recognition.face_encodings(image, known_face_locations=face_locations, model='large')
    print('人脸编码维度:', face_encodings[0].shape)
    print(face_encodings)

if __name__ == '__main__':
    test()

程序输出结果:

人脸编码维度: (128,)
[array([-0.10339236,  0.14851965,  0.01029977,  0.00930228, -0.15734453,
        0.03904981,  0.01654922, -0.17565952,  0.05527157, -0.12608829,
        0.18594478, -0.07738445, -0.31720433, -0.09317419,  0.0242323 ,
        0.17734227, -0.1299797 , -0.1051617 , -0.21656519, -0.10200764,
        0.00980881,  0.06125376, -0.03489925, -0.02904189, -0.12794323,
       -0.25462753, -0.08247674, -0.03054573,  0.02245354, -0.04793654,
        0.04205053,  0.01841517, -0.23550904, -0.06501944, -0.02505583,
        0.02860026, -0.05353981, -0.06184244,  0.13586399,  0.03928199,
       -0.13611943,  0.04089652,  0.01368326,  0.23697728,  0.18460381,
       -0.00639988,  0.02225903, -0.09905794,  0.11359482, -0.24700806,
       -0.0144341 ,  0.12040581,  0.11725815,  0.08271284,  0.03133506,
       -0.08889135,  0.04660001,  0.13280977, -0.147306  ,  0.07945663,
        0.09690579, -0.18537416, -0.06320523, -0.06023312,  0.12699956,
        0.0395139 , -0.02118635, -0.13156748,  0.19904432, -0.14599995,
       -0.11009898,  0.00675882, -0.07475307, -0.13796815, -0.39703727,
        0.03987332,  0.40932226,  0.17702992, -0.2292663 , -0.04161827,
       -0.04523409,  0.02514784,  0.1070801 ,  0.06148657, -0.04007861,
       -0.12225512, -0.12017394,  0.07339939,  0.25885367, -0.10757827,
       -0.00895133,  0.28658509,  0.07006181, -0.04103569,  0.03035998,
        0.00265448, -0.0738667 , -0.06689832, -0.03737948, -0.01301235,
        0.1173306 , -0.16319954,  0.03531633,  0.11514346, -0.14696895,
        0.20176159, -0.02319317,  0.00985028,  0.01496939, -0.05379927,
       -0.08210421,  0.02171123,  0.19380003, -0.15109025,  0.20256151,
        0.20543517, -0.08692768,  0.09492791,  0.07402149,  0.1480388 ,
       -0.07978582,  0.00954351, -0.15085556, -0.18490645,  0.05490613,
        0.00381539,  0.02888954,  0.05953676])]
  1. 人脸信息匹配 {#title-4} ====================

人脸信息匹配其实就是将两个人脸的编码计算欧式距离,距离越大则越不相似,我们实际在比较两个人脸相似度时,就需要设置一个判断阈值。

我们接下来从下面两张图片中提取人脸编码信息,并比较是否是同一个人。

示例代码:

import face_recognition
import matplotlib.pyplot as plt

def test():

    # 读取输入图像
    trump = face_recognition.load_image_file('1.jpg', mode='RGB')
    biden = face_recognition.load_image_file('2.jpeg', mode='RGB')

    # 识别人脸位置
    trump_locations = face_recognition.face_locations(trump, model='hog')
    biden_locations = face_recognition.face_locations(biden, model='hog')

    # 绘制提取人脸
    top, right, bottom, left = trump_locations[0]
    plt.subplot(121)
    plt.title('Trump')
    plt.imshow(trump[top: bottom, left: right])

    top, right, bottom, left = biden_locations[0]
    plt.subplot(122)
    plt.title('Biden')
    plt.imshow(biden[top: bottom, left: right])
    plt.show()

    # 人脸信息编码
    trump_encodings = face_recognition.face_encodings(trump, trump_locations)
    biden_encodings = face_recognition.face_encodings(biden, biden_locations)

    # 计算人脸相似度
    similarity = face_recognition.face_distance(trump_encodings, biden_encodings[0])
    print('人脸相似度:', similarity)  # 值越大越不相似

    # 比较人脸编码
    # tolerance 为阈值,两个人脸编码的欧式距离小于该值认为相似,默认为 0.6, 值越大越严格
    # 第一个参数为一个人脸编码列表
    # 第二个参数为单个人脸编码数值
    result = face_recognition.compare_faces(trump_encodings, biden_encodings[0], tolerance=0.3)
    print(result)


if __name__ == '__main__':
    test()

程序执行结果:

人脸相似度: [0.62457377]
[False]

提取到人脸图像

赞(2)
未经允许不得转载:工具盒子 » Python face_recognition Package