【Python】利用 face_recognition 库进行人脸检测识别【附完整示例】

1. 背景条件

1.1 安装所需库

首先安装 face_recognitionPillow 这两个库。您可以使用以下命令来安装它们:

pip install face_recognition Pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
1.2 拷贝代码

安装完成后,您就可以在本地运行以下提供的代码了。

import face_recognition
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt
import time

def faceRecognition(image_path):
    # 尝试加载图片
    try:
        print(f"Loading image from {image_path}")
        image = face_recognition.load_image_file(image_path)
    except FileNotFoundError:
        return "Error: 文件未找到,请确保文件路径正确!"
    except Exception as e:
        return f"Error: {e}"

    # 人脸定位
    print("Detecting faces...")
    face_locations = face_recognition.face_locations(image)
    face_landmarks = face_recognition.face_landmarks(image)

    # 如果没有找到人脸,则返回
    if len(face_locations) == 0:
        return "没有在图片中找到人脸."

    # 打开图片并准备画图
    pil_image = Image.open(image_path)
    draw = ImageDraw.Draw(pil_image)

    for face_location, face_landmark in zip(face_locations, face_landmarks):
        top, right, bottom, left = face_location
        print(f"Drawing rectangle at location Top: {top}, Left: {left}, Bottom: {bottom}, Right: {right}")
        # 画人脸边框
        draw.rectangle(((left, top), (right, bottom)), outline=(255, 0, 0), width=3)
        # 画出人脸特征点
        for facial_feature in face_landmark.keys():
            for point in face_landmark[facial_feature]:
                draw.circle(point, radius=2, fill=(0, 255, 0))  # 使用绿色填充圆圈

    # 使用matplotlib显示图片
    plt.imshow(pil_image)
    plt.axis('off')  # 不显示坐标轴
    plt.show()

    # 保存图片
    output_path = "E:/imgs/recognized_faces_with_landmarks.jpg"
    pil_image.save(output_path)
    print(f"Image with landmarks saved to {output_path}")

if __name__ == '__main__':
    start = time.time()
    # 使用示例图片的路径
    sample_image_path = "E:/imgs/sample_image.jpg"
    output_path = faceRecognition(sample_image_path)
    print(output_path)
    end = time.time()
    print('共耗时' + str(end - start) + '秒')

2. 程序概述

这个程序使用 face_recognitionPillow 库来检测图片中的人脸,并在检测到的人脸周围画边框,同时在人脸的特征点上画绿色的小圆圈。最后,程序将修改后的图片保存到指定的路径。

3. 功能分解

  1. 导入必要的库
    • face_recognition:用于人脸检测和人脸特征点识别。
    • PIL(Pillow)库中的 ImageImageDraw:用于加载图片和在图片上画图。
  2. 定义 faceRecognition 函数
    • 参数image_path,即输入图片的路径。
    • 功能
      • 加载图片
        • 使用 face_recognition.load_image_file 尝试加载图片。
        • 如果图片不存在或发生其他错误,则捕获异常并返回错误信息。
      • 人脸定位
        • 使用 face_recognition.face_locations 方法找到图片中所有人脸的位置。
        • 使用 face_recognition.face_landmarks 方法找到每个人脸的特征点。
      • 检查是否找到人脸
        • 如果没有找到人脸,则返回相应的信息。
      • 打开图片并准备画图
        • 使用 Pillow 库打开图片。
        • 创建一个 ImageDraw 对象用于在图片上画图。
      • 画人脸边框和特征点
        • 遍历每个人脸位置和特征点。
        • 使用 draw.rectangle 方法在每个人脸周围画一个红色边框。
        • 使用 draw.circle 方法在每个人脸的特征点上画一个绿色的小圆圈。
      • 保存图片
        • 将修改后的图片保存到指定的路径(E:/imgs/recognized_faces_with_landmarks.jpg)。
      • 返回值
        • 返回保存后的图片的路径。
  3. 调用 faceRecognition 函数
    • 使用示例图片的路径(sample_image_path)作为参数调用 faceRecognition 函数。
  4. 输出 output_path
    • 打印出保存后的图片的路径,以便知道图片被保存在哪里。

4. 运行效果

4.1 单人检测效果

在这里插入图片描述

4.2 多人检测效果

在这里插入图片描述

5. 小结

以上程序接受一个图片路径作为输入,检测图片中的人脸和特征点,然后在每个人脸周围画红色边框,在特征点上画绿色小圆圈,最后将修改后的图片保存并返回保存路径。这是一个典型的人脸识别和图像处理任务,可以用于各种需要人脸识别的应用场景。

6. 进阶:人脸识别比对

在以上的基础上,我们应用欧氏距离进行人脸距离计算

6.1 定义

欧氏距离(Euclidean distance)是数学中的一个概念,用于计算两个点在欧几里得空间中的直线距离。在人脸识别和图像处理中,欧氏距离可以用来度量两个面部特征向量之间的差异,从而判断两张人脸的相似度。

6.2 原理:

在二维空间中,两个点AB之间的欧氏距离可以通过以下公式计算:

  • 第一个点A的坐标:
    A=(x1,y1) A = (x_1, y_1) A=(x1,y1)

  • 第二个点B的坐标:
    B=(x2,y2) B = (x_2, y_2) B=(x2,y2)

  • 二维空间的欧氏距离公式:
    d=(x2−x1)2+(y2−y1)2 d = \sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2} d=(x2x1)2+(y2y1)2

在人脸识别中,每张人脸可以表示为一个高维向量,其中每个维度对应于面部特征的一个量化值,比如眼睛的位置、鼻子的宽度、嘴巴的形状等。假设我们有两个面部特征向量AB,它们分别是n维的:

  • 向量A的表示:
    A=[a1,a2,...,an] \textbf{A} = [a_1, a_2, ..., a_n] A=[a1,a2,...,an]
  • 向量B的表示:
    B=[b1,b2,...,bn] \textbf{B} = [b_1, b_2, ..., b_n] B=[b1,b2,...,bn]
6.3 公式扩展

欧氏距离的计算公式扩展到 n 维空间为:

  • n维空间的欧氏距离公式:
    d(A,B)=∑i=1n(bi−ai)2 d(\textbf{A}, \textbf{B}) = \sqrt{\sum_{i=1}^{n} (b_i - a_i)^2} d(A,B)=i=1n(biai)2
6.4 判断人脸距离:
  1. 特征提取:首先,从每张人脸图片中提取特征,这些特征可以是面部关键点的坐标、局部特征描述符(如LBP、HOG)或者深度学习模型提取的特征向量。
  2. 特征标准化:为了消除不同量纲和数值范围的影响,通常需要对特征向量进行标准化处理。
  3. 计算距离:使用上述公式计算两个特征向量之间的欧氏距离。
  4. 相似度判断:设定一个阈值 ( \theta ),如果两个特征向量之间的欧氏距离小于这个阈值,可以认为这两张人脸是相似的或者是同一个人;如果距离大于这个阈值,则认为它们属于不同的人。
6.5 结论

欧氏距离越小,表明两张人脸越相似;欧氏距离越大,表明两张人脸的差异越大。在实际应用中,这个方法可能会受到光照、姿态、表情等因素的影响,因此通常会结合其他方法和算法来提高人脸识别的准确率和鲁棒性。

但在本次的程序中,我们为了条件方便,用了如下方式,所以得出的相似度分数越大则表示两张面孔越相似

similarity_score = 1 - face_distances[0]
6.6 程序代码
import face_recognition
from PIL import Image, ImageDraw
from matplotlib import pyplot as plt
import time


def faceRecognition(image_path, known_image_path, tolerance=0.8):
    # 尝试加载图片
    try:
        print(f"Loading image from {image_path}")
        image = face_recognition.load_image_file(image_path)
        known_image = face_recognition.load_image_file(known_image_path)
    except FileNotFoundError as e:
        return f"Error: {e}"
    except Exception as e:
        return f"Error: {e}"

    # 获取已知人脸编码
    print("Encoding known face...")
    known_face_encoding = face_recognition.face_encodings(known_image)[0]

    # 人脸定位和编码
    print("Detecting faces...")
    face_locations = face_recognition.face_locations(image)
    face_encodings = face_recognition.face_encodings(image, face_locations)

    # 如果没有找到人脸,则返回
    if len(face_locations) == 0:
        return "没有在图片中找到人脸."

    # 打开图片并准备画图
    pil_image = Image.open(image_path)
    draw = ImageDraw.Draw(pil_image)

    # 遍历每个人脸位置和人脸编码
    for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
        # 比较人脸
        matches = face_recognition.compare_faces([known_face_encoding], face_encoding, tolerance=tolerance)

        # 计算相似度分数
        face_distances = face_recognition.face_distance([known_face_encoding], face_encoding)
        similarity_score = 1 - face_distances[0] if face_distances[0] <= 1 else 0
        similarity_score_rounded = round(similarity_score, 2)

        name = "Unknown"
        if True in matches and similarity_score>tolerance:
            name = "Known"

        # 画人脸边框
        draw.rectangle(((left, top), (right, bottom)), outline=(255, 0, 0), width=3)
        # 打印匹配信息
        match_text = f"{name} (Match: {'Yes' if True in matches and similarity_score>tolerance else 'No'})"
        similarity_text = f"Similarity: {similarity_score_rounded}"
        draw.text((right + 10, top), f"{match_text}\n{similarity_text}", fill=(255, 255, 255))

    # 使用matplotlib显示图片
    plt.imshow(pil_image)
    plt.axis('off')  # 不显示坐标轴
    plt.show()

    # 保存图片
    output_path = "recognized_faces.png"
    pil_image.save(output_path)
    print(f"Image with recognized faces saved to {output_path}")


def CompareFace(knownpath, unknowpath):
    sample_image_path = unknowpath  # 待识别的人脸图片路径
    known_image_path = knownpath  # 已知人脸图片路径
    output_path = faceRecognition(sample_image_path, known_image_path)
    end = time.time()
    totalTime = end - start


if __name__ == '__main__':
    start = time.time()
    CompareFace("E:/imgs/img2.png", "E:/imgs/img2.png")	# 测试相同人脸图片
    CompareFace("E:/imgs/img2.png", "E:/imgs/img.png")	# 测试不同人脸图片
    end = time.time()
    totalTime = end - start
    print('共耗时 %.2f 秒'%(totalTime))

以上程序使用 face_recognition 库来来检测、编码人脸和识别图片中的人脸,并使用 matplotlib 库来显示识别结果。并可以保存带有识别结果的图片。通过调整 tolerance 参数,可以设置匹配的相似度阈值。

在以上程序中我们使用 face_distance 函数来计算检测到的人脸与已知人脸之间的距离。然后,我们将距离转换为相似度分数,并四舍五入到两位小数。匹配信息(“Match: Yes” 或 “Match: No”)和相似度分数都打印在检测到的人脸红框的右侧。

相似度分数是通过 1 - face_distances[0] 计算的,以确保分数在 0 到 1 之间。如果距离大于 1,我们将其设置为 0,因为这种情况表明两张脸完全不相似。

7. 识别效果

7.1 相同图片测试

我们传入两张相同的图片,测试结果如下:

结果正如预期一样,识别出已知且相似度为1.0,说明完全相似

在这里插入图片描述

7.2 不同图片测试

此时我们传入的是两张完全不同的图片,测试结果如下:

结果也正如预期一样,识别出未知且相似度分数只有0.17。

在这里插入图片描述

以上就是本文的全部内容了,感兴趣的小伙伴可以尝试自行扩展程序,实现一个简单的人脸识别系统。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ustinian_310

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值