Linux 使用OpenCV进行人脸目标检测

大家好,今天我们来学习如何使用 OpenCV 的 Haar 级联分类器实现实时人脸检测,并在检测到的人脸区域(ROI)内进一步检测眼睛。Haar 级联是一种基于机器学习的目标检测方法,特别适合实时检测人脸、眼睛等特征,广泛应用于监控、人脸识别等场景。

一、Haar 级联分类器原理简介

Haar 级联分类器通过学习目标的 Haar 特征 (如边缘、纹理等),构建多层级联的弱分类器,最终实现对目标的快速检测。其核心优势是计算量小、实时性强,适合在普通硬件上运行。

本次教程将分为两个步骤:

  1. 检测图像 / 视频中的人脸(获取人脸区域 ROI);
  2. 在人脸 ROI 内检测眼睛(避免在非人脸区域误检)。

二、准备工作

1. 预训练模型下载

OpenCV 提供了预训练的 Haar 级联模型,无需自己训练,直接下载即可:

  • 人脸检测模型haarcascade_frontalface_default.xml
  • 眼睛检测模型haarcascade_eye.xml

官方下载地址(OpenCV GitHub 仓库):

下载方法:点击链接后,右键 “Raw”→“另存为”,保存到本地(建议新建一个models文件夹存放)。

2. 环境配置

确保已安装 OpenCV 和 NumPy(之前装过就忽略):

pip install opencv-python numpy

三、实时人脸检测 + 眼睛检测实现

我们将使用摄像头实时采集视频流,先检测人脸,再在人脸区域内检测眼睛。

import cv2
import numpy as np

# 1. 加载Haar级联模型(请替换为你的模型路径)
# 注意:模型路径需与代码文件位置对应,若放在models文件夹下则为"models/xxx.xml"
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")

# 检查模型是否加载成功
if face_cascade.empty() or eye_cascade.empty():
    print("模型加载失败!请检查文件路径是否正确。")
    exit()

# 2. 初始化摄像头
cap = cv2.VideoCapture(0)  # 0表示默认摄像头
if not cap.isOpened():
    print("无法打开摄像头!")
    exit()
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) # 打开自动曝光
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 关闭自动曝光

cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) # 打开自动曝光

cap.set(cv2.CAP_PROP_AUTO_WB, 1)  # 0:关闭自动白平衡

# 3. 实时检测循环
while True:
    # 读取一帧视频
    ret, frame = cap.read()
    if not ret:
        print("无法获取视频帧,退出程序。")
        break
    
    # 转换为灰度图(Haar检测通常基于灰度图,减少计算量)
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    
    # 4. 人脸检测
    # 参数说明:
    # - scaleFactor:缩放因子(1.1表示每次缩放10%),值越小检测越精确但速度越慢
    # - minNeighbors:最小邻居数(5表示一个目标至少被检测5次才认为是有效目标)
    # - minSize:目标最小尺寸(小于此尺寸的区域不检测)
    faces = face_cascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30)  # 人脸最小尺寸(宽x高)
    )
    
    # 5. 遍历检测到的人脸,在人脸ROI内检测眼睛
    for (x, y, w, h) in faces:
        # 绘制人脸边界框(蓝色,线宽2)
        cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
        
        # 提取人脸ROI(灰度图和彩色图,分别用于检测和绘制)
        face_gray = gray[y:y+h, x:x+w]  # 人脸区域的灰度图
        face_color = frame[y:y+h, x:x+w]  # 人脸区域的彩色图
        
        # 6. 在人脸ROI内检测眼睛
        eyes = eye_cascade.detectMultiScale(
            face_gray,
            scaleFactor=1.1,
            minNeighbors=3,
            minSize=(20, 20)  # 眼睛最小尺寸
        )
        
        # 绘制眼睛边界框(绿色,线宽2)
        for (ex, ey, ew, eh) in eyes:
            # 注意:眼睛坐标是相对于人脸ROI的,需转换为全局坐标
            cv2.rectangle(face_color, (ex, ey), (ex+ew, ey+eh), (0, 255, 0), 2)
    
    # 显示检测结果
    cv2.imshow("Face and Eye Detection", frame)
    
    # 按'q'退出程序
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()
    

四、代码详解

1. 模型加载

python

运行

face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier("haarcascade_eye.xml")

  • CascadeClassifier:OpenCV 用于加载 Haar 级联模型的类。
  • 注意:模型路径必须正确,若模型文件与代码在同一文件夹,直接写文件名;否则需写绝对路径(如C:/models/haarcascade_frontalface_default.xml)。
2. 人脸检测核心参数

python

运行

faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

  • scaleFactor=1.1:每次检测时将图像缩小 10%,平衡检测速度与精度。
  • minNeighbors=5:过滤噪声(值越大,误检越少,但可能漏检)。
  • minSize=(30, 30):忽略小于 30x30 像素的区域(避免检测过小的噪声)。
3. 人脸 ROI 与眼睛检测

python

运行

# 提取人脸ROI(只在人脸区域内检测眼睛,提高效率)
face_gray = gray[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(face_gray, ...)

  • 为什么要在人脸 ROI 内检测眼睛?

避免在背景(如窗户、灯泡)中误检为眼睛,同时减少计算量(只需处理人脸大小的区域)。

五、效果优化与常见问题

1. 检测效果不好?调整这些参数!
  • 漏检严重:减小scaleFactor(如 1.05)、减小minNeighbors(如 3)、减小minSize
  • 误检太多:增大scaleFactor(如 1.2)、增大minNeighbors(如 7)、增大minSize
2. 眼睛检测不稳定?
3. 实时性差?
  • 降低摄像头分辨率:cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
  • 增大scaleFactor(如 1.3),减少检测迭代次数。

六、总结

Haar 级联分类器是实时人脸 / 眼睛检测的经典方案,优点是速度快、无需复杂计算资源,缺点是对姿态(如侧脸)和光照敏感。后续笛子哥会讲解yolo的方案,敬请期待。

1 个赞