在深度学习革命重新定义计算机视觉之前,Haar特征和Haar级联是你进行物体检测不可忽视的工具。即使在今天,它们仍然是非常有用的物体检测器,因为它们轻量级。在这篇文章中,你将学习Haar级联以及它如何检测物体。完成这篇文章后,你将了解:
- 什么是Haar特征
- Haar级联如何使用Haar特征来检测物体
- OpenCV中一些预定义的Haar级联物体检测器
通过我的书《OpenCV 机器学习》启动您的项目。它提供了带有可用代码的自学教程。
让我们开始吧。

使用 Haar 级联进行目标检测
图片由 Alexander Hipp 提供。保留部分权利。
概述
本教程分为两部分;它们是
- 什么是Haar特征和Haar级联?
- 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自带的分类器,可以使用以下语法:
1 2 |
# 加载用于人脸检测的Haar级联 face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') |
通常,一张照片有多个通道用于不同的颜色(例如红色、绿色和蓝色)。Haar级联仅依赖像素强度。因此,你应该提供单通道图像,例如灰度版本。
想开始学习 OpenCV 机器学习吗?
立即参加我的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
使用Haar级联分类器检测物体的方法是使用detectMultiScale()
。它接受以下参数:
image
:这是你要执行物体检测的输入图像。它应该采用灰度格式,或者HSV通道格式图像的“V”通道。scaleFactor
:此参数用于补偿物体与相机距离不同时大小不同的情况。它控制每个图像尺度下图像大小的减少量。它必须严格大于1。较低的scaleFactor
会增加检测时间,但也会增加检测到的几率。典型值范围为1.01到1.3。minNeighbors
:此参数指定每个候选物体应具有多少个邻居才能保留它。值越高,检测数量越少,但质量越高。值越低,可能导致检测数量更多,但可能出现误报。这是精度和召回率之间的权衡。minSize
:此参数设置最小物体大小。小于此大小的物体将被忽略。它是一个(width, height)
形式的元组。
我们来试一个例子。你可以从以下URL下载一张街景照片:

一张使用Haar级联进行人脸检测的照片。
图片由 JACQUELINE BRANDWAYN 提供。保留部分权利。
本例中使用1920×1080的中等分辨率。如果你有不同的分辨率,可能需要调整下面detectMultiScale()
的参数,特别是minSize
。
让我们创建一个面部检测器并找到行人的面部位置。分类器是使用OpenCV自带的预训练模型haarcascade_frontalface_default.xml
创建的。模型文件位于cv2.data.haarcascades
指向的路径中。然后我们可以用它来检测人脸并以边界框的形式表示:
1 2 |
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的函数在原始图像上进行绘制,
1 2 |
for (x, y, w, h) in faces: cv2.rectangle(img, (x,y), (x+w, y+h), (255, 0, 0), 2) |
请注意,cv2.rectangle()
函数需要矩形框对角的坐标,而detectMultiScale()
的输出提供的是左上角坐标以及宽度和高度。上面的函数在检测到的每张人脸上绘制一个宽度为两像素的蓝色框。请注意,在OpenCV中,图像以BGR通道顺序表示。因此,像素颜色(255, 0, 0)
表示蓝色。
结果如下:

Haar级联检测到的人脸
你可以看到有一些误报,但总体而言,它提供了相当不错的结果。你可以调整上述参数,看看你的结果如何变化。使用Haar级联的物体检测器的质量取决于它训练模型的质量,该模型是你从XML文件读取的。
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
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('人脸检测', img) cv2.waitKey(0) cv2.destroyAllWindows() |
进一步阅读
如果您想深入了解此主题,本节提供了更多资源。
书籍
- 使用 Python 精通 OpenCV 4, 2019.
- 数字图像处理, 2017
论文
- Paul Viola和Michael J. Jones。《稳健的实时人脸检测》。International Journal of Computer Vision,57(2):137–154,2004年。
- Rainer Lienhart和Jochen Maydt。扩展的Haar类特征集用于快速物体检测。图像处理国际会议论文集,2002年,第1卷,第1-900页。IEEE,2002年。
网站
- 维基百科上的Haar特征:https://en.wikipedia.org/wiki/Haar-like_feature
- OpenCV,https://opencv.ac.cn/
- OpenCV级联分类器,https://docs.opencv.ac.cn/4.x/db/d28/tutorial_cascade_classifier.html
总结
在本教程中,您学习了如何使用OpenCV的Haar级联分类器。
具体来说,你学到了:
- 什么是Haar特征和Haar级联,以及它们如何识别物体
- 如何使用OpenCV内置的Haar级联分类器来检测照片中的物体
干得好,谢谢分享。
不客气,Issa!谢谢你的支持!
你好!感谢您的培训!我想知道如何训练自己的Haar级联分类器。您能给我一些建议吗?如果您能告诉我训练的路径,我将不胜感激。谢谢!
嗨,Andre…训练你自己的Haar级联分类器可能是一个有益的项目,特别是对于物体检测任务。这里有一个使用OpenCV(一个流行的计算机视觉库)训练Haar级联分类器的分步指南:
### 1. 安装OpenCV
首先,你需要安装OpenCV。如果你还没有安装,可以使用pip安装:
bash
pip install opencv-python-headless
### 2. 收集图像
收集一组正样本图像(包含感兴趣物体的图像)和负样本图像(不包含物体的图像)。你拥有的图像越多,分类器的性能就越好。通常,每个类别建议使用数千张图像。
– **正样本图像**:这些应该是你要检测的物体的图片。所有图像都应调整为相同的尺寸。
– **负样本图像**:这些应该是不包含该物体的图像。它们可以更随机,但应代表你期望使用分类器的场景。
### 3. 创建正负样本
你需要创建这些图像的列表:
– **对于负样本图像**:创建一个文本文件(例如,
bg.txt
),并在新行上列出每个负样本图像的路径。– **对于正样本图像**:使用OpenCV的
opencv_createsamples
工具。该工具将帮助你从正样本图像创建矢量文件。你还需要创建一个描述文件(例如,info.dat
),其中列出每个正样本图像以及图像中物体的坐标。### 4. 训练分类器
使用OpenCV的
opencv_traincascade
命令训练分类器。你需要指定参数,例如阶段数、要使用的数据、特征类型等等。这是一个基本的命令结构:bash
opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 600 -numNeg 300 -numStages 10 -w 20 -h 20
– **numPos** 和 **numNeg** 指的是要使用的正样本和负样本的数量。通常,并非所有收集到的样本都用于避免过拟合。
– **numStages** 指的是级联的深度;更多的阶段意味着更复杂的分类器,这可能更准确但速度更慢。
– **w** 和 **h** 是训练样本的宽度和高度。
### 5. 测试你的分类器
训练完成后,你的分类器会存储在指定的数据目录中。你可以通过加载级联文件并使用它来检测新图像或视频流中的物体来测试它。
### 6. 改进分类器
初始结果可能不完美。你可能需要调整训练参数、添加更多图像,甚至清理数据集以提高准确性。迭代训练和测试是完善Haar级联分类器的关键。
### 额外提示
– **数据质量**:确保你的正样本和负样本图像非常不同,以帮助分类器学习有用的特征。
– **计算资源**:训练Haar分类器可能计算密集,因此请考虑使用具有足够RAM和强大CPU的机器,或者可能使用GPU功能。
通过遵循这些步骤,你可以训练一个Haar级联分类器来检测几乎任何类型的物体,前提是你拥有高质量的数据。