本文主要是介绍第14期(六月)组队学习 Task3:Haar特征描述算子-人脸检测,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Task3:Haar特征描述算子-人脸检测
- Haar特征描述算子-人脸检测
- 1 Haar特征简介
- 1.1 积分图
- 1.1.1 积分图构建
- 1.1.2 计算Haar特征值
- 1.1.3 旋转矩形特征的计算
- 1.1.4 AdaBoost分类器
- 2 参考代码
- 2.1 静态图像的人脸检测
- 2.2 动态图像的人脸检测
- 3 致谢
Haar特征描述算子-人脸检测
Haar特征是用于物体识别的一种数字图像特征,与哈尔小波转换极为相似,也是第一种即时的人脸检测运算;同时是一种用于目标检测或识别的图像特征描述子,通常和AdaBoost分类器组合使用,Haar特征对AdaBoost训练出的强分类器进行级联,使其成为人脸检测以及识别领域较为经典的算法。
1 Haar特征简介
Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻 梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构,如下图所示。
对于图中的 A A A, B B B和 D D D这类特征,特征数值计算公式为: v = Σ 白 − Σ 黑 v=\Sigma白-\Sigma黑 v=Σ白−Σ黑,而对于 C C C来说,计算公式为: v = Σ 白 − 2 ∗ Σ 黑 v=\Sigma白-2*\Sigma黑 v=Σ白−2∗Σ黑;将黑色区域像素和乘以2,是为了使两种矩形区域中像素数目一致。即白色区域的权值为正值,黑色区域的权值为负值,而且权值与矩形区域的面积成反比,可以抵消两种矩形区域面积不等造成的影响,保证Haar特征值在灰度分布均匀的区域特征值趋近于0。
通过改变特征模板的大小和位置,可在图像子窗口中穷举出大量的特征。上图的特征模板称为“特征原型”;特征原型在图像子窗口中扩展(平移伸缩)得到的特征称为“矩形特征”;矩形特征的值称为“特征值”。
矩形特征可位于图像任意位置,大小也可以任意改变,所以矩形特征值是矩形模版类别、矩形位置和矩形大小这三个因素的函数。故类别、大小和位置的变化,使得 很小的检测窗口含有非常多的矩形特征,如:在24*24像素大小的检测窗口内矩形特征数量可以达到16万个。需要解决两个问题:(1)快速计算Haar矩形特征值?—积分图;(2)筛选有效的矩形特征用于分类识别?—可以通过AdaBoost算法来训练。
1.1 积分图
1.1.1 积分图构建
在一个图像窗口中,可以提取出大量的Haar矩形特征区域,如果在计算Haar特征值时,每次都遍历矩形特征区域,将会造成大量重复计算,严重浪费时间。积分图是一种快速计算矩形特征的方法,主要思想是将图像起始像素点到每一个像素点之间所形成的矩形区域的像素值的和,作为一个元素保存下来,即将原始图像转换为积分图(或者求和图),当求某一矩形区域的像素和时,只需要索引矩形区域4个角点在积分图中的取值,进行普通的加减运算,即可求得Haar特征值,整个过程只需遍历一次图像,计算特征的时间复杂度为常数 ( O ( 1 ) ) (O(1)) (O(1)),可以大大提升计算效率。
积分图中元素的公式定义如下:
i i ( x , y ) = Σ k ≤ x , l ≤ y f ( k , l ) ii(x,y) = \Sigma_{k\leq x,l\leq y} f(k,l) ii(x,y)=Σk≤x,l≤yf(k,l)
上式含义是在 ( x , y ) (x,y) (x,y)(第 x x x行第 y y y列)位置处,积分图中元素为原图像中对应像素左上角所有像素值之和, i i ( x , y ) ii(x,y) ii(x,y)表示一个积分图像。在具体实现时,可用下式进行迭代运算。
s ( x , y ) = s ( x , y − 1 ) + i ( x , y ) s(x,y)=s(x,y-1)+i(x,y) s(x,y)=s(x,y−1)+i(x,y)
i i ( x , y ) = i i ( x − 1 , y ) + s ( x , y ) ii(x,y)=ii(x-1,y)+s(x,y) ii(x,y)=ii(x−1,y)+s(x,y)
s ( x , y ) s(x,y) s(x,y)为行方向的累加值,初始值 s ( x , − 1 ) = 0 , i i ( − 1 , y ) = 0 s(x,-1)=0,ii(-1,y)=0 s(x,−1)=0,ii(−1,y)=0
1.1.2 计算Haar特征值
构建好积分图后,图像中任何矩形区域的像素值累加和都可以通过简单的加减运算快速得到,如下图所示,矩形区域D的像素和值计算公式如下:
S u m ( D ) = i i ( x 4 , y 4 ) − i i ( x 2 , y 2 ) − i i ( x 3 , y 3 ) + i i ( x 1 , y 1 ) Sum(D)=ii(x_4, y_4)-ii(x_2,y_2)-ii(x_3,y_3)+ii(x_1,y_1) Sum(D)=ii(x4,y4)−ii(x2,y2)−ii(x3,y3)+ii(x1,y1)
矩形区域求和示意图
在下图中,以水平向右为x轴正方向,垂直向下为y轴正方向,可定义积分图公式Summed Area Table( S A T ( x , y ) SAT(x,y) SAT(x,y))
S A T ( x , y ) = Σ x ’ ≤ x , y ’ ≤ y i ( x ’ , y ’ ) SAT(x,y)=\Sigma_{x’\leq x,y’\leq y} i(x’,y’) SAT(x,y)=Σx’≤x,y’≤yi(x’,y’)
以及迭代求解式
S A T ( x , y ) = S A T ( x , y − 1 ) + S A T ( x − 1 , y ) − S A T ( x − 1 , y − 1 ) + I ( x , y ) SAT(x,y)=SAT(x,y-1)+SAT(x-1,y)-SAT(x-1,y-1)+I(x,y) SAT(x,y)=SAT(x,y−1)+SAT(x−1,y)−SAT(x−1,y−1)+I(x,y)
S A T ( − 1 , y ) = 0 , S A T ( x , − 1 ) = 0 SAT(-1,y)=0, SAT(x,-1)=0 SAT(−1,y)=0,SAT(x,−1)=0
对于左上角坐标为 ( x , y ) (x,y) (x,y),宽高为 ( w , h ) (w,h) (w,h)的矩形区域 r ( x , y , w , h , 0 ) r(x,y,w,h,0) r(x,y,w,h,0),可利用积分图 S A T ( x , y ) SAT(x,y) SAT(x,y)求取像素和值
R e c S u m ( r ) = S A T ( x + w − 1 , y + h − 1 ) + S A T ( x − 1 , y − 1 ) − S A T ( x + w − 1 , y − 1 ) − S A T ( x − 1 , y + h − 1 ) RecSum(r)=SAT(x+w-1, y+h-1)+SAT(x-1, y-1)-SAT(x+w-1, y-1)-SAT(x-1,y+h-1) RecSum(r)=SAT(x+w−1,y+h−1)+SAT(x−1,y−1)−SAT(x+w−1,y−1)−SAT(x−1,y+h−1)
积分图求矩形区域和值
1.1.3 旋转矩形特征的计算
对于旋转矩形特征,相应的有 4 5 ∘ 45^{\circ} 45∘倾斜积分图用于快速计算Haar特征值,如下图所示,倾斜积分图的定义为像素点左上角 4 5 ∘ 45^{\circ} 45∘区域和左下角 4 5 ∘ 45^{\circ} 45∘区域的像素和,公式表示如下:
R S A T ( x , y ) = Σ x ’ ≤ x , x ’ ≤ x − ∣ y − y ’ ∣ i ( x ’ , y ’ ) RSAT(x,y)=\Sigma_{x’\leq x,x’\leq x-\left|y-y’\right|} i(x’,y’) RSAT(x,y)=Σx’≤x,x’≤x−∣y−y’∣i(x’,y’)
其递推公式计算如下:
R S A T ( x , y ) = R S A T ( x − 1 , y − 1 ) + R S A T ( x − 1 , y ) − R S A T ( x − 2 , y − 1 ) + I ( x , y ) RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x-1,y)-RSAT(x-2,y-1)+I(x,y) RSAT(x,y)=RSAT(x−1,y−1)+RSAT(x−1,y)−RSAT(x−2,y−1)+I(x,y)
R S A T ( x , y ) = R S A T ( x , y ) + R S A T ( x − 1 , y + 1 ) − R S A T ( x − 2 , y ) RSAT(x,y)=RSAT(x,y)+RSAT(x-1,y+1)-RSAT(x-2,y) RSAT(x,y)=RSAT(x,y)+RSAT(x−1,y+1)−RSAT(x−2,y)
其中 R S A T ( − 1 , y ) = R S A T ( − 2 , y ) = R S A T ( x , − 1 ) = 0 RSAT(-1,y)=RSAT(-2,y)=RSAT(x,-1)=0 RSAT(−1,y)=RSAT(−2,y)=RSAT(x,−1)=0
也可直接通过下式递归计算:
R S A T ( x , y ) = R S A T ( x − 1 , y − 1 ) + R S A T ( x + 1 , y − 1 ) − R S A T ( x , y − 2 ) + I ( x − 1 , y ) + I ( x , y ) RSAT(x,y)=RSAT(x-1,y-1)+RSAT(x+1,y-1)-RSAT(x,y-2)+I(x-1,y)+I(x,y) RSAT(x,y)=RSAT(x−1,y−1)+RSAT(x+1,y−1)−RSAT(x,y−2)+I(x−1,y)+I(x,y)
以上3个积分图计算公式是等价的。
如下图所示,构建好倾斜积分图后,可快速计算倾斜矩形区域 r = ( x , y , w , h , 4 5 ∘ ) r=(x,y,w,h,45^{\circ}) r=(x,y,w,h,45∘)的像素和值
R e c S u m ( r ) = R S A T ( x + w , y + w ) + R S A T ( x − h , y + h ) − R S A T ( x , y ) − R S A T ( x + w − h , y + w + h ) RecSum(r)=RSAT(x+w,y+w)+RSAT(x-h,y+h)-RSAT(x,y)-RSAT(x+w-h,y+w+h) RecSum(r)=RSAT(x+w,y+w)+RSAT(x−h,y+h)−RSAT(x,y)−RSAT(x+w−h,y+w+h)
1.1.4 AdaBoost分类器
由输入图像得到积分图,通过取不同种类、大小的Haar特征模板,并在不同位置处,利用积分图提取Haar矩形特征,可快速得到大量Haar特征值,AdaBoost分类器可用于对提取的Haar特征(通常需要做归一化处理)进行训练分类,并应用于人脸检测中。AdaBoost是一种集成分类器,由若干个强分类级联而成,而每个强分类器又由若干个弱分类器(例如决策树)组合训练得到。
弱分类器的定义如下:
h j ( x ) = { 1 , p j f j ( x ) < p j θ j 0 , o t h e r w i s e h_j(x)=\begin{cases} 1, p_j f_j(x) < p_j \theta_j\\ 0, otherwise\end{cases} hj(x)={1, pjfj(x)<pjθj0, otherwise
上式中 p j p_j pj是为了控制不等式的方向而设置的参数。 x x x表示一个图像窗口, f j ( x ) f_j(x) fj(x)表示提取的Haar特征,阈值 θ \theta θ用于判断该窗口是否为目标区域(人脸)。
算法流程:
假设训练样本为 ( x i , y i ) , i = 0 , 1 , … , n (x_i,y_i),i=0,1,…,n (xi,yi),i=0,1,…,n, y i y_i yi取值为0(负样本)、1(正样本)。
初始化权重 w 1 , i = 1 2 m , y i = 1 2 l w_1,i=\dfrac{1}{2m},y_i=\dfrac{1}{2l} w1,i=2m1,yi=2l1,其中 m m m表示负样本的个数, l l l表示正样本的个数。
For t = 1 , 2 , … , T t =1,2,…,T t=1,2,…,T
1.归一化权值:$w_{t,i} = \dfrac{w_{t,i}}{\Sigma_{j=1}^n w_{t,j}} $
2.对于每个(种)特征,训练一个分类器( h j h_j hj),每个分类器只使用一种Haar特征进行训练。分类误差为 ε j = Σ i w i ∣ h j ( x i ) − y i ∣ \varepsilon_j=\Sigma_i w_i \left|h_j(x_i)-y_i\right| εj=Σiwi∣hj(xi)−yi∣, h j h_j hj为特征分类器, x i x_i xi为训练图像样本。
3.选择最低误差的分类器 h t h_t ht
4.更新训练样本的权值 w t + 1 , i = w t , i β t 1 − e i w_{t+1,i}=w_{t,i}\beta_t^{1-e_i} wt+1,i=wt,iβt1−ei,分类正确 e i = 0 e_i=0 ei=0,分类错误 e i = 1 e_i=1 ei=1, β t = ε t 1 − ε t \beta_t=\dfrac{\varepsilon_t}{1-\varepsilon_t} βt=1−εtεt
最后的强分类器为
h ( x ) = { 1 , Σ t = 1 T α t h t ≥ 1 2 Σ t = 1 T α t 0 , o t h e r w i s e h(x)=\begin{cases} 1, \Sigma_{t=1}^T \alpha_t h_t \geq \dfrac{1}{2}\Sigma_{t=1}^T \alpha_t \\ 0, otherwise\end{cases} h(x)=⎩⎨⎧1, Σt=1Tαtht≥21Σt=1Tαt0, otherwise
其中 α t = l o g ( 1 β t ) \alpha_t=log(\dfrac{1}{\beta_t}) αt=log(βt1)。
在训练多个弱分类器得到强分类器的过程中,采用了两次加权的处理方法,一是对样本进行加权,在迭代过程中,提高错分样本的权重;二是对筛选出的弱分类器 h t h_t 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} \approx 0.0001\% 0.5020≈0.0001%,在不影响检测准确率的同时,极大地降低了误识率。当然前提是单个强分类器的准确率非常高,这样级联多个分类器才能不影响最终的准确率或者影响很小。
在一幅图像中,为了能够检测到不同位置的目标区域,需要以一定步长遍历整幅图像;而对于不同大小的目标,则需要改变检测窗口的尺寸,或者固定窗口而缩放图像。这样,最后检测到的子窗口必然存在相互重叠的情况,因此需要进一步对这些重叠的子窗口进行合并,即非极大值抑制(NMS,non-maximum suppression),同时剔除零散分布的错误检测窗口。
使用AdaBoost算法训练分类器之前,提前准备正和负样本,由样本特点选择和构造特征集。在训练过程中,当弱分类器对样本分类正确,样本的权重会减小,当弱分类器对样本分类错误,样本的权重会增大,后续的分类器会强化对错分样本的训练,最后,所有弱分类器组合形成强分类器,通过比较弱分类器投票的加权和与平均投票结果来检测图像。
2 参考代码
2.1 静态图像的人脸检测
import cv2
import numpy as np
face_cascade=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
face_cascade.load('D:/binchen/tkinter1/txzq1/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml')
# 1.静态图像中的⼈脸检测
#def StaticDetect(filename):
# 创建⼀个级联分类器 加载⼀个 .xml 分类器⽂件. 它既可以是Haar特征也可以是LBP特征的分类器.
#face_cascade = cv2.CascadeClassifier(haar_front_face_xml)
# 加载图像
img = cv2.imread('test1.jpeg')
# 转换为灰度图
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.2 动态图像的人脸检测
import cv2
import numpy as nphaar_front_face_xml = './data/haarcascade_frontalface_default.xml'
haar_eye_xml = './data/haarcascade_eye.xml'
#face_cascade=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#face_cascade.load('D:/binchen/tkinter1/txzq1/Lib/site-packages/cv2/data/haarcascade_frontalface_default.xml')# 视频中的⼈脸检测
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'):breakcamera.release()cv2.destroyAllWindows()
if __name__ == '__main__':filename = 'test.jpeg'StaticDetect(filename)
3 致谢
感谢 Datawhale提供的帮助和支持。
这篇关于第14期(六月)组队学习 Task3:Haar特征描述算子-人脸检测的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!