文章目录
一、静态图像人脸检测
OpenCV提供了基于Haar特征的人脸检测器,可以快速在静态图片中定位人脸位置:
python
import cv2
# 读取图像并转换为灰度图
image = cv2.imread('people.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 加载预训练的人脸检测分类器
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 检测人脸
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.05, minNeighbors=15, minSize=(8, 8))
print("发现{}张人脸!".format(len(faces)))
print("其位置分别是:", faces)
# 在原图上绘制矩形框标记人脸
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 显示结果
cv2.imshow("result", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键参数解析:
- scaleFactor=1.05:图像金字塔的缩放比例。值越小检测越精细但速度越慢,值越大检测越快但可能漏检
- minNeighbors=15:每个候选矩形应该保留的邻近矩形数量。值越高误检越少,但可能漏掉真实人脸
- minSize=(8, 8):检测目标的最小尺寸,过滤掉过小的误检区域
二、实时视频流人脸检测
将上述技术应用到摄像头实时视频流中:
python
import cv2
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# 打开摄像头(0表示默认摄像头)
cap = cv2.VideoCapture(0)
while True:
ret, image = cap.read()
if not ret:
break
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.05, minNeighbors=15, minSize=(8, 8))
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.imshow("Face Detection", image)
# 按ESC键退出
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()

三、人脸与微笑检测结合
在检测人脸的基础上,进一步识别面部表情(微笑):
python
import cv2
faceCascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
smile = cv2.CascadeClassifier("haarcascade_smile.xml")
cap = cv2.VideoCapture(0)
while True:
ret, image = cap.read()
image = cv2.flip(image, 1) # 水平翻转,让画面像镜子一样
if ret is None:
break
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=15, minSize=(5, 5))
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 提取人脸区域(ROI)
roi_grayscale = gray[y:y + h, x:x + w]
cv2.imshow('Face', roi_grayscale)
# 在人脸区域内检测微笑
smiles = smile.detectMultiScale(roi_grayscale, scaleFactor=1.5, minNeighbors=25, minSize=(50, 50))
for (sx, sy, sw, sh) in smiles:
a = x + sx # 转换回原图坐标系
b = y + sy
cv2.rectangle(image, (a, b), (a + sw, b + sh), (255, 0, 0), 2)
cv2.putText(image, "smile", (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0, 255, 255), 2)
cv2.imshow('Face and Smile Detection', image)
key = cv2.waitKey(25)
if key == 27: # ESC键退出
break
cap.release()
cv2.destroyAllWindows()

微笑检测参数说明:
- scaleFactor=1.5:相对较大的缩放比例,因为微笑特征比人脸特征变化小
- minNeighbors=25:较高的阈值,减少误将其他表情识别为微笑
- minSize=(50, 50):限定最小微笑区域,避免检测到过小的纹理变化
四、基于LBPH的人脸识别
LBPH(Local Binary Patterns Histograms)是一种基于局部纹理特征的人脸识别算法:
python
import cv2
import numpy as np
# 准备训练图像(灰度图)
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))
# 对应的标签:0代表hg,1代表pyy
labels = [0, 0, 1, 1]
dic = {0: 'hg', 1: 'pyy', -1: '无法识别'}
# 待识别的图像
predict_image = cv2.imread('hg.png', cv2.IMREAD_GRAYSCALE)
# 创建LBPH识别器,设置阈值为80
recognizer = cv2.face.LBPHFaceRecognizer_create(threshold=80)
# 训练模型
recognizer.train(images, np.array(labels))
# 进行预测
label, confidence = recognizer.predict(predict_image)
print('这人是:', dic[label])
print('置信度:', confidence)

LBPH算法特点:
- threshold=80:识别阈值,低于此值才认为是已知人脸
- confidence值:越小表示匹配度越高,0表示完美匹配
- 优点:对光照变化不敏感,计算速度快
五、基于特征脸(EigenFace)的人脸识别
EigenFace是基于PCA(主成分分析)的人脸识别方法:
python
import cv2
import numpy as np
images = []
# 加载并统一图像尺寸
a = cv2.imread('hg1.png', 0) # 0表示灰度模式
a = cv2.resize(a, (120, 180))
b = cv2.imread('hg2.png', 0)
b = cv2.resize(b, (120, 180))
c = cv2.imread('pyy1.png', 0)
c = cv2.resize(c, (120, 180))
d = cv2.imread('pyy2.png', 0)
d = cv2.resize(d, (120, 180))
images.append(a)
images.append(b)
images.append(c)
images.append(d)
labels = [0, 0, 1, 1]
pre_image = cv2.imread('pyy3.png', 0)
pre_image = cv2.resize(pre_image, (120, 180))
# 创建EigenFace识别器,设置阈值为5000
recognizer = cv2.face.EigenFaceRecognizer.create(threshold=5000)
recognizer.train(images, np.array(labels))
label, confidence = recognizer.predict(pre_image)
dic = {0: 'hg', 1: 'pyy', -1: 'Unknown'}
print('这人是:', dic[label])
print(f'置信度为:{confidence:.4f}')
# 在图像上显示识别结果
aa = cv2.putText(cv2.imread('pyy2.png').copy(), dic[label], (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2)
cv2.imshow('Result', aa)
cv2.waitKey(0)

EigenFace关键点:
- 图像尺寸统一:所有训练和测试图像必须调整为相同尺寸
- threshold=5000:EigenFace的阈值通常设置较大
- confidence值:与LBPH不同,EigenFace的置信度值有不同含义