人脸识别最简单但性能最好的喂饭教程

121 阅读5分钟

大家知道人脸识别吗,计算机上的视频(本质也是图⽚)是由数字组成的,因此通过数学计算可以进⾏图像识别。⼈脸识别任务是图像识别的⼦类,图像识别可拆分为图像检测和图像对⽐两个任务:检测图像⾥的⼈脸,实际上是分类问题的⼀种,即图像⾥有没有⼈脸,图像对⽐是指检测出的⼈脸和预先采集的⼈脸的相似程度。 在这里插入图片描述

⼈脸识别的⼀般步骤:

  1. 图⽚转换为灰度:这是因为灰度图像只包含亮度信息,简化了处理过程,同时保留了识别所需的主要特征信息。在OpenCV中,我们使用cvtColor函数将BGR彩色图像转换为灰度图像。
  2. 识别图像中的⼈脸,使用预训练的人脸分类器(如Haar级联分类器)来检测图像中的人脸区域。OpenCV提供了haarcascade_frontalface_default.xml这个预训练模型,它能够有效地检测正面人脸。
  3. 训练特征库,将特定的⼈脸标注并存⼊特征库,这个步骤包括收集人脸样本、提取特征并建立模型。我们需要: 使用摄像头采集多张人脸图片(通过按's'键保存) 将采集的图片转换为灰度图并提取特征 使用LBPH(Local Binary Pattern Histogram)算法训练模型 将训练好的模型保存为yml文件
  4. ⽐对⽬标图⽚(视频),对⽬标图像出现的⼈脸进⾏判断,根据相似程度进⾏后续处理

人脸识别有哪些常用库:

  1. 基于特征向量⽅法:OpenCV
  2. 基于 CNN 或 HOG ⽅法:Tensorflow、PyTorch

我们这里采用 OpenCV 库来教大家怎么完成人脸识别的训练和识别结果,通过 OpenCV 库,分析图像的基本组成,图像中的每⼀个像素点由三个元素组成,分别表示 RGB 三种颜⾊,而⼀张图⽚的宽和⾼由多个像素点组成。

Opencv的使用流程

1. 准备工作 首先安装必要的库,我这里使用的是python3.9:

# opencv基础库
pip install opencv-python
# pillow图像处理库
pip install pillow
# contrib用于训练人脸模型的opencv扩展包
pip install opencv-contrib-python

2. 采集人脸样本

import cv2 as cv

cap = cv.VideoCapture(0)
num = 1
face_name = "Boss"
face_id = 1

while (cap.isOpened()):
    # 捕获摄像头图像
    ret_flag, vshow = cap.read()
    # 显示捕获的照片
    cv.imshow("capture_test", vshow)
    # 图像刷新的频率
    k = cv.waitKey(1) & 0xff
    # 设置按键保存照片
    if k == ord('s'):
        # 保存图片
        cv.imencode(".jpg", vshow)[1].tofile(f"./imgdata/{str(face_id)}_{face_name}_{str(num)}.jpg")
        print(f"成功保存第{str(num)}张照片")
        num += 1
    elif k == ord(' '):
        break
# 关闭摄像头
cap.release()
# 销毁窗口
cv.destroyAllWindows()

在采集样本阶段,我们使用摄像头捕获人脸图片,按's'键保存图片,保存格式为"ID_姓名_序号.jpg",这里建议建议每个人保存20-30张不同角度的照片,然后按空格键结束采集。

3. 训练模型阶段 将采集的图片用于训练模型:

import cv2 as cv
from PIL import Image
import numpy as np
from pathlib import Path

def getImageAndLabel(path):
    facesSamples = []
    ids = []

    # 调用人脸分类器
    face_detect = cv.CascadeClassifier('haarcascade_frontalface_default.xml')

    # 循环读取照片人脸数据
    for imagePath in Path(path).rglob("*"):
        # 用灰度的方式打开照片
        PIL_img = Image.open(imagePath).convert('L')
        # 将照片转换为计算机能识别的数组OpenCV(BGR--0-255)
        img_numpy = np.array(PIL_img, 'uint8')
        # 提取图像中人脸的特征值
        faces = face_detect.detectMultiScale(img_numpy)
        # 将文件名按"."进行分割
        id = int(imagePath.stem.split("_")[0])
        # 防止无人脸图像
        for x,y,w,h in faces:
            ids.append(id)
            facesSamples.append(img_numpy[y:y+h, x:x+w])
    return facesSamples, ids


# 获取图片数据和对应的ID
faces, ids = getImageAndLabel('imgdata')

# 调用LBPH算法对人脸数据进行处理
recognizer = cv.face.LBPHFaceRecognizer_create()

# 训练数据
recognizer.train(faces, np.array(ids))

# 保存训练模型
recognizer.write('trainer/trainer.yml')

在上面代码中,我们在这个阶段会先读取所有样本图片并转换为灰度图,使用人脸分类器检测每张图片中的人脸区域,提取人脸特征并与ID关联,使用LBPH算法训练模型,最后将训练好的模型保存为yml文件。

4. 实时人脸识别 使用训练好的模型进行实时人脸识别:

import cv2

# 创建识别器并加载训练好的模型
recogizer = cv2.face.LBPHFaceRecognizer_create()
recogizer.read('trainer/trainer.yml')

names = ["Boss"]  # 名字
idn = [1]  # 标签

# 识别图片
def face_detect_demo(img):
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 调用人脸分类器
    face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

    # 读取人脸特征并返回人脸坐标
    face = face_detector.detectMultiScale(gray, 1.1, 5, 0, (100,100), (800,800))
    for x,y,w,h in face:
        # 标记人脸
        cv2.rectangle(img, (x,y), (x+w,y+h), color=(0,0,255), thickness=2)
        # 识别人脸
        ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])
        if confidence > 60:
            print("陌生人")
        else:
            print("老板来了,自动关闭游戏")
    cv2.imshow('result', img)

# 打开摄像头进行实时识别
cap = cv2.VideoCapture(0)

while True:
    flag, frame = cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if ord(' ') == cv2.waitKey(10):
        break

cv2.destroyAllWindows()
cap.release()

首先我们会加载训练好的模型,实时去捕获摄像头画面,检测画面中的人脸,将检测到的人脸与模型进行对比然后根据置信度判断身份,最后在画面中标注识别结果。 到这里我们的人脸识别系统就做好了,基本上满足了实时性,并且使用非常简单。需要注意的是,在采集样本时,确保光线充足,采集不同角度的人脸图片,保持适当的拍摄距离

系统优化建议

识别参数调整: scaleFactor:默认1.1,值越大检测速度越快,越小检测越精确; minNeighbors:默认5,值越大误检测越少,但可能漏检; minSize和maxSize:限制检测人脸的大小范围; 可以调整detectMultiScale函数的参数提高检测效果; 置信度阈值:代码中设置的阈值为60,可以根据实际需求调整,阈值越低,误识别率越高;阈值越高,可能出现识别不出的情况 实时性优化:可以适当降低视频帧率提高处理速度,考虑使用多线程处理提高性能 这个系统可以根据实际需求进行扩展,比如添加多人识别、记录识别日志、触发特定动作等功能。通过调整各项参数,可以在识别准确率和系统性能之间找到最佳平衡点。感兴趣的同学自己尝试优化,当然也可以跟随我们的公众号,等待后续我们出优化的思路。