Haar特征
文章目录
- 1.Introduction
- 2.Haar特征计算详解
- 3.使用sklearn计算Haar特征
- 参考资料
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
1.Introduction
Rapid Object Detection using a Boosted Cascade of Simple Features
Haar特征是由Viola和Jones在2001年提出的,用于面部识别和人脸检测。
Haar特征的基本思想是将图像划分为多个矩形区域,并计算每个矩形区域内像素值的差异,从而得到一组能够有效描述图像特征的数值。Haar特征与小波变换有相似之处,因此也被称之为Haar小波。
Haar特征由一系列可以缩放的矩形(如下图所示)结合原图像进行运算得到的,这种方法最早在1909年由匈牙利数学家Alfred Haar
提出。Haar Feature
的求解过程与卷积有相似之处。
如上图中,一种矩形表示一种Haar特征,大小不同也能得到不同的Haar特征。其应用思路如下,考虑人脸检测,Haar特征能够识别出人脸的关键部位。如下图,检测眉毛位置使用图中所示意的Haar特征,因眉毛处的像素比额头处要暗,也就是灰度值小,拿矩形白色部分的像素和减去黑色矩形的像素和,能得到比其他部位更大的灰度插值。同样,对鼻子处,左右部分也存在灰度差值。
图片来自于1
2.Haar特征计算详解
以上图所示的模式来计算Haar
特征。
上面这个图表示的是对一个3x3
大小的图像求type-2-x
模式的Haar
特征的过程,即黑色区域像素和减去白色区域像素和。一个宽高3x3
的图像,经过rescale
的type-2-x
的Haar
变换可以得到12个特征值。当图像尺度变大时能够得到更多的Haar
特征。对一个宽高8x8
的图像,type-2-x
的Haar
变换可以得到576个特征值;而对一个宽高56x56
的图像,type-2-x
的Haar
变换可以得到1251264个特征值。
从上面的示例中也可以看到,Haar变换的计算过程涉及到图像区域像素的求和,不同scale的Haar变换,图像区域其实是有重和的,反复的进行求和比较耗时,为了提高计算的性能,可以使用积分图改进Haar
算法。
积分图的定义是对于图像每个像素将其左上角所有像素求和所得如上面的宽高3x3
图像的示例,其对应的积分图为:
有了积分图后,可以借助积分图求图像特定区域的面积。
看上面这张图,表示原始图像的积分图,想要求原图像区域D中的像素和,使用积分图计算如下:
积分图上点1处的值为:ii(1)=RectSum(A)
积分图上点2处的值为:ii(2)=RectSum(A) - RectSum(B)
积分图上点3处的值为:ii(3)=RectSum(A) + RectSum(C)
积分图上点4处的值为:ii(1)=RectSum(A) - RectSum(B) + RectSum(C) + RectSum(D)
求区域D的像素和可表示成RectSum(D)=ii(4) + ii(1) - ii(2) - ii(3)
,通过这种方式计算原图像中区域像素的和可以极大的减少运算量,加快运算速度。
通过上面的介绍可以知道,一张图像可以得到非常多的Haar
特征,很多特征都是和目标检测无关的,传统的方法通常将Adaboost
分类器和Haar
特征一起使用,其思想是将Haar
特征当成很多个弱分类器,再使用Adaboost
将如此多的弱分类器组合到一起组成强分类器。实际使用中,采用级联的分类器,以便更快的判断出图像区域中是否包含人脸,如下图,
使用Adaboost
和Haar
特征来做人脸检测的例子可以参考SkImage的示例。
3.使用sklearn计算Haar特征
skimage.feature.haar_like_feature(int_image, r, c, width, height, feature_type=None, feature_coord=None)
r
: 计算Haar
特征图像的起始区域左上角的行坐标c
: 计算Haar
特征图像的起始区域左上角的列坐标width
: 计算Haar
特征图像的区域宽度height
: 计算Haar
特征图像的起始区域高度feature_type
:计算Haar
特征使用的模式,支持type-2-x/type-2-y/type-3-x/type-3-y/type-4
这几种。feature_coord
:计算Haar
特征使用的模式矩形,白色和黑色区域的起始和终止坐标,其值可以使用haar_like_feature_coord()
方法来获取。具体看下面的例子。
from skimage import feature
import numpy as np
from skimage.transform import integral_image
img = np.random.randint(0, 255, (56, 56))
img = np.uint8(img)
"""
img:
[[ 70 84 24]
[ 41 222 212]
[252 164 108]]
"""
types = np.array(['type-2-x', 'type-2-x'])
int_image = img
h, w = int_image.shape[:2]
ii = integral_image(int_image)
feat_coord = np.array([[[[0, 0], [0, 0]], [(0, 1), (0, 1)]],[[(0, 0), (1, 0)], [(0, 1), (1, 1)]]])
feat = feature.haar_like_feature(ii, 0, 0, w, h, feature_type=types, feature_coord=feat_coord)
"""
intergral_img:
[[ 70 154 178]
[ 111 417 653]
[ 363 833 1177]]
Haar Feature: [ 14 195]
使用haar_like_feature_coord
计算矩形的起始区域:
feat_coord, feat_type = feature.haar_like_feature_coord(3, 3, 'type-2-x')
print(feat_coord)
"""
Haar Coordinate:
[list([[(0, 0), (0, 0)], [(0, 1), (0, 1)]])
list([[(0, 0), (1, 0)], [(0, 1), (1, 1)]])
list([[(0, 0), (2, 0)], [(0, 1), (2, 1)]])
list([[(0, 1), (0, 1)], [(0, 2), (0, 2)]])
list([[(0, 1), (1, 1)], [(0, 2), (1, 2)]])
list([[(0, 1), (2, 1)], [(0, 2), (2, 2)]])
list([[(1, 0), (1, 0)], [(1, 1), (1, 1)]])
list([[(1, 0), (2, 0)], [(1, 1), (2, 1)]])
list([[(1, 1), (1, 1)], [(1, 2), (1, 2)]])
list([[(1, 1), (2, 1)], [(1, 2), (2, 2)]])
list([[(2, 0), (2, 0)], [(2, 1), (2, 1)]])
list([[(2, 1), (2, 1)], [(2, 2), (2, 2)]])]
"""
参考资料
- 1.https://medium.com/analytics-vidhya/what-is-haar-features-used-in-face-detection-a7e531c8332b
- 2.https://zhuanlan.zhihu.com/p/38056144