Datawhale 计算机视觉基础-图像处理(下)-Task03 Haar特征描述算子-人脸检测

    技术2022-07-12  68

    Haar概念

    Haar特征

    Haar特征是一种用于目标检测或识别的图像特征描述子,Haar特征通常和AdaBoost分类器组合使用,而且由于Haar特征提取的实时性以及AdaBoost分类的准确率,使其成为人脸检测以及识别领域较为经典的算法。

    Haar-like特征是是计算机视觉领域一种常用的特征描述算子。它最早是由Papageorigiou等 人用于人脸描述。目前常用的Haar-like特征可以分为三类:线性特征、边缘特征、点特征(中心特征)、对角线特征。如下图所示 : 在计算Haar特征值时,用白色区域像素值的和减去黑色区域像素值的和,也就是说白色区域的权值为正值,黑色区域的权值为负值,而且权值与矩形区域的面积成反比,抵消两种矩形区域面积不等造成的影响,保证Haar特征值在灰度分布均匀的区域特征值趋近于0。Haar特征在一定程度上反应了图像灰度的局部变化,在人脸检测中,脸部的一些特征可由矩形特征简单刻画,例如,眼睛比周围区域的颜色要深,鼻梁比两侧颜色要浅等。   Haar-like矩形特征分为多类,特征模板可用于图像中的任一位置,而且大小也可任意变化,因此Haar特征的取值受到特征模板的类别、位置以及大小这三种因素的影响,使得在一固定大小的图像窗口内,可以提取出大量的Haar特征。例如,在一个24×24的检测窗口内,矩形特征的数量可以达到16万个。这样就需要解决两个重要问题,快速计算Haar矩形特征值——积分图;筛选有效的矩形特征用于分类识别——AdaBoost分类器。

    Haar特征计算——积分图

    积分图构建

    在一个图像窗口中,可以提取出大量的Haar矩形特征区域,如果在计算Haar特征值时,每次都遍历矩形特征区域,将会造成大量重复计算,严重浪费时间。而积分图正是一种快速计算矩形特征的方法,其主要思想是将图像起始像素点到每一个像素点之间所形成的矩形区域的像素值的和,作为一个元素保存下来,也就是将原始图像转换为积分图(或者求和图),这样在求某一矩形区域的像素和时,只需索引矩形区域4个角点在积分图中的取值,进行普通的加减运算,即可求得Haar特征值,整个过程只需遍历一次图像,计算特征的时间复杂度为常数(O(1))。因此可以大大提升计算效率。 积分图中元素的公式定义如下:

    上式含义是在(x,y)(第x行第y列)位置处,积分图中元素为原图像中对应像素左上角所有像素值之和。在具体实现时,可用下式进行迭代运算。 s ( x , y ) = s ( x , y − 1 ) + i ( x , y ) i i ( x , y ) = i i ( x − 1 , y ) + s ( x , y ) s(x,y)=s(x,y-1)+i(x,y)\\ ii(x,y)=ii(x-1,y)+s(x,y) s(x,y)=s(x,y1)+i(x,y)ii(x,y)=ii(x1,y)+s(x,y)

    扫描图像一遍,当到达图像右下角像素时,积分图像𝑖𝑖就构建好了。 积分图构造好之后,图像中任何矩阵区域像素累加和都可以通过简单运算得到如图所示: 设D的四个顶点分别为α,β,γ,δ则D的像素和可以表示为 D s u m = i i ( α ) + i i ( β ) − ( i i ( γ ) + i i ( δ ) ) Dsum=ii(α)+ii(β)−(ii(γ)+ii(δ)) Dsum=ii(α)+ii(β)(ii(γ)+ii(δ))

    特征计算

    上面已经知道,一个区域的像素值的和,可以由该区域的端点的积分图来计算。由前面特征模板的特征值的定义可以推出,矩形特征的特征值可以由特征端点的积分图计算出来。以A矩形特征为例,如下图,使用积分图计算其特征值: 该矩形特征的特征值,由定义,为区域A的像素值减去区域B的像素值。

    区域A的像素值: i i ( 5 ) + i i ( 1 ) − i i ( 2 ) − i i ( 4 ) ii(5)+ii(1)−ii(2)−ii(4) ii(5)+ii(1)ii(2)ii(4) 区域B的像素值: i i ( 6 ) + i i ( 2 ) − i i ( 5 ) − i i ( 3 ) ii(6)+ii(2)−ii(5)−ii(3) ii(6)+ii(2)ii(5)ii(3) 所以:该矩形特征的特征值 i i ( 5 ) + i i ( 1 ) − i i ( 2 ) − i i ( 4 ) − [ i i ( 6 ) + i i ( 2 ) − i i ( 5 ) − i i ( 3 ) ] = i i ( 5 ) − i i ( 4 ) + [ i i ( 3 ) − i i ( 2 ) ] − [ i i ( 2 ) − i i ( 1 ) ] − [ i i ( 6 ) − i i ( 5 ) ] ii(5)+ii(1)-ii(2)-ii(4)-[ii(6)+ii(2)-ii(5)-ii(3)]=ii(5)-ii(4)+[ii(3)-ii(2)]-[ii(2)-ii(1)]-[ii(6)-ii(5)] ii(5)+ii(1)ii(2)ii(4)[ii(6)+ii(2)ii(5)ii(3)]=ii(5)ii(4)+[ii(3)ii(2)][ii(2)ii(1)][ii(6)ii(5)] 所以,矩形特征的特征值,只与特征矩形的端点的积分图有关,而与图像的坐标无关。通过计算特征矩形的端点的积分图,再进行简单的加减运算,就可以得到特征值,正因为如此,特征的计算速度大大提高,也提高了目标的检测速度。

    Haar特征值归一化(也可以采用标准归一化)

    仅仅一个128大小的Haar特征计算出的特征值变化范围从-2000~+6000,跨度非常大。这种跨度大的特性不利于量化评定特征值,所以需要进行“归一化”,压缩特征值范围。假设当前检测窗口中的图像像素为𝑖(𝑥,𝑦)i(x,y),当前检测窗口为𝑤∗ℎw∗h大小(例如上图中为2020大小),OpenCV采用如下方式“归一化”:

    1、计算检测窗口中图像的灰度值和灰度值平方和: s u m = ∑ i ( x , y ) sum=\sum i(x,y) sum=i(x,y)

    s q s u m = ∑ i 2 ( x , y ) sq_{sum}=\sum i^2(x,y) sqsum=i2(x,y)

    2、计算平均值: m e a n = s u m w ∗ h mean = \frac{sum}{w*h} mean=whsum

    s q m e a n = s q s u m w ∗ h sq_{mean}=\frac{sq_{sum}}{w*h} sqmean=whsqsum

    3、计算归一化因子: v a r N o r m F a c t o r = s q m e a n − m e a n 2 varNormFactor=\sqrt{sq_{mean}-mean^2} varNormFactor=sqmeanmean2 4、归一化特征值: n o r m V a l u e = f e a t u r e V a l u e v a r N o r m F a c t o r normValue=\frac{featureValue}{varNormFactor} normValue=varNormFactorfeatureValue 之后使用归一化的特征值𝑛𝑜𝑟𝑚𝑉𝑎𝑙𝑢𝑒与阈值对比。

    AdaBoost分类器

    由输入图像得到积分图,通过取不同种类、大小的Haar特征模板,并在不同位置处,利用积分图提取Haar矩形特征,可快速得到大量Haar特征值,AdaBoost分类器可用于对提取的Haar特征(通常需要做归一化处理)进行训练分类,并应用于人脸检测中。AdaBoost是一种集成分类器,由若干个强分类级联而成,而每个强分类器又由若干个弱分类器(例如决策树)组合训练得到。 弱分类器的定义如下 在训练多个弱分类器得到强分类器的过程中,采用了两次加权的处理方法,一是对样本进行加权,在迭代过程中,提高错分样本的权重;二是对筛选出的弱分类器ht进行加权,弱分类器准确率越高,权重越大。此外,还需进一步对强分类器进行级联,以提高检测正确率并降低误识率。级联分类器如下所示: 首先将所有待检测的子窗口输入到第一个分类器中,如果某个子窗口判决通过,则进入下一个分类器继续检测识别,否则该子窗口直接退出检测流程,也就是说后续分类器不需要处理该子窗口。通过这样一种级联的方式可以去除一些误识为目标的子窗口,降低误识率。例如,单个强分类器,99%的目标窗口可以通过,同时50%的非目标窗口也能通过,假设有20个强分类器级联,那么最终的正确检测率为 0.9 9 20 = 98 0.99^{20}=98% 0.9920=98,而错误识别率为 0.5 0 20 ≈ 0.0001 0.50^{20}≈0.0001% 0.50200.0001,在不影响检测准确率的同时,大大降低了误识率。当然前提是单个强分类器的准确率非常高,这样级联多个分类器才能不影响最终的准确率或者影响很小。   在一幅图像中,为了能够检测到不同位置的目标区域,需要以一定步长遍历整幅图像;而对于不同大小的目标,则需要改变检测窗口的尺寸,或者固定窗口而缩放图像。这样,最后检测到的子窗口必然存在相互重叠的情况,因此需要进一步对这些重叠的子窗口进行合并,也就是非极大值抑制(NMS,non-maximum suppression),同时剔除零散分布的错误检测窗口。

    实践

    代码

    import cv2 import numpy as np haar_front_face_xml = './data/haarcascade_frontalface_default.xml' haar_eye_xml = './data/haarcascade_eye.xml' # 1.静态图像中的人脸检测 def StaticDetect(filename): # 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器. face_cascade = cv2.CascadeClassifier(haar_front_face_xml) # 加载图像 img = cv2.imread(filename) # 转换为灰度图 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 进行人脸检测,传入scaleFactor,minNegihbors,分别表示人脸检测过程中每次迭代时图像的压缩率以及 # 每个人脸矩形保留近似数目的最小值 # 返回人脸矩形数组 faces = face_cascade.detectMultiScale(gray_img, 1.3, 5) for (x, y, w, h) in faces: # 在原图像上绘制矩形 img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2) cv2.namedWindow('Face Detected!') cv2.imshow('Face Detected!', img) cv2.waitKey(0) cv2.destroyAllWindows() # 2、视频中的人脸检测 def DynamicDetect(): ''' 打开摄像头,读取帧,检测帧中的人脸,扫描检测到的人脸中的眼睛,对人脸绘制蓝色的矩形框,对人眼绘制绿色的矩形框 ''' # 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器. face_cascade = cv2.CascadeClassifier(haar_front_face_xml) eye_cascade = cv2.CascadeClassifier(haar_eye_xml) # 打开摄像头 camera = cv2.VideoCapture(0) cv2.namedWindow('Dynamic') while True: # 读取一帧图像 ret, frame = camera.read() # 判断图片读取成功? if ret: gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 人脸检测 faces = face_cascade.detectMultiScale(gray_img, 1.3, 5) for (x, y, w, h) in faces: # 在原图像上绘制矩形 cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = gray_img[y:y + h, x:x + w] # 眼睛检测 eyes = eye_cascade.detectMultiScale(roi_gray, 1.03, 5, 0, (40, 40)) for (ex, ey, ew, eh) in eyes: cv2.rectangle(frame, (ex + x, ey + y), (x + ex + ew, y + ey + eh), (0, 255, 0), 2) cv2.imshow('Dynamic', frame) # 如果按下q键则退出 if cv2.waitKey(100) & 0xff == ord('q'): break camera.release() cv2.destroyAllWindows() if __name__ == '__main__': filename = r'D:\LKY\practice\e.jpg' StaticDetect(filename) # DynamicDetect()

    检测结果

    # 参考

    图像特征提取之Haar特征 特征提取之Haar特征 http://blog.csdn.net/xizero00/article/details/46929261 https://gitee.com/yuanmingkun/team-learning/blob/master https://github.com/datawhalechina/team-learning/blob/master

    Processed: 0.015, SQL: 10