今天用Opencv库来实现简单的人脸检测。
简单来说,人脸检测就是在一副图像中找到人脸,在某些情况下还有要用bounding box将其框出来。那么怎么找呢?
这就需要机器学习的知识,需要构建一个人脸分类器,首先收集人脸样本,这些作为正样本,在收集不是人脸的样本作为负样本。然后提取样本的特征(特征提取是一个大学问,一会儿后面介绍)这些样本特征是一个高维向量,将这些特征和对应的标签送入分类器进行训练,这种学习方式是supervised learning。
-
特征提取
好,那该如何提取一幅图像的特征呢?图像由像素组成,每一个像素点又是由RGB三通道的不同值组成,也就是X*Y*3的一个矩阵,为了处理方便将图像灰度化处理:
Gray(x,y)=R*0.3+G *0.59+B*0.11
这样就转化为灰度图像了,opencv库里有自带的函数可以直接调用。
转化为灰度图像之后就可以计算特征了,这里使用的是Haar特征,其他的还有HOG特征等等。Haar-like特征是用如下一些黑白矩形计算的特征
Haar特征.jpg
黑色区域的像素和减去白色区域的像素和得到的就是特征值,不同的黑白矩形能表征不一样的图像特征,一般计算一幅图像的特征值计算量较大,采用积分图的方法,遍历一遍图像就可以计算所有特征值,也是一种动态规划算法,这里略去不细讲。
- 有了特征接下来就是训练分类器了,在人脸检测方面用的是级联强分类器。
- 先用训练样本训练一个弱分类器,调整阈值达到较小的误判率,这样的分类器为最优弱分类器。
- 重新改变样本分布的权重,加大那些误判样本的权重,再次训练得到第二个最优分类器。
- 训练N次得到N个最优分类器,再将N个分类器组合成一个强分类器。强分类器也就是最优弱分类器的加权投票。
- 只有一个强分类器还是不够,再用多个强分类器级联就构成了最终的人脸分类器。
-
进行人脸检测
有了分类器就可以进行人脸检测了,对于被检测图像采用滑动窗口的检测方法,在子窗口中计算特征值,有分类器进行检测。由于图像人脸大小不一,所以需要对图像Scaling。
附上代码(opencv库已经很完善了):
#-*-coding:utf-8-*-
import numpy as np
import cv2
import os
#定义人脸检测函数
def Face_Detect(gray):
#将图像灰度化
#gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#opencv有已经训练好的分类器可以直接加载使用
#加载Haar级联分类器
faces_cascade=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#滑动窗口检测,返回有人脸的区域坐标,1.3为窗口每次缩放的倍数,
faces=faces_cascade.detectMultiScale(gray,1.3,5)
result=[]
for (x,y,width,height) in faces:
result.append((x,y,x+width,y+height))
return result
#定义眼睛检测函数
def Eye_Detect(gray):
#gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
eye_cascade=cv2.CascadeClassifier('haarcascade_eye.xml')
eyes=eye_cascade.detectMultiScale(gray,1.3,5)
result=[]
for (x,y,width,height) in eyes:
result.append((x,y,x+width,y+height))
return result
#检测并框出人脸和眼睛
def Draw_features(img_name):
#检测人脸和眼睛,在检测出人脸的区域内检测眼睛,防止眼睛检测在非人脸区域出现
#读取图像并灰度化
img=cv2.imread(img_name)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#检测人脸
faces=Face_Detect(gray)
#在原图上框出人脸
if faces:
for (x1,y1,x2,y2) in faces:
cv2.rectangle(img,(x1,y1),(x2,y2),(255,255,0),thickness=8)
face_region=gray[y1:y2,x1:x2]
eyes=Eye_Detect(face_region)
if eyes:
for (xa,ya,xb,yb) in eyes:
cv2.rectangle(img,(xa+x1,ya+y1),(xb+x1,yb+y1),(154,250,0),thickness=6)
cv2.imwrite('C:\\Users\Administrator\Desktop\Draw_fetures.jpg',img)
#Test
if __name__=='__main__':
filename='C:\\Users\Administrator\Documents\Tencent Files\\1246540310\FileRecv\MobileFile\me2.jpg'
Draw_features(filename)
眼睛的检测效果没有那么好,把我的嘴角和后面人的腿都检测出来了
Draw_fetures.jpg
网友评论