Python 人脸识别入门实践:从人脸检测到人脸比对完整实现
一、什么是人脸识别?
人脸识别,简单来说,就是让计算机判断一张图片或视频中的人脸是谁。
它通常包括两个层面的任务:
text
人脸检测:判断图像中有没有人脸,并找出人脸位置
人脸识别:判断检测到的人脸属于谁
例如,在一张图片中,程序可以完成以下工作:
text
输入图片
↓
检测图片中的人脸位置
↓
提取人脸特征
↓
和已知人脸进行比对
↓
输出识别结果
所以,人脸识别并不是简单地"看见脸",而是要进一步判断"这张脸是谁"。
二、人脸检测和人脸识别的区别
很多小白刚开始学习时,会把"人脸检测"和"人脸识别"混在一起。
其实它们不是一回事。
| 对比项 | 人脸检测 | 人脸识别 |
|---|---|---|
| 目标 | 找出图像中的人脸位置 | 判断人脸属于谁 |
| 输出结果 | 人脸框坐标 | 人名或身份 |
| 难度 | 相对较低 | 相对较高 |
| 示例 | 图片中有几张脸 | 这张脸是不是张三 |
举个例子:
text
人脸检测:这张图片里有一张人脸,位置在左上角。
人脸识别:这张人脸是张三。
完整的人脸识别系统通常要先做人脸检测,再做人脸识别。
三、人脸识别的基本流程
一个基础的人脸识别系统一般包括以下步骤:
text
准备已知人脸图片
↓
提取已知人脸特征
↓
读取待识别图片
↓
检测待识别图片中的人脸
↓
提取待识别人脸特征
↓
计算两张人脸特征的相似度
↓
输出识别结果
可以理解为:
text
先把"标准答案"存起来
再拿新图片和标准答案进行比较
最后判断是不是同一个人
四、环境准备
本文使用 Python 实现基础人脸识别功能,需要安装以下库:
bash
pip install opencv-python
pip install face_recognition
如果安装 face_recognition 时遇到问题,通常是因为它依赖 dlib,部分电脑需要先安装 CMake:
bash
pip install cmake
pip install dlib
pip install face_recognition
如果是在 Windows 环境中,安装 dlib 可能会比较麻烦,可以优先使用 Anaconda 或者搜索对应 Python 版本的 whl 文件安装。
五、使用 OpenCV 实现人脸检测
首先,我们用 OpenCV 完成最基础的人脸检测。
1. 准备图片
假设项目目录中有一张图片:
text
test.jpg
2. 编写人脸检测代码
python
import cv2
# 读取图片
image = cv2.imread("test.jpg")
if image is None:
print("图片读取失败,请检查图片路径")
exit()
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 加载 OpenCV 自带的人脸检测模型
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
# 检测人脸
faces = face_cascade.detectMultiScale(
gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30)
)
# 绘制人脸框
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 输出检测到的人脸数量
print("检测到的人脸数量:", len(faces))
# 显示结果
cv2.imshow("Face Detection", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
运行后,程序会在图片中的人脸区域画出绿色矩形框。
六、OpenCV 人脸检测代码解析
1. 读取图片
python
image = cv2.imread("test.jpg")
用于读取本地图片。
2. 转换灰度图
python
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
很多传统图像检测算法会先把彩色图片转换为灰度图,这样可以减少计算量。
3. 加载人脸检测器
python
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
这里使用的是 OpenCV 自带的 Haar 人脸检测模型,适合小白入门。
4. 检测人脸
python
faces = face_cascade.detectMultiScale(gray)
检测结果中包含每张人脸的位置。
每个人脸框包括:
text
x, y, w, h
含义分别是:
| 参数 | 含义 |
|---|---|
| x | 人脸框左上角 x 坐标 |
| y | 人脸框左上角 y 坐标 |
| w | 人脸框宽度 |
| h | 人脸框高度 |
七、使用摄像头进行实时人脸检测
除了检测图片,也可以调用摄像头进行实时检测。
python
import cv2
# 打开摄像头
cap = cv2.VideoCapture(0)
# 加载人脸检测模型
face_cascade = cv2.CascadeClassifier(
cv2.data.haarcascades + "haarcascade_frontalface_default.xml"
)
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=(30, 30)
)
# 绘制人脸框
for (x, y, w, h) in faces:
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示画面
cv2.imshow("Real-time Face Detection", frame)
# 按 q 退出
if cv2.waitKey(1) & 0xFF == ord("q"):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
其中:
python
cv2.VideoCapture(0)
表示调用电脑默认摄像头。
如果有多个摄像头,可以尝试:
python
cv2.VideoCapture(1)
cv2.VideoCapture(2)
八、使用 face_recognition 实现人脸识别
OpenCV 上面的代码主要完成的是"人脸检测",也就是找到人脸在哪里。
如果想判断"这个人是谁",可以使用 face_recognition 库。
假设我们有两张图片:
text
known.jpg # 已知人物照片
unknown.jpg # 待识别人物照片
代码如下:
python
import face_recognition
# 加载已知人脸图片
known_image = face_recognition.load_image_file("known.jpg")
# 加载待识别人脸图片
unknown_image = face_recognition.load_image_file("unknown.jpg")
# 提取已知人脸特征
known_encodings = face_recognition.face_encodings(known_image)
# 提取待识别人脸特征
unknown_encodings = face_recognition.face_encodings(unknown_image)
# 判断是否检测到人脸
if len(known_encodings) == 0:
print("已知图片中没有检测到人脸")
exit()
if len(unknown_encodings) == 0:
print("待识别图片中没有检测到人脸")
exit()
# 获取第一张人脸的特征
known_encoding = known_encodings[0]
unknown_encoding = unknown_encodings[0]
# 人脸比对
results = face_recognition.compare_faces(
[known_encoding],
unknown_encoding,
tolerance=0.6
)
# 输出结果
if results[0]:
print("识别结果:是同一个人")
else:
print("识别结果:不是同一个人")
九、人脸识别代码解析
1. 加载图片
python
known_image = face_recognition.load_image_file("known.jpg")
unknown_image = face_recognition.load_image_file("unknown.jpg")
分别加载已知图片和待识别图片。
2. 提取人脸特征
python
known_encodings = face_recognition.face_encodings(known_image)
unknown_encodings = face_recognition.face_encodings(unknown_image)
face_encodings 会把人脸转换成一组特征向量。
可以简单理解为:
text
把一张人脸转换成一串数字
后续程序就是通过比较这串数字来判断两张脸是否相似。
3. 人脸比对
python
results = face_recognition.compare_faces(
[known_encoding],
unknown_encoding,
tolerance=0.6
)
tolerance 表示容忍度。
一般来说:
| tolerance | 说明 |
|---|---|
| 0.4 | 更严格,误识别更少,但可能漏识别 |
| 0.6 | 默认值,比较常用 |
| 0.8 | 更宽松,容易识别成功,但误识别风险更高 |
小白入门阶段可以先使用:
python
tolerance=0.6
十、识别多个人脸
如果一张图片中有多个人脸,可以循环处理。
python
import face_recognition
# 加载已知人脸
known_image = face_recognition.load_image_file("known.jpg")
known_encodings = face_recognition.face_encodings(known_image)
if len(known_encodings) == 0:
print("已知图片中没有检测到人脸")
exit()
known_encoding = known_encodings[0]
# 加载待识别图片
unknown_image = face_recognition.load_image_file("unknown.jpg")
# 获取待识别图片中所有人脸位置
face_locations = face_recognition.face_locations(unknown_image)
# 获取所有人脸特征
face_encodings = face_recognition.face_encodings(unknown_image, face_locations)
print("检测到人脸数量:", len(face_encodings))
for index, face_encoding in enumerate(face_encodings):
result = face_recognition.compare_faces(
[known_encoding],
face_encoding,
tolerance=0.6
)
if result[0]:
print(f"第 {index + 1} 张人脸:匹配成功")
else:
print(f"第 {index + 1} 张人脸:不是目标人物")
十一、给识别结果画框并显示姓名
下面这个例子会在图片中画出人脸框,并标注识别结果。
python
import cv2
import face_recognition
# 加载已知人脸
known_image = face_recognition.load_image_file("known.jpg")
known_encodings = face_recognition.face_encodings(known_image)
if len(known_encodings) == 0:
print("已知图片中没有检测到人脸")
exit()
known_encoding = known_encodings[0]
known_name = "Zhang San"
# 加载待识别图片
image = face_recognition.load_image_file("unknown.jpg")
# 检测人脸位置和特征
face_locations = face_recognition.face_locations(image)
face_encodings = face_recognition.face_encodings(image, face_locations)
# 转换颜色格式,便于 OpenCV 显示
image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
for face_location, face_encoding in zip(face_locations, face_encodings):
top, right, bottom, left = face_location
matches = face_recognition.compare_faces(
[known_encoding],
face_encoding,
tolerance=0.6
)
if matches[0]:
name = known_name
else:
name = "Unknown"
# 绘制人脸框
cv2.rectangle(image_bgr, (left, top), (right, bottom), (0, 255, 0), 2)
# 绘制姓名背景
cv2.rectangle(image_bgr, (left, bottom - 30), (right, bottom), (0, 255, 0), -1)
# 写入姓名
cv2.putText(
image_bgr,
name,
(left + 6, bottom - 8),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(255, 255, 255),
2
)
# 显示结果
cv2.imshow("Face Recognition", image_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()
十二、识别多个人物
如果要识别多个人物,可以准备多张已知人脸图片。
假设有:
text
known_faces/
├── zhangsan.jpg
├── lisi.jpg
└── wangwu.jpg
可以这样写:
python
import face_recognition
import os
known_face_encodings = []
known_face_names = []
known_faces_dir = "known_faces"
for filename in os.listdir(known_faces_dir):
if filename.endswith(".jpg") or filename.endswith(".png"):
image_path = os.path.join(known_faces_dir, filename)
image = face_recognition.load_image_file(image_path)
encodings = face_recognition.face_encodings(image)
if len(encodings) > 0:
known_face_encodings.append(encodings[0])
# 使用文件名作为姓名
name = os.path.splitext(filename)[0]
known_face_names.append(name)
print("已加载人脸数量:", len(known_face_encodings))
print("已加载人物姓名:", known_face_names)
这样就可以把文件夹中的人脸批量加载进来。
十三、完整人脸识别项目代码
下面是一份相对完整的人脸识别代码,可以识别多个人物,并在图片上标注姓名。
项目目录结构:
text
face_project/
├── known_faces/
│ ├── zhangsan.jpg
│ ├── lisi.jpg
│ └── wangwu.jpg
├── test.jpg
└── main.py
完整代码如下:
python
import cv2
import face_recognition
import os
# 存储已知人脸特征和姓名
known_face_encodings = []
known_face_names = []
# 已知人脸文件夹
known_faces_dir = "known_faces"
# 加载已知人脸
for filename in os.listdir(known_faces_dir):
if filename.lower().endswith((".jpg", ".jpeg", ".png")):
image_path = os.path.join(known_faces_dir, filename)
image = face_recognition.load_image_file(image_path)
encodings = face_recognition.face_encodings(image)
if len(encodings) > 0:
known_face_encodings.append(encodings[0])
name = os.path.splitext(filename)[0]
known_face_names.append(name)
else:
print(f"警告:{filename} 中没有检测到人脸")
print("已加载人脸数量:", len(known_face_encodings))
# 读取待识别图片
image = face_recognition.load_image_file("test.jpg")
# 检测人脸位置
face_locations = face_recognition.face_locations(image)
# 提取人脸特征
face_encodings = face_recognition.face_encodings(image, face_locations)
# 转换为 OpenCV 可显示的 BGR 格式
image_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
# 遍历检测到的人脸
for face_location, face_encoding in zip(face_locations, face_encodings):
top, right, bottom, left = face_location
# 默认未知
name = "Unknown"
# 与已知人脸进行比对
matches = face_recognition.compare_faces(
known_face_encodings,
face_encoding,
tolerance=0.6
)
# 如果有匹配结果
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
# 绘制人脸框
cv2.rectangle(image_bgr, (left, top), (right, bottom), (0, 255, 0), 2)
# 绘制姓名背景
cv2.rectangle(image_bgr, (left, bottom - 30), (right, bottom), (0, 255, 0), -1)
# 显示姓名
cv2.putText(
image_bgr,
name,
(left + 6, bottom - 8),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(255, 255, 255),
2
)
# 保存结果
cv2.imwrite("result.jpg", image_bgr)
# 显示结果
cv2.imshow("Face Recognition Result", image_bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()
十四、摄像头实时人脸识别
如果要使用摄像头进行实时人脸识别,可以参考下面代码。
python
import cv2
import face_recognition
import os
known_face_encodings = []
known_face_names = []
known_faces_dir = "known_faces"
# 加载已知人脸
for filename in os.listdir(known_faces_dir):
if filename.lower().endswith((".jpg", ".jpeg", ".png")):
image_path = os.path.join(known_faces_dir, filename)
image = face_recognition.load_image_file(image_path)
encodings = face_recognition.face_encodings(image)
if len(encodings) > 0:
known_face_encodings.append(encodings[0])
known_face_names.append(os.path.splitext(filename)[0])
# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
print("摄像头读取失败")
break
# OpenCV 读取的是 BGR,face_recognition 使用 RGB
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 检测人脸位置
face_locations = face_recognition.face_locations(rgb_frame)
# 提取人脸特征
face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
for face_location, face_encoding in zip(face_locations, face_encodings):
top, right, bottom, left = face_location
name = "Unknown"
matches = face_recognition.compare_faces(
known_face_encodings,
face_encoding,
tolerance=0.6
)
if True in matches:
first_match_index = matches.index(True)
name = known_face_names[first_match_index]
# 绘制人脸框
cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2)
# 绘制姓名背景
cv2.rectangle(frame, (left, bottom - 30), (right, bottom), (0, 255, 0), -1)
# 显示姓名
cv2.putText(
frame,
name,
(left + 6, bottom - 8),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(255, 255, 255),
2
)
cv2.imshow("Real-time Face Recognition", frame)
# 按 q 退出
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
十五、人脸识别常见问题
1. 为什么识别不到人脸?
可能原因有:
- 图片太模糊;
- 人脸太小;
- 光线太暗;
- 人脸角度太偏;
- 人脸被遮挡;
- 图片路径错误;
- 图片中没有正面人脸。
2. 为什么识别结果不准确?
可能原因有:
- 已知人脸图片太少;
- 已知图片和待识别图片差异太大;
- 人脸表情变化明显;
- 光照变化太大;
- 人脸被帽子、口罩、眼镜遮挡;
- tolerance 参数设置不合理。
3. 如何提高识别准确率?
可以从以下几个方面优化:
text
使用更清晰的已知人脸图片
每个人准备多张不同角度的人脸图片
保证光线充足
尽量使用正脸图片
适当调整 tolerance 参数
避免使用严重遮挡的人脸图片
4. 为什么摄像头运行很卡?
可能原因有:
- 电脑性能不足;
- 摄像头分辨率太高;
- 每一帧都做人脸识别计算量较大;
- 同时识别的人脸数量太多。
可以尝试降低分辨率:
python
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
十六、人脸识别的应用场景
人脸识别可以应用在很多实际项目中。
1. 门禁系统
通过摄像头识别人脸,实现刷脸开门。
2. 考勤系统
通过人脸识别判断员工或学生是否到场。
3. 相册分类
根据人脸自动对照片进行分类。
4. 智慧安防
用于人员识别、陌生人检测、重点区域监控等场景。
5. 登录验证
在部分系统中,可以使用人脸作为身份验证方式。
十七、人脸识别项目开发注意事项
人脸识别属于生物特征识别技术,在实际项目中需要特别注意隐私和数据安全。
开发时建议注意以下几点:
- 采集人脸数据前应取得用户授权;
- 不要随意上传他人人脸照片;
- 不要把人脸数据公开到网络;
- 人脸数据应加密存储;
- 项目中应明确告知用户数据用途;
- 不要将人脸识别用于违法、侵犯隐私或未经授权的场景。
技术可以提高效率,但必须在合法、合规、尊重隐私的前提下使用。
十八、本文总结
本文介绍了 Python 人脸识别的基础知识和实现方法,主要包括:
text
人脸检测与人脸识别的区别
OpenCV 实现人脸检测
face_recognition 实现人脸比对
多人物人脸识别
摄像头实时人脸识别
常见问题和优化方法
对于初学者来说,建议按照下面的顺序学习:
text
先理解人脸检测
再学习人脸特征提取
然后实现两张图片比对
最后实现多人脸识别和摄像头实时识别
人脸识别是计算机视觉中的经典应用,也是很多课程设计、毕业设计和项目实战中常见的方向。掌握本文中的基础代码后,可以进一步扩展为刷脸考勤系统、门禁系统、人脸登录系统以及 Web 可视化识别平台。