使用Python做的一个简单的人脸识别项目
使用Python做的一个简单的人脸识别项目
最近在学习使用使用python来学习OpenCV,验证其相关的算法。因为平时接触到人脸打卡,于是想着能否用Python和OpenCV来实现一个简单的人脸识别项目。代码由豆包生成。
一、知识点概述
人脸识别是计算机视觉的经典应用场景,OpenCV 作为开源的计算机视觉库,提供了成熟的人脸检测与识别工具链。本次笔记聚焦于基于 OpenCV 的人脸检测(Haar 级联分类器) + 人脸识别(LBPH 算法) 完整实现,从原理、步骤到代码全覆盖,适合入门学习与实战。
核心概念
- 人脸检测:定位图像中人脸的位置(坐标 + 尺寸),是识别的前提;
- 人脸识别:将检测到的人脸与已知人脸库匹配,确定身份;
- ROI(感兴趣区域):截取人脸区域单独处理,提升效率与精度。
二、核心原理说明
1. 人脸检测:Haar 级联分类器
- 原理:基于 Haar 特征(边缘、纹理、对比度等),通过 Adaboost 算法筛选出关键特征,再用级联分类器快速排除非人脸区域,最终定位人脸。
- 优势:速度快、无需训练,OpenCV 内置预训练模型(
haarcascade_frontalface_default.xml),开箱即用; - 适用场景:正面人脸检测(对侧脸 / 遮挡鲁棒性较弱)。
2. 人脸识别:LBPH(局部二值模式直方图)算法
- 原理
- 对人脸灰度图提取 LBP 特征(将每个像素与周围像素比较,生成二进制编码);
- 将人脸分块,统计每块的 LBP 特征直方图,拼接成整个人脸的特征向量;
- 计算待识别人脸与已知人脸的特征向量相似度,匹配身份。
- 优势
- 对光照变化、小角度旋转鲁棒;
- 无需大量样本,单张人脸即可训练;
- 支持动态更新人脸库。
三、详细操作步骤

步骤 1:环境准备
-
安装 OpenCV:
本人已经通过清华的镜像安装了如下库:使用的python解释器版本是python3.12
![ScreenShot_2026-03-22_135300_791]()
清华镜像地址:清华镜像地址
全局永久配置(所有项目生效)的操作是:
在系统终端或 PyCharm Terminal 执行
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
步骤2:项目结构
face_recognition_project/ # 项目根目录
├─ data/ # 数据文件夹
│ ├─ raw_faces/ # 原始人脸图片(手动放)
│ │ ├─ zhangsan/ # 张三的人脸图片(5-10张)
│ │ └─ lisi/ # 李四的人脸图片(5-10张)
│ └─ processed_faces/ # 自动生成的人脸ROI(运行代码后生成)
├─ model/ # 模型文件夹(自动生成)
│ ├─ face_recognizer.yml # 训练好的LBPH模型
│ └─ label_map.npy # 标签映射文件
├─ modules/ # 功能模块文件夹(放拆分的代码)
│ ├─ data_preprocess.py # 人脸ROI提取代码
│ ├─ model_train.py # 模型训练代码
│ └─ realtime_recognize.py# 实时识别代码
└─ main.py # 主运行文件(核心入口)
如图所示:

2.1 拆分代码到对应模块
1.modules/data_preprocess.py(人脸 ROI 提取)
import cv2
import os
import numpy as np
# 核心修改:获取项目根目录的绝对路径(适配main.py的位置)
# 因为data_preprocess.py在modules里,所以要回退一级到项目根目录
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 绝对路径配置(再也不会错!)
RAW_FACE_PATH = os.path.join(BASE_DIR, "data", "raw_faces")
PROCESSED_FACE_PATH = os.path.join(BASE_DIR, "data", "processed_faces")
# 确保文件夹存在(即使没创建,代码也会自动建)
os.makedirs(PROCESSED_FACE_PATH, exist_ok=True)
os.makedirs(RAW_FACE_PATH, exist_ok=True) # 新增:自动创建raw_faces
# 加载人脸检测器
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
def extract_face_roi(img_path, save_path, person_name):
"""提取单张图片的人脸ROI"""
img = cv2.imread(img_path)
if img is None:
print(f"跳过无效图片:{img_path}")
return
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)
)
for i, (x, y, w, h) in enumerate(faces):
face_roi = gray[y:y + h, x:x + w]
face_roi = cv2.resize(face_roi, (100, 100)) # 统一尺寸
roi_save_path = os.path.join(save_path, f"{person_name}_{i}.jpg")
cv2.imwrite(roi_save_path, face_roi)
print(f"保存ROI:{roi_save_path}")
def batch_extract():
"""批量处理原始人脸数据"""
# 先检查raw_faces是否为空
if not os.listdir(RAW_FACE_PATH):
print("警告:data/raw_faces 文件夹为空!请先放入人脸图片文件夹(如zhangsan/)")
return
for person_dir in os.listdir(RAW_FACE_PATH):
person_raw_path = os.path.join(RAW_FACE_PATH, person_dir)
if not os.path.isdir(person_raw_path):
continue
# 创建人物的ROI保存目录
person_processed_path = os.path.join(PROCESSED_FACE_PATH, person_dir)
os.makedirs(person_processed_path, exist_ok=True)
# 处理该人物的所有图片
for img_name in os.listdir(person_raw_path):
img_path = os.path.join(person_raw_path, img_name)
extract_face_roi(img_path, person_processed_path, person_dir)
# 测试用(单独运行该文件时执行)
if __name__ == "__main__":
batch_extract()
print("ROI提取完成!")
2.modules/model_train.py(模型训练)
import cv2
import os
import numpy as np
# 核心修改:绝对路径配置
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROCESSED_FACE_PATH = os.path.join(BASE_DIR, "data", "processed_faces")
MODEL_SAVE_PATH = os.path.join(BASE_DIR, "model", "face_recognizer.yml")
LABEL_MAP_PATH = os.path.join(BASE_DIR, "model", "label_map.npy")
def train_model():
"""训练LBPH人脸识别模型"""
# 检查processed_faces是否有数据
if not os.path.exists(PROCESSED_FACE_PATH) or not os.listdir(PROCESSED_FACE_PATH):
print("警告:没有提取到人脸ROI!请先运行步骤1提取ROI")
return
faces = []
labels = []
label_map = {}
current_label = 0
# 加载处理后的人脸数据
for person_dir in os.listdir(PROCESSED_FACE_PATH):
person_path = os.path.join(PROCESSED_FACE_PATH, person_dir)
if not os.path.isdir(person_path):
continue
label_map[person_dir] = current_label # 人名→数字标签
for img_name in os.listdir(person_path):
img_path = os.path.join(person_path, img_name)
face = cv2.imread(img_path, 0) # 灰度图读取
faces.append(face)
labels.append(current_label)
current_label += 1
# 转换为numpy数组
faces = np.array(faces)
labels = np.array(labels)
# 初始化并训练LBPH识别器
recognizer = cv2.face.LBPHFaceRecognizer_create(
radius=1, neighbors=8, grid_x=8, grid_y=8
)
recognizer.train(faces, labels)
# 保存模型和标签映射
os.makedirs(os.path.join(BASE_DIR, "model"), exist_ok=True)
recognizer.save(MODEL_SAVE_PATH)
np.save(LABEL_MAP_PATH, label_map)
print(f"模型保存至:{MODEL_SAVE_PATH}")
print(f"标签映射:{label_map}")
return recognizer, label_map
# 测试用
if __name__ == "__main__":
train_model()
print("模型训练完成!")
3.modules/realtime_recognize.py(实时识别)
import cv2
import numpy as np
import os
# 核心修改:绝对路径配置
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MODEL_PATH = os.path.join(BASE_DIR, "model", "face_recognizer.yml")
LABEL_MAP_PATH = os.path.join(BASE_DIR, "model", "label_map.npy")
def realtime_recognize():
"""实时人脸识别"""
# 加载模型和标签映射
if not os.path.exists(MODEL_PATH) or not os.path.exists(LABEL_MAP_PATH):
print("错误:未找到训练好的模型!请先运行模型训练步骤。")
return
recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read(MODEL_PATH)
label_map = np.load(LABEL_MAP_PATH, allow_pickle=True).item()
reverse_label_map = {v: k for k, v in label_map.items()} # 数字→人名
# 加载人脸检测器
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
# 打开摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
print("实时识别中,按'q'退出...")
while True:
ret, frame = cap.read()
if not ret:
print("摄像头读取失败!")
break
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=5, minSize=(50, 50)
)
# 识别每一个检测到的人脸
for (x, y, w, h) in faces:
face_roi = gray[y:y + h, x:x + w]
face_roi = cv2.resize(face_roi, (100, 100)) # 与训练数据尺寸一致
# 预测(标签,置信度)
label, confidence = recognizer.predict(face_roi)
# 判断识别结果
if confidence < 120: # 先改成120,让它认出你
person_name = reverse_label_map[label]
text = f"{person_name} (置信度:{confidence:.1f})"
color = (0, 255, 0) # 绿色框
else:
text = "?????? (%.1f)" % confidence
color = (0, 0, 255)
# 绘制框和文字
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
cv2.rectangle(frame, (x, y - 30), (x + len(text) * 10, y), color, -1)
cv2.putText(
frame, text, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2
)
cv2.imshow("Real-Time Face Recognition", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
# 测试用
if __name__ == "__main__":
realtime_recognize()
2.2 创建主入口文件(main.py)
import sys
import os
# 将modules目录加入Python路径(确保能导入模块)
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(BASE_DIR, "modules"))
from data_preprocess import batch_extract
from model_train import train_model
from realtime_recognize import realtime_recognize
def main():
print("===== 人脸识别项目 =====")
print("1. 提取人脸ROI")
print("2. 训练识别模型")
print("3. 实时人脸识别")
print("4. 运行全流程(1→2→3)")
choice = input("请输入选择(1/2/3/4):")
if choice == "1":
print("\n开始提取人脸ROI...")
batch_extract()
print("ROI提取完成!")
elif choice == "2":
print("\n开始训练模型...")
train_model()
print("模型训练完成!")
elif choice == "3":
print("\n启动实时识别...")
realtime_recognize()
elif choice == "4":
print("\n=== 运行全流程 ===")
print("步骤1:提取ROI...")
batch_extract()
print("步骤2:训练模型...")
train_model()
print("步骤3:启动实时识别...")
realtime_recognize()
else:
print("输入错误!请输入1-4。")
if __name__ == "__main__":
main()
提示:
需要子在data/raw_faces下创建以人名命名的文件夹(如zhangsan),放入 5-10 张该人的正面人脸图片;
如下图:

代码运行结果如下:

好了项目介绍就到这里了。


浙公网安备 33010602011771号