人脸识别是计算机视觉领域最经典、最实用的应用之一。OpenCV 提供了三种开箱即用的传统人脸识别算法:LBPH 、EigenFace 、FisherFace,无需复杂训练、无需 GPU,仅用少量样本就能实现精准识别。
本文将通过四段循序渐进的代码 ,从最基础的静态识别,一步步升级到实时摄像头人脸识别,每段代码都保留原貌并详细解释,带你从零掌握 OpenCV 人脸识别全流程。
一、基础入门:LBPH 人脸识别(最简单、无需固定尺寸)
LBPH(Local Binary Patterns Histogram)是 OpenCV 最易用的人脸识别算法,不要求图片尺寸一致,对光照适应性强,适合入门。
python
import cv2
import numpy as np
# 1. 加载训练图片(灰度图)
images = []
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))
# 2. 设置标签:0=胡歌,1=彭于晏
labels=[0,0,1,1]
dic={0:'hg',1:'pyy',-1:'无法识别'}
# 3. 加载待预测图片
predict_image=cv2.imread('hg.png',cv2.IMREAD_GRAYSCALE)
# 4. 创建LBPH识别器并训练
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)
recognizer.train(images,np.array(labels))
# 5. 预测并输出结果
label,confidence = recognizer.predict(predict_image)
print('这人是:',dic[label])
print('置信度:',confidence)
运行结果:

1.加载图片:使用灰度模式读取训练样本,人脸识别无需彩色信息
-
标签设置:同一人物使用相同数字标签(0、1)
-
LBPH 识别器:threshold=80 表示置信度大于 80 则判定为无法识别
-
训练与预测:train() 训练模型,predict() 返回预测标签与置信度
-
置信度:数值越小表示匹配度越高
二、进阶一:EigenFace 人脸识别(固定尺寸 + 可视化标注)
EigenFace(特征脸)是基于 PCA 降维的经典算法,必须统一所有图片尺寸,速度极快。
代码实现
python
import cv2
import numpy as np
# 1. 统一图片尺寸为20x30(EigenFace必须固定大小)
images=[]
a = cv2.imread('hg1.png',0)
a = cv2.resize(a,(20,30))
b = cv2.imread('hg2.png',0)
b = cv2.resize(b,(20,30))
c = cv2.imread('pyy1.png',0)
c = cv2.resize(c,(20,30))
d = cv2.imread('pyy2.png',0)
d = cv2.resize(d,(20,30))
images.append(a)
images.append(b)
images.append(c)
images.append(d)
labels=[0,0,1,1]
# 2. 待预测图片同样缩放到20x30
pre_image = cv2.imread('hg.png',0)
pre_image = cv2.resize(pre_image,(20,30))
# 3. 创建并训练EigenFace识别器
recognizer = cv2.face.EigenFaceRecognizer_create(threshold=5000)
recognizer.train(images,np.array(labels))
# 4. 预测
label,confidence = recognizer.predict(pre_image)
dic ={0:'hg',1:'pyy',-1:'无法识别'}
print('这人是:',dic[label])
print('置信度:',confidence)
# 5. 可视化:在图片上标注识别结果
aa=cv2.putText(cv2.imread('hg.png').copy(),dic[label],(10,30),cv2.FONT_HERSHEY_SIMPLEX,
0.9,(0,0,255),2)
cv2.imshow('xx',aa)
cv2.waitKey(0)
1.尺寸统一:EigenFace 强制要求所有图片大小相同,使用 resize() 统一尺寸
-
阈值设置:threshold=5000 区分识别成功 / 失败
-
可视化标注:cv2.putText() 在图片上显示识别结果
-
窗口显示:imshow() 展示标注后的图片,waitKey() 保持窗口
运行结果:


三、进阶二:FisherFace 人脸识别(中文显示 + 函数封装)
FisherFace 基于 LDA 算法,识别精度比 EigenFace 更高,解决了 OpenCV 不能显示中文的问题。
python
import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageFont
# 中文显示函数(解决OpenCV无法写中文的问题)
def cv2AddChineseText(img,text,position,textColor=(0,255,0),textSize=30):
if (isinstance(img,np.ndarray)):
img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
fontStyle = ImageFont.truetype("simsun.ttc",textSize,encoding="utf-8")
draw.text(position,text,textColor,font=fontStyle)
return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)
# 图片预处理函数(统一尺寸)
def image_re(image):
a = cv2.imread(image,0)
a = cv2.resize(a,(120,180))
images.append(a)
# 加载训练集
images=[]
image_re('hg1.png')
image_re('hg2.png')
image_re('pyy1.png')
image_re('pyy2.png')
labels=[0,0,1,1]
# 预处理测试图片
pre_image = cv2.imread('hg.png',0)
pre_image = cv2.resize(pre_image,(120,180))
# 训练FisherFace识别器
recognizer=cv2.face.FisherFaceRecognizer_create(threshold =5000)
recognizer.train(images,np.array(labels))
# 预测
label,confidence=recognizer.predict(pre_image)
dic ={0:'胡歌',1:'彭于晏',-1:'无法识别'}
print('这人是:',dic[label])
print('置信度为:',confidence)
# 中文标注并显示
image = cv2AddChineseText(cv2.imread('hg.png').copy(),dic[label],(30,10),textColor=(255,0,0))
cv2.imshow('xx',image)
cv2.waitKey(0)
运行结果:
中文显示函数:使用 PIL 库实现中文文字绘制,完美解决 OpenCV 中文乱码
-
函数封装:image_re() 简化图片加载 + 缩放流程,代码更简洁
-
FisherFace 算法:精度最优,适合小样本人脸识别
-
中文标签:直接显示 "胡歌""彭于晏",更直观
四、终极实战:实时摄像头人脸识别(最终版)
结合 Haar 人脸检测 + FisherFace 识别,实现摄像头实时检测、实时识别、中文标注、人脸框选。
python
import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageFont
# 中文显示函数
def cv2AddChineseText(img,text,position,textColor=(0,255,0),textSize=30):
if (isinstance(img,np.ndarray)):
img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
fontStyle = ImageFont.truetype("simsun.ttc",textSize,encoding="utf-8")
draw.text(position,text,textColor,font=fontStyle)
return cv2.cvtColor(np.asarray(img),cv2.COLOR_BGR2RGB)
# 图片预处理函数
def image_re(image):
a = cv2.imread(image,0)
a = cv2.resize(a,(120,180))
images.append(a)
# 加载自定义训练集
images=[]
image_re('pdd1.png')
image_re('pdd2.png')
image_re('pdd3.png')
image_re('yll1.png')
image_re('yll2.png')
image_re('yll3.png')
labels=[0,0,0,1,1,1]
dic ={0:'庞丹丹',1:'杨璐璐',-1:'无法识别'}
# 训练FisherFace
recognizer=cv2.face.FisherFaceRecognizer_create(threshold =5000)
recognizer.train(images,np.array(labels))
# 打开摄像头
cap = cv2.VideoCapture(0)
# 加载人脸检测器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
while True:
ret,frame=cap.read()
frame = cv2.flip(frame,flipCode=1) # 镜像翻转
if ret is None: break
# 转灰度图
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# 检测人脸
face = face_cascade.detectMultiScale(gray,1.1,10)
try:
for (x,y,w,h) in face:
# 裁剪人脸区域
pre_image = gray[y - 20:y + h + 20, x - 10:x + w + 10]
# 缩放并识别
pre_image = cv2.resize(pre_image, (120, 180))
label, confidence = recognizer.predict(pre_image)
# 画框+中文标注
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
frame = cv2AddChineseText(frame, dic[label], position=(x, y - 30), textColor=(0, 255, 0))
except:
pass
# 显示画面
cv2.imshow('摄像头人脸识别', frame)
# ESC退出
if cv2.waitKey(1) == 27: break
cap.release()
cv2.destroyAllWindows()
1.自定义数据集:可替换为自己的照片,实现专属人脸识别
-
摄像头调用:VideoCapture(0) 打开默认摄像头
-
Haar 人脸检测:自动定位画面中的人脸位置
-
实时识别:每一帧画面都进行检测→裁剪→识别→标注
-
交互退出:按 ESC 键关闭程序
-
异常处理:try-except 避免无人脸时程序崩溃
运行结果:
