Haar 特征与 Haar 级联在 OpenCV 中的人脸检测实战

【精选优质专栏推荐】


每个专栏均配有案例与图文讲解,循序渐进,适合新手与进阶学习者,欢迎订阅。

在这里插入图片描述

在深度学习革命重新定义计算机视觉之前,Haar 特征和 Haar 级联是进行目标检测时不可忽视的工具。即便在今天,它们依然是非常实用的目标检测器,因为它们计算开销轻。在本文中,你将了解 Haar 级联以及它是如何检测目标的。阅读完本文后,你将了解:

  • 什么是 Haar 特征

  • Haar 级联如何利用 Haar 特征进行目标检测

  • OpenCV 中的一些预定义 Haar 级联目标检测器

本教程分为两部分:

  1. 什么是 Haar 特征和 Haar 级联

  2. OpenCV 中的 Haar 级联

什么是 Haar 特征和 Haar 级联?

自从 Paul Viola 和 Michael Jones 在 2001 年提出这一技术以来,Haar 特征和 Haar 级联彻底改变了目标检测领域。它们已经成为从人脸识别到实时目标检测等各种应用中的核心组成部分。

Haar 特征是从图像中的矩形区域提取的。特征值基于像素强度计算。通常通过滑动窗口进行计算,窗口内的区域被划分为两个或更多矩形区域。Haar 特征即这些区域像素强度之和的差值。

人们认为,目标的存在会改变像素强度的分布。例如,背景通常是均匀的模式,而前景目标则会打破这种模式。通过检查相邻矩形区域的像素强度,你可以察觉差异,从而判断目标的存在。

为了提高计算效率,Haar 特征中的矩形区域通常与图像边缘平行,而非倾斜。然而,我们可以使用不同大小和形状的矩形来捕捉目标的不同特征和尺度变化。因此,Haar 特征的关键优势在于能够表示三种模式:

  • 边缘
    矩形区域方向决定了边缘是垂直还是水平。用于识别图像不同区域之间的边界。

  • 线条
    图像中的对角边缘,用于识别目标中的线条和轮廓。

  • 中心-周围特征
    检测矩形区域中心与其周围区域的像素强度变化,用于识别具有明显形状或模式的目标。

Haar 级联通过层级组合多个 Haar 特征来构建分类器。与其用每个 Haar 特征分析整个图像,不如将检测过程分解为多个阶段,每个阶段包含一组特征。

Haar 级联的核心思想是:整个图像中只有一小部分像素与目标相关。因此,尽快剔除无关区域非常重要。在检测过程中,Haar 级联会在不同尺度和位置扫描图像,以排除无关区域。通过 AdaBoost 算法训练得到的级联结构,实现了高效的分层特征评估,降低了计算负担并加快了检测速度。

OpenCV 中的 Haar 级联

Haar 级联是一种算法,但在使用它作为目标检测器之前,你需要先训练一个 Haar 级联分类器。

在 OpenCV 中,有以下预训练的 Haar 级联分类器(可从 https://github.com/opencv/opencv/tree/4.x/data/haarcascades 下载模型文件):

  • 人脸

  • 眼睛检测

  • 人体(全身、上半身或下半身)

  • 车辆车牌

预训练分类器以 XML 文件形式存储。可以通过 GitHub 链接找到内置分类器的文件名。创建分类器时,需要提供该 XML 文件路径。如果使用 OpenCV 自带的文件,可以使用如下语法:

# 加载用于人脸检测的 Haar 级联
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

通常一张照片有多个颜色通道(如红、绿、蓝),而 Haar 级联仅依赖像素强度。因此应提供单通道图像,例如灰度图。

使用 Haar 级联分类器进行目标检测时,需要调用 detectMultiScale() 方法,其参数如下:

  • image:输入图像,应为灰度图或 HSV 图像的 “V” 通道

  • scaleFactor:补偿目标与摄像头距离不同而导致的尺寸变化,控制每次图像缩放的比例。必须大于 1。值越低检测时间越长,但检测成功率越高,典型范围 1.01–1.3

  • minNeighbors:指定保留候选目标所需的邻居数。值越高,检测数量少但质量高;值越低,可能出现更多检测和误报。精度与召回率之间的权衡

  • minSize:设置目标最小尺寸,小于此尺寸的目标会被忽略,格式为 (宽, 高)

示例:你可以下载一张街景照片进行实验:

https://unsplash.com/photos/people-walking-on-sidewalk-during-daytime-GBkAx9qUeus

在这里插入图片描述

在这个示例中,使用的分辨率为 1920×1080。如果你使用不同的分辨率,可能需要针对 detectMultiScale() 调整参数,尤其是 minSize。

接下来,我们创建一个人脸检测器,并找到行人的人脸位置。分类器使用 OpenCV 自带的预训练模型 haarcascade_frontalface_default.xml,该模型文件位于 cv2.data.haarcascades 指向的路径下。然后可以用它将人脸检测为边界框:

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4, minSize=(20, 20))

你可以自由调整这些参数。为了展示检测结果,可以使用 OpenCV 的绘图函数在原图上标出:

for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

注意,cv2.rectangle() 需要矩形对角线的坐标,而 detectMultiScale() 输出的是左上角坐标以及宽高。上面的代码会在检测到的每个人脸上绘制一个宽度为 2 像素的蓝色矩形框。在 OpenCV 中,图像通道顺序为 BGR,因此像素颜色 (255, 0, 0) 表示蓝色。

检测结果如下:

在这里插入图片描述

你会发现虽然存在一些误报,但整体效果还是相当不错的。你可以调整上面的参数来观察结果的变化。使用 Haar 级联的目标检测器的效果,很大程度上取决于训练模型的质量,也就是你从 XML 文件中读取的模型。

完整代码如下:

import cv2
import sys

# 照片来源: https://unsplash.com/photos/people-walking-on-sidewalk-during-daytime-GBkAx9qUeus
# 摄影师: Jacqueline Brandwayn

filename = 'jacqueline-brandwayn-GBkAx9qUeus-unsplash.jpg'
#filename = 'people2.jpg'

# 加载用于人脸检测的 Haar 级联
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# 读取输入图像
img = cv2.imread(filename)

# 将图像转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 执行人脸检测
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=4, minSize=(20, 20))

# 在检测到的人脸周围绘制矩形
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

# 显示结果
cv2.imshow('Face Detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

总结

本文介绍了基于 Haar 特征 和 Haar 级联 的目标检测方法。Haar 特征通过对图像中矩形区域像素强度的差异进行计算,可以表示边缘、线条以及中心-周围的特征模式;Haar 级联则将多个 Haar 特征按层级组合,分阶段扫描图像,从而高效检测目标。

在 OpenCV 中,我们可以直接使用预训练的 Haar 级联分类器(如 haarcascade_frontalface_default.xml)进行人脸检测。通过 detectMultiScale() 方法,可以在灰度图像上检测目标,并用 cv2.rectangle() 绘制边界框。检测效果受模型训练质量和参数设置影响,可通过调整 scaleFactor、minNeighbors 和 minSize 来优化。

总体来说,Haar 级联虽然是较早的传统方法,但因其计算轻量、实现简单,仍然适用于实时目标检测和资源受限场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋说

感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值