项目实战—人脸检测之HOG实战(四)
我们在之前注意到,在计算HOG方向梯度直方图特征时,如果按照上面说的直接对每一个小块进行梯度、梯度幅值、角度的计算,然后在进行统计,这样做的话,HOG的计算复杂度将会十分大,因此,我们可以将积分图的概念引入HOG的计算,以便加速HOG的计算性能。
积分图就是:对于一幅灰度图像而言,如果每一像素点的灰度值等于该像素点左上矩形区域所有像素点的灰度值之和,那么这幅图像就是积分图像。
1)为什么要用积分图像
图像直方图的计算方法为:遍历图像中的全部像素并累加计算每个灰度强度值出现的次数。但是,有时候需要计算图像中多个特定区域的直方图的,如果按照上面的计算方法进行计算的话,这个求解过程将会变得十分的耗时。在这种情况下使用积分图像将会极大的提高统计图像子区域像素的效率。
2)积分图像的概念
积分图就是:对于一幅灰度图像而言,如果每一像素点的灰度值等于该像素点左上矩形区域所有像素点的灰度值之和,那么这幅图像就是积分图像。
现在我们开始进行实战部分。
首先我们需要安装dlib库:
conda install dlib
同时还需要安装imutils库:
pip install imutils
预处理
首先,输入图像必须尺寸相同(可通过裁剪和缩放)。图像长宽比要求为 1:2,因此输入图像的尺寸可能为 64x128 或 100x200。
计算梯度图像
第一步是通过以下卷积核计算图像的水平梯度和垂直梯度:
图像的梯度通常会消除非必要信息。
上面图像的梯度可以通过下面的 python 语句找到:
gray = cv2.imread('min.jpg', 0) im = np.float32(gray) / 255.0 # Calculate gradient gx = cv2.Sobel(im, cv2.CV_32F, 1, 0, ksize=1) gy = cv2.Sobel(im, cv2.CV_32F, 0, 1, ksize=1) mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True)
绘制图片:
plt.figure(figsize=(12,8)) plt.imshow(mag) plt.show()
计算 HOG
首先将图像分成 8x8 个单元来提供紧凑表示,使 HOG 对噪声更鲁棒。然后,计算每个单元的 HOG。
为了估计区域内的梯度方向,我们只需在每个区域内的 64 个梯度方向值(8x8)及其大小(另外 64 个值)之间构建直方图。直方图的类别对应梯度的角度,从 0 到 180°。总共 9 类:0°,20°,40°...... 160°。
上面的代码给了我们 2 个信息:
· 梯度方向
· 梯度大小
当我们构建 HOG 时,有 3 种情况:
· 角度小于 160°,且不介于两类之间。在这种情况下,角度将添加到 HOG 的正确类中。
· 角度小于 160°,恰好在两类之间。在这种情况下,像素被均分到左右两侧类中。
· 角度大于 160°。在这种情况下,我们认为像素与 160°和 0°成比例。
每个 8x8 单元的 HOG 如下所示:
模块归一化
最后,可以用 16×16 的模块对图像进行归一化,并使其对光照不变。这可以通过将大小为 8x8 的 HOG 的每个值除以包含它的 16x16 模块的 HOG 的 L2 范数来实现,这个模块实际上是长度为 9*4 = 36 的简单向量。
最后,将所有 36x1 向量连接成一个大向量。OK!现在有了特征向量,我们可以在上面训练一个软 SVM 分类器(C=0.01)。
检测图像上的人脸
代码最终实现:
import cv2 import dlib import numpy as np import matplotlib.pyplot as plt from imutils import face_utils gray = cv2.imread('min.jpg', 0) im = np.float32(gray) / 255.0 # Calculate gradient gx = cv2.Sobel(im, cv2.CV_32F, 1, 0, ksize=1) gy = cv2.Sobel(im, cv2.CV_32F, 0, 1, ksize=1) mag, angle = cv2.cartToPolar(gx, gy, angleInDegrees=True) face_detect = dlib.get_frontal_face_detector() rects = face_detect(gray, 1) for (i, rect) in enumerate(rects): (x, y, w, h) = face_utils.rect_to_bb(rect) cv2.rectangle(gray, (x, y), (x + w, y + h), (255, 255, 255), 3) plt.figure(figsize=(12,8)) plt.imshow(gray, cmap='gray') plt.show()
结果:
实时人脸检测
同样的,我们可以使用摄像头进行人脸检测:
video_capture = cv2.VideoCapture(0) face_detect = dlib.get_frontal_face_detector() flag = 0 while True: ret, frame = video_capture.read() gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) rects = face_detect(gray, 1) for (i, rect) in enumerate(rects): (x, y, w, h) = face_utils.rect_to_bb(rect) cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.imshow('Video', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break video_capture.release() cv2.destroyAllWindows()
演示效果大家可以自行实验。