Haar Cascades是Paul Viola和Michael Jones在2001年发表的论文"Rapid Object Detection using a Boosted Cascade of Simple Features"中提出的一种目标检测算法。论文中写的非常细致,网上相关的文章也很多,作为一个非学院派、业余AI爱好者就只简单说一下其原理。我们知道一个好的分类模型一般至少需要两个先决条件:高质量的训练数据+高质量的特征,Haar Cascades也不例外 。他需要通过一大批正样本(包含目标)和负样本(不包含目标)来训练分类器,这是对数据的要求。论文还提出了如何提取特征:定义一些长方形,每一个长方形就代表一个特征,这些长方形内部会划分为多个黑白色区域。比如下图,定义了A、B、C、D四个长方形,即四个特征:

Haar特征

然后用这些长方形去划过图片(非常类似于CNN里面的卷积核),每划一次,用白色框中的所有的像素值减去黑色框中所有像素的值,得到一个该特征的值。这样有了数据,有了特征,就可以训练分类器了,比如使用AdaBoost分类器对数据进行训练。目前这个算法已经非常成熟,本文演示一下如何借助OpenCV使用Haar Cascades进行目标检测。OpenCV已经集成了Haar Cascades,而且内置了一些训练好的模型,可以从这里获取和查看。

下面代码实现了通过Haar特征进行人脸和眼睛检测:

import cv2

from imutils.video import VideoStream

face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_eye_tree_eyeglasses.xml")
vs = VideoStream(src=0).start()

while True:
    frame = vs.read()
    frame = cv2.resize(frame, (640, 480))
    # Haar Cascades必须使用灰度图
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
    rects_face = face_cascade.detectMultiScale(gray_frame)

    for (x, y, w, h) in rects_face:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        y = y - 10 if y - 10 > 10 else y + 10
        cv2.putText(frame, "face", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 1)

    rects_eye = eye_cascade.detectMultiScale(gray_frame)
    for (x, y, w, h) in rects_eye:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
        y = y - 10 if y - 10 > 10 else y + 10
        cv2.putText(frame, "eye", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 1)

    # 滤镜不能少...
    frame = cv2.bilateralFilter(frame, 0, 20, 5)
    cv2.imshow("preview", frame)
    k = cv2.waitKey(1) & 0xFF
    if k == ord("q"):
        break

代码见GitHub.

下面是检测效果(原谅我厚颜无耻的加了一点滤镜...):

detected

关于Haar Cascades算法需要知道以下几点:

  1. Haar Cascades分类器的输入需要灰度图。
  2. Haar特征是一种目标检测算法,可以用来训练各种目标的检测模型。但一个模型只能用来检测一种目标,比如上面代码中,检测人脸和眼睛是两个模型(其实光眼睛这一个也区分了两个模型,一个戴眼镜和一个不戴眼睛)。这和基于深度学习的目标检测模型是有区别的,后者一般一个模型可以检测多个目标。

虽然Haar Cascades一般没有一些基于深度学习的目标检测模型强大,但他也有自己的一些优势,比如容易训练、资源占用少等,所以仍旧有一定的使用场景。本文介绍的比较简单,一些细节会放在下篇文章中和另外一种目标检测算法一起讲解。