Dlib人脸识别实战:5分钟搭建Python人脸识别系统

人脸识别技术早已不再是科幻电影的专属,如今借助Python和Dlib库,即使是编程新手也能快速搭建自己的人脸识别系统。想象一下,你只需要几行代码,就能让电脑认出你的面孔——这听起来像是未来科技,但实际上实现起来比想象中简单得多。

1. 环境准备与工具安装

在开始之前,我们需要确保开发环境配置正确。推荐使用Python 3.7或更高版本,这是大多数计算机视觉库兼容性最好的Python版本。

1.1 安装必要依赖

首先打开终端或命令提示符,执行以下命令安装核心库:

pip install dlib opencv-python numpy

注意:Dlib的安装可能需要C++编译环境。如果遇到问题,可以尝试先安装CMake:pip install cmake

安装完成后,验证是否成功:

import dlib
print(dlib.__version__)  # 应该输出类似19.22.0的版本号

1.2 下载预训练模型

Dlib人脸识别需要三个关键文件:

  1. 人脸检测器(默认已包含在dlib中)
  2. 人脸特征点检测模型
  3. 人脸识别模型

可以通过以下链接获取后两个模型文件:

  • shape_predictor_5_face_landmarks.dat(特征点检测)
  • dlib_face_recognition_resnet_model_v1.dat(人脸识别)

提示:这些模型文件较大(约100MB),建议提前下载并放在项目目录的models文件夹中

2. 基础人脸检测实现

让我们从最简单的功能开始——检测图片中的人脸。

2.1 加载图片并检测人脸

import dlib
import cv2

# 初始化人脸检测器
detector = dlib.get_frontal_face_detector()

# 读取图片
image = cv2.imread("test.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 检测人脸
faces = detector(gray, 1)

# 在图片上标记人脸
for face in faces:
    x, y, w, h = face.left(), face.top(), face.width(), face.height()
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)

# 显示结果
cv2.imshow("Faces found", image)
cv2.waitKey(0)

2.2 实时摄像头人脸检测

将上述代码稍作修改,即可实现实时摄像头人脸检测:

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = detector(gray, 1)
    
    for face in faces:
        x, y, w, h = face.left(), face.top(), face.width(), face.height()
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
    
    cv2.imshow('Real-time Face Detection', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

3. 人脸特征提取与识别

真正的人脸识别需要提取人脸特征并比较这些特征。

3.1 加载识别模型

# 加载特征点检测模型
predictor = dlib.shape_predictor("models/shape_predictor_5_face_landmarks.dat")

# 加载人脸识别模型
face_rec_model = dlib.face_recognition_model_v1("models/dlib_face_recognition_resnet_model_v1.dat")

3.2 提取人脸特征向量

def get_face_descriptor(image_path):
    img = dlib.load_rgb_image(image_path)
    faces = detector(img, 1)
    
    if len(faces) == 0:
        return None
    
    shape = predictor(img, faces[0])
    face_descriptor = face_rec_model.compute_face_descriptor(img, shape)
    
    return np.array(face_descriptor)

3.3 比较两个人脸的相似度

def compare_faces(descriptor1, descriptor2, threshold=0.6):
    distance = np.linalg.norm(descriptor1 - descriptor2)
    return distance < threshold, distance

4. 构建完整的人脸识别系统

现在我们将所有部分组合起来,构建一个可以识别特定人物的系统。

4.1 创建人脸数据库

首先,我们需要建立一个已知人脸的数据库:

import os
import pickle

face_database = {}

def add_to_database(name, image_path):
    descriptor = get_face_descriptor(image_path)
    if descriptor is not None:
        face_database[name] = descriptor
        return True
    return False

# 示例:添加已知人脸
add_to_database("Alice", "known_faces/alice.jpg")
add_to_database("Bob", "known_faces/bob.jpg")

# 保存数据库
with open('face_database.pkl', 'wb') as f:
    pickle.dump(face_database, f)

4.2 识别未知人脸

def recognize_face(image_path, threshold=0.6):
    test_descriptor = get_face_descriptor(image_path)
    if test_descriptor is None:
        return "No face detected"
    
    min_distance = float('inf')
    best_match = "Unknown"
    
    for name, known_descriptor in face_database.items():
        distance = np.linalg.norm(known_descriptor - test_descriptor)
        if distance < min_distance:
            min_distance = distance
            best_match = name
    
    if min_distance < threshold:
        return best_match, min_distance
    else:
        return "Unknown", min_distance

4.3 实时人脸识别系统

结合前面的代码,我们可以创建一个实时识别系统:

def real_time_recognition():
    cap = cv2.VideoCapture(0)
    
    while True:
        ret, frame = cap.read()
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        faces = detector(rgb_frame, 1)
        
        for face in faces:
            x, y, w, h = face.left(), face.top(), face.width(), face.height()
            
            shape = predictor(rgb_frame, face)
            face_descriptor = face_rec_model.compute_face_descriptor(rgb_frame, shape)
            test_descriptor = np.array(face_descriptor)
            
            min_distance = float('inf')
            best_match = "Unknown"
            
            for name, known_descriptor in face_database.items():
                distance = np.linalg.norm(known_descriptor - test_descriptor)
                if distance < min_distance:
                    min_distance = distance
                    best_match = name
            
            if min_distance < 0.6:
                label = f"{best_match} ({min_distance:.2f})"
                color = (0, 255, 0)
            else:
                label = "Unknown"
                color = (0, 0, 255)
            
            cv2.rectangle(frame, (x, y), (x+w, y+h), color, 2)
            cv2.putText(frame, label, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
        
        cv2.imshow('Face Recognition', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    cap.release()
    cv2.destroyAllWindows()

5. 性能优化与实用技巧

虽然我们的基础系统已经可以工作,但还有一些改进空间。

5.1 提高识别准确率

  • 调整阈值:对于亚洲面孔,建议将阈值从0.6降低到0.4-0.5
  • 多张参考图片:为每个人存储多个角度的特征向量
  • 图像预处理:确保人脸在图片中大小适中且清晰
# 改进的特征提取函数
def get_enhanced_descriptor(image_path):
    img = dlib.load_rgb_image(image_path)
    img = cv2.resize(img, (0,0), fx=2, fy=2)  # 放大图像
    faces = detector(img, 1)
    
    if len(faces) == 0:
        return None
    
    shape = predictor(img, faces[0])
    face_descriptor = face_rec_model.compute_face_descriptor(img, shape)
    
    return np.array(face_descriptor)

5.2 处理多人脸场景

修改识别函数以处理一张图片中的多个人脸:

def recognize_multiple_faces(image_path, threshold=0.6):
    img = dlib.load_rgb_image(image_path)
    faces = detector(img, 1)
    results = []
    
    for face in faces:
        shape = predictor(img, face)
        descriptor = face_rec_model.compute_face_descriptor(img, shape)
        test_descriptor = np.array(descriptor)
        
        min_distance = float('inf')
        best_match = "Unknown"
        
        for name, known_descriptor in face_database.items():
            distance = np.linalg.norm(known_descriptor - test_descriptor)
            if distance < min_distance:
                min_distance = distance
                best_match = name
        
        if min_distance < threshold:
            results.append((best_match, min_distance, face))
        else:
            results.append(("Unknown", min_distance, face))
    
    return results

5.3 常见问题解决

  • 问题1:Dlib安装失败

    • 解决方案:先安装CMake和Boost库
    • Windows用户可以使用预编译的whl文件
  • 问题2:识别准确率低

    • 确保人脸在图片中占比适中(建议30%-70%)
    • 尝试不同的光照条件
    • 使用更高分辨率的图片
  • 问题3:处理速度慢

    • 缩小图片尺寸
    • 使用GPU加速(需要编译支持CUDA的Dlib版本)
# 性能优化示例:缩小图片尺寸
def fast_face_detection(image_path):
    img = cv2.imread(image_path)
    small = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
    gray = cv2.cvtColor(small, cv2.COLOR_BGR2GRAY)
    faces = detector(gray, 1)
    return [(face.left()*2, face.top()*2, face.width()*2, face.height()*2) for face in faces]
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐