一、写在前面:人脸识别到底是什么?

你有没有好奇过,手机的人脸解锁、门禁的刷脸开门,到底是怎么认出你的?

其实核心逻辑很简单:

  1. 先 “记住” 人脸:把你的多张照片喂给算法,让它学习你的面部特征,相当于给你建了一个 “人脸档案”
  2. 再 “认出” 人脸:用新的照片去和档案里的特征做对比,找到最像的那个,就完成了识别

今天我们用LBPH(局部二值模式直方图) 这个超适合新手的算法,用 Python+OpenCV 从零实现一个人脸识别小项目,全程代码可复制,小白也能一步跑通!


二、先搞懂:LBPH 到底是个啥?

不用怕复杂公式,我们用大白话讲清楚 LBPH 的原理:

1. 核心思想:把人脸变成 “特征直方图”

LBPH 的本质,是把一张人脸照片,转换成一串能代表它特征的数字,方便计算机对比:

  • LBP(局部二值模式):给人脸的每个像素点,都和它周围的 8 个邻居比大小,比它大就记 1,小就记 0,最后生成一个 8 位的二进制数,相当于给这个像素打了个 “特征标签”
  • PH(直方图):把整张脸分成 8×8=64 个小格子,每个格子里统计所有像素的 LBP 标签出现的次数,生成一个小直方图
  • 最终特征:把 64 个小直方图拼起来,就得到了这张人脸的 “专属特征串”,相当于人脸的 “身份证”

2. 为什么 LBPH 适合新手?

  • 原理简单,代码量少,不用复杂的深度学习模型
  • 对光照、表情的小变化鲁棒性不错,适合入门级人脸识别
  • OpenCV 直接封装好了现成的 API,不用自己从零实现算法

三、环境准备:3 步搞定开发环境

1. 安装 Python

如果还没装 Python,直接去

Python 官网

File

下载 3.9 及以上版本,安装时记得勾选「Add Python to PATH」,避免后续环境问题。

2. 安装 OpenCV 和 NumPy

打开电脑的命令提示符(CMD),输入下面两行命令,一键安装依赖:

bash

运行

pip install opencv-python opencv-contrib-python numpy
  • opencv-python:OpenCV 主库,用来处理图片、读取文件
  • opencv-contrib-python:包含 LBPH 人脸识别的扩展库
  • numpy:用来处理数组数据,训练模型必须用

3. 准备人脸图片

我们需要两类图片:

  • 训练集(4 张):2 张 A 的照片 + 2 张 B 的照片,用来让算法 “记住” 两个人的脸比如:hg1.pnghg2.png(A 的照片),pyy1.pngpyy2.png(B 的照片)
  • 测试集(1 张):1 张要识别的照片,比如hg.png(A 的新照片)

⚠️ 关键注意事项

  1. 所有图片必须和代码放在同一个文件夹里,避免路径报错
  2. 图片文件名必须和代码里写的完全一致(包括大小写、后缀.png/.jpg)
  3. 尽量用灰度图(或者让代码自动转灰度),人脸尽量居中、清晰,去掉多余背景

四、完整代码:逐行讲解,小白直接复制

下面是完整可运行的代码,我会逐行解释每一步的作用,你直接复制就能用!

python

运行

# 1. 导入需要的库
import cv2  # OpenCV库,用来处理图片、人脸识别
import numpy as np  # NumPy库,用来处理数组数据

# ==============================================
# 2. 准备训练数据:加载训练用的人脸照片
# ==============================================
# 创建一个空列表,用来存所有训练图片
images = []
# 用cv2.imread读取图片,cv2.IMREAD_GRAYSCALE表示以灰度图读取
# 灰度图能减少计算量,提升识别效率
images.append(cv2.imread('hg1.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('hg2.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('pyy1.png', cv2.IMREAD_GRAYSCALE))
images.append(cv2.imread('pyy2.png', cv2.IMREAD_GRAYSCALE))

# ==============================================
# 3. 给训练图片打标签:对应每个人的身份
# ==============================================
# labels列表和images列表一一对应:
# hg1、hg2对应标签0(代表A),pyy1、pyy2对应标签1(代表B)
labels = [0, 0, 1, 1]
# 创建一个字典,把标签转换成我们能看懂的名字
# -1代表无法识别的人脸
dic = {0: 'hg', 1: 'pyy', -1: '无法识别'}

# ==============================================
# 4. 加载待识别的测试图片
# ==============================================
# 读取要识别的图片,同样转成灰度图
predict_image = cv2.imread('hg.png', cv2.IMREAD_GRAYSCALE)

# ==============================================
# 5. 创建LBPH人脸识别器
# ==============================================
# cv2.face.LBPHFaceRecognizer_create() 是OpenCV封装好的LBPH识别器
# threshold=80:设置置信度阈值,超过80就判定为“无法识别”
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)

# ==============================================
# 6. 训练模型:让算法“记住”人脸
# ==============================================
# recognizer.train() 用来训练模型
# 第一个参数是训练图片列表,第二个参数是标签数组(必须用np.array转成数组格式)
recognizer.train(images, np.array(labels))

# ==============================================
# 7. 执行识别:对比特征,输出结果
# ==============================================
# recognizer.predict() 用来识别新图片
# 返回两个值:label(识别到的标签)、confidence(置信度)
label, confidence = recognizer.predict(predict_image)

# ==============================================
# 8. 打印识别结果
# ==============================================
print('这人是:', dic[label])
print('置信度:', confidence)

五、代码运行:常见报错 & 解决方法

1. 最常见报错:can't open/read file: check file path/integrity

报错原因:代码找不到你写的图片文件解决方法

  • 检查图片是否和代码在同一个文件夹
  • 检查文件名是否完全一致(比如hg.png不要写成HG.pnghg.jpg
  • 可以用绝对路径避免问题,比如:

    python

    运行

    predict_image = cv2.imread(r'E:\py_flie\图像拼接\hg.png', cv2.IMREAD_GRAYSCALE)
    
    前面加r是为了避免转义字符问题,直接复制路径即可

2. 报错:cv2.error: OpenCV(3.4.18) ... error: (-215:Assertion failed)

报错原因:图片读取失败(为空),后续识别无法执行解决方法

  • 先加一个图片检查的代码,避免崩溃:

    python

    运行

    if predict_image is None:
        print("错误:无法读取待识别图片,请检查文件路径和文件名!")
        exit()
    
  • 确保图片没有损坏,格式正确(支持 png、jpg、jpeg 等常见格式)

3. 置信度 0.0?是好事!

很多同学运行后会看到:

plaintext

这人是: hg
置信度: 0.0

完全不用担心!这是最完美的结果!

  • LBPH 的置信度规则:数值越小,匹配度越高
  • 0.0 代表待识别图片和训练集中的某张图片完全一模一样,算法 100% 匹配
  • 正常用新照片识别,置信度会在 20~60 之间,超过 80 就会判定为 “无法识别”

六、核心概念详解:置信度到底是什么?

很多小白搞不懂置信度,这里用一张表讲清楚:

表格

置信度数值 含义 状态
0.0 待识别图片和训练图片完全一致 100% 完美匹配
1~70 人脸特征高度相似,匹配成功 正常识别结果
80+ 特征差距大,匹配度低 接近阈值,可能识别错误
触发 - 1 标签 置信度超过 threshold(我们设的 80) 无法识别该人脸

举个例子

  • 你用训练过的hg1.png去识别,置信度就是 0.0(完全一样)
  • 用一张没训练过的hg3.png(A 的新照片)去识别,置信度大概 30 左右(很像)
  • 用一张陌生人的照片去识别,置信度会超过 80,输出 “无法识别”

七、项目优化:让识别更准确、更实用

1. 优化训练数据

  • 每个人的训练照片越多(5~10 张),识别越准确
  • 训练照片尽量包含不同角度、不同光照、不同表情的人脸
  • 统一图片尺寸(比如都 resize 成 200×200),避免尺寸差异影响识别

2. 调整识别阈值

threshold=80是默认推荐值,你可以根据需求调整:

  • 想更严格(不容易认错人):把阈值调低,比如threshold=60
  • 想更宽松(更容易识别):把阈值调高,比如threshold=100

3. 增加人脸检测步骤

现在的代码是直接用人脸照片识别,实际场景中需要先从照片里检测出人脸,再识别:

python

运行

# 加载OpenCV自带的人脸检测分类器
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
# 检测人脸
faces = face_cascade.detectMultiScale(predict_image, 1.1, 4)
# 遍历检测到的人脸,逐个识别
for (x, y, w, h) in faces:
    face_img = predict_image[y:y+h, x:x+w]  # 裁剪出人脸区域
    label, confidence = recognizer.predict(face_img)
    print(f"检测到人脸:{dic[label]},置信度:{confidence}")

4. 保存和加载训练好的模型

训练好的模型可以保存下来,下次不用重新训练:

python

运行

# 保存模型
recognizer.save('lbph_model.yml')
# 加载模型
recognizer.read('lbph_model.yml')

八、写在最后:人脸识别的拓展方向

这个 LBPH 项目是人脸识别的入门级项目,适合新手理解原理,实际应用中还有很多进阶方向:

  1. 深度学习人脸识别:用 FaceNet、MTCNN、ArcFace 等模型,识别准确率更高,适合复杂场景
  2. 实时人脸识别:结合摄像头,实现实时人脸检测 + 识别,比如门禁系统
  3. 多人脸识别:在一张照片里识别多个人的身份
  4. 活体检测:防止用照片、视频冒充人脸,提升安全性

九、完整优化版代码(带错误检查,直接用)

最后给你一个优化后的完整代码,加了错误检查、路径判断,小白直接复制就能跑:

python

运行

import cv2
import numpy as np
import os

# ===================== 配置区:修改这里的文件名和路径 =====================
# 训练图片列表
train_img_names = ['hg1.png', 'hg2.png', 'pyy1.png', 'pyy2.png']
# 对应标签:0=hg,1=pyy
labels = [0, 0, 1, 1]
# 标签对应名字
name_dict = {0: 'hg', 1: 'pyy', -1: '无法识别'}
# 待识别图片
test_img_name = 'hg.png'
# 置信度阈值
threshold = 80
# ======================================================================

# 1. 加载训练图片
images = []
for img_name in train_img_names:
    # 检查图片是否存在
    if not os.path.exists(img_name):
        print(f"错误:训练图片 {img_name} 不存在,请检查文件路径!")
        exit()
    # 读取图片
    img = cv2.imread(img_name, cv2.IMREAD_GRAYSCALE)
    if img is None:
        print(f"错误:无法读取训练图片 {img_name},文件可能损坏!")
        exit()
    images.append(img)

# 2. 加载待识别图片
if not os.path.exists(test_img_name):
    print(f"错误:待识别图片 {test_img_name} 不存在,请检查文件路径!")
    exit()
predict_image = cv2.imread(test_img_name, cv2.IMREAD_GRAYSCALE)
if predict_image is None:
    print(f"错误:无法读取待识别图片 {test_img_name},文件可能损坏!")
    exit()

# 3. 创建LBPH人脸识别器
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=threshold)

# 4. 训练模型
recognizer.train(images, np.array(labels))

# 5. 执行识别
label, confidence = recognizer.predict(predict_image)

# 6. 输出结果
print("="*50)
print(f"识别结果:{name_dict[label]}")
print(f"置信度(越小越匹配):{round(confidence, 2)}")
if confidence > threshold:
    print("提示:置信度超过阈值,识别结果可能不准确!")
print("="*50)

常见问题 Q&A

Q1:为什么我的置信度很高,识别错了?

A:大概率是训练数据太少,或者人脸角度、光照差异太大。增加训练照片数量,统一拍摄环境,就能提升准确率。

Q2:可以识别更多人吗?

A:完全可以!比如要识别 3 个人,就给每个人加 2 张训练照片,标签对应 0、1、2,字典里加对应的名字即可。

Q3:LBPH 和深度学习人脸识别有什么区别?

A:LBPH 是传统机器学习算法,速度快、代码简单,适合小场景、入门学习;深度学习算法准确率更高,适合复杂场景,但需要更多数据和算力。


如果你跟着教程跑通了,或者遇到了其他问题,欢迎在评论区留言交流!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐