OpenCV 学习:人脸识别与表情检测

文章目录


一、静态图像人脸检测

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的置信度值有不同含义
相关推荐
lxl13073 小时前
学习C++(5)运算符重载+赋值运算符重载
学习
AutumnorLiuu4 小时前
C++并发编程学习(一)——线程基础
开发语言·c++·学习
CS创新实验室4 小时前
关于 Moltbot 的学习总结笔记
笔记·学习·clawdbot·molbot
峥嵘life4 小时前
Android EDLA CTS、GTS等各项测试命令汇总
android·学习·elasticsearch
千谦阙听4 小时前
数据结构入门:栈与队列
数据结构·学习·visual studio
.小墨迹4 小时前
C++学习——C++中`memcpy`和**赋值拷贝**的核心区别
java·linux·开发语言·c++·学习·算法·机器学习
望忆4 小时前
关于《Cold & Warm Net: Addressing Cold-Start Usersin Recommender Systems》
学习
你再说一遍?3644 小时前
计算机视觉实训作业记录:基于 YOLOv12 的水下目标检测模型优化与实现
yolo·目标检测·计算机视觉
笔画人生5 小时前
教培机构用蓝耘MaaS做“个性化学习计划”:从学情分析到方案生成的完整链路
python·学习
red_redemption5 小时前
自由学习记录(113)
学习