opencv入门:人脸检测

人脸识别

实现人脸识别之前要先进行人脸检测,然后才能判断这个人是谁

人脸检测

预测离散值时,进行的是分类,对于只涉及两个类别的 二分任务,我们通常将其中一个类称为 正类(正样本),另一个就是负类(反类,负样本)。

例如,在人脸检测中,主要任务就是构造可以区分包含人脸实例和不包含人脸实例的分类器。分为包含人脸的正类,不包含的负类。

发展

opencv提供了三种不同的训练好的级联分类器。

  1. 级联分类器
    通常情况下,分类器需要对多个图像特征进行识别。例如,识别一个动物是不是狗(正类),还是其他动物(负类),我们可能需要根据多个条件进行判断,这样下来就很繁琐,但是如果我们先比较他们有几条腿,有四条腿的被判断为可能为狗。。并对此范围内的对象进行分析和判断,没有四条腿的动物直接否决,不可能是狗,,这样仅比较腿的数目就可以排除样本集中大量的负类。这就是级联分类器,就是将多个简单的分类器按照一定的顺序级联成的。

优势就是经过开始阶段的简单判断可以排除掉明显不符合要求的实例,这就大大加快了后面分类的速度。OpenCV 提供了用于训练级联分类器的工具,也提供了训练好的用于人脸定位的级联分类器,都可以作为现成的资源使用。。。。蛮想知道具体是怎么实现的。。。

  1. Haar级联分类器
    opencv提供了已经训练好的 Haar 级联分类器用于人脸定位。假设两幅 4 X 4 大小的图像,针对这两幅图像我们可以通过简单的计算来判断它们在左右关系这个维度是否有相关性。
    在这里插入图片描述
    用两幅图像左侧像素值之和减去右侧像数值之和:左图,(128+96) - (108+76) = 40 ,同理右侧算得 也是40. 所以我们可以认为在左侧像数值之和减去右侧像数值之和这个角度,这两个图像具有一定的相关性。

进一步扩展,我们可以从更多的角度考虑图像的特征。有群大牛就提出了 Haar特征,这些特征包含垂直特征,水平特征和对角特征。利用这些特征,他们实现了行人检测和人脸检测。
在这里插入图片描述

Haar特征反应的是图像的灰度变化,将像素划分为模块后求差。Haar特征用黑白两种矩形框组合成特征模板,在特征模板内,用白色矩形像素块的像素和减去黑色矩形像素块的像数来表示改模板的特征。 经过上述处理,人脸的一些特征就可以用矩形框的差值简单表示。比如,眼睛的颜色比脸颊的颜色要深,鼻梁两侧的颜色比鼻梁的颜色深,唇部的颜色比唇部周围的颜色深。关于Harr特征的矩形框,有如下三个变量:

  • 矩形位置,矩形框要逐像素的遍历整个图像获取每个位置的差值。
  • 矩形大小,矩形的大小可以根据需要做任何调整。
  • 矩形类型,包含垂直,水平,对角等不同类型。

这三个变量保证了可以细致全面的获取图像的特征信息。但是变量的个数越多,特征的数量也就越多。例如一个 24X24 的检测窗口就有仅 20万个特征数量。

后来,学者提出使用积分图像快速计算 Haar 特征的方法。提出通过构造积分图,让Haar 特征可以通过查表法和有限次简单运算快速获取,极大的减少了运算量。同时他们提出通过构造级联分类器让不符合条件的背景图像(负样本)被快速的抛弃,从而能够将算力运用在可能包含人脸的对象上。

为了进一步提高效率,又有学者提出对 Haar 特征库进行扩展。将 Haar 特征进一步划分为4类。另外他们认为 对角特征和线特征的第5个和第7个 是相近的,通常下无序重复计算。同时他们还给出了计算Haar 特征数的方法,快速计算方法,以及级联分类器的构造方法等
在这里插入图片描述
opencv 就是在上述基础上,实现了将 Haar级联分类器用于人脸部特征的定位。我们可以直接调用 Opencv自带的Haar 级联分类器来实现人脸定位。除此之外,还提供了使用 Hog特征 和 LBP 算法的级联分类器。Hog主要用于行人检测,LBP 算法也是用来人脸检测的。

基本原理

  1. Haar-like算法原理脑补链接
    本质上这就是一个特征提取的算法,可以理解成为一个窗口,这个窗口将在图像中做步长为1的滑动,最终遍历整个图像计算白色像数值之和减去黑色像数值之和。从四个扩展到14个增加了旋转性,可以得到更丰富的边缘信息。但想想就知道需要计算多少次,,于是就使用积分图来进行快速计算(积分图跟haar 没有关系的)。

积分图是(Integral Image)类似动态规划的方法,主要的思想是将图像从起点开始到各个点所形成的矩形区域像素之存在数组中,当要计算某个区域的像素和时可以直接从数组中索引,不需要重新计算这个区域的像素和,从而加快了计算。

在这里插入图片描述
然后我们进行haar 特征提取。每个特征都可以获得一个值,注意有14个模板,另外模板的大小,位置还可以改变(之前提到过的矩形框的三个变量)这样就可以获得同一图片不同的特征这样就会有十几万个不同的特征(具体怎么通过模板获得那么多特征,那就是数学之美了),那么如何从十几万个特征中选出最佳的特征。这个挑选组合的工作就是Adaboost和级联来做的了。通过Adaboost迭代来挑选哪些类型特征更有价值。

  1. Adaboost脑补链接
    这个就是一种用来分类的算法。基本原理就是,三个臭皮匠顶个诸葛亮。。(人家总结的就是好)
    在这里插入图片描述
    在训练模型时,我们输入几万张人脸图(正图形)和好几万张非人脸图(负图像),缩放为 20*20 像素,然后使用haar 进行特征提取(怪不得好训练几天),在选取最佳特征时,经所有特征应用于图像,对于每个特征 adaboost 算法会找到最佳的阈值,这个阈值将人脸分为正面和负面(非人脸),显然会出现错误或分类错误,我们选择错误率最低的特征,这意味着它们是对人脸和非人脸图像进行最准确分类的特征。这个过程是很复杂的,开始时每个图像的权重相同,一次分类后,错误的分类权重增加(参考上图),然后执行相同的过程,重新计算错误率,重新计算新的权重然后再重复,直到达到所需精度或错误率或找到所需的特征数量为止。脑补链接。。感觉这个不错,虽然我看不懂。。。

最终分类器是这些弱分类器的加权和,弱分类就是说靠他自己是不能对图像完成分类,需要与其他弱分类构成强分类器。这就可以大大减少特征。但是对于一个照片特征还是太多了,图像中,大多数图像是非面部区域,就可以使用级联分类器。

  1. 级联分类器
    在这里插入图片描述

经过级联分类器,将6000多个特征经过38个阶段最终可以评估出10个。。下面就是从adaboost 获取的两个最佳特征。
在这里插入图片描述
这样经过训练获得一个人脸检测器,就可以输入图片进行检测啦。。。

级联分类器的使用

为了训练针对特定类型对象的级联分类器,opencv提供了专门的软件工具。opencv_createsamples.exe 和 opencv_traincascade.exe,这两个软件可以用来训练级联分类器(不知道为啥4.4没有,,又下了个3.4)。但是很耗时间,如果训练的数据量大,可能需要好几天(我也不会啊,,看来要抓紧时间去看机器学习了),在opencv中有一些已经训练好的级联分类器,这些分类器可以用来检测人脸,脸部特征(眼睛,鼻子),人类和其他物体,这些级联分类器以 XML 文件的形式放在 源文件的 data 目录下,加载不同的级联分类器的 XML 文件就可以实现对不同对象的检测。

在这里插入图片描述
以上就是部分 haar 级联分类器,加载级联分类器的语法格式:<CascadeClassifier object> = cv2.CascadeClassifier( filename )
注意如果你用的 pip 安装的 opencv ,那是都没有的,你可以下个去data文件夹内查找XML 文件,或者直接在网络上下个XML 文件然后直接使用。

函数介绍

objects = cv2.CascadeClassifier.detectMultiScale( image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]] ) 这个就可以检测图片内所有的人脸。函数由分类器对象调用。

  • image 待检测图像,通常是灰度图
  • scaleFactor 表示前后两次相继的扫描中,搜索窗口的缩放比例。
  • minNeighbors: 表示构成检测目标的相邻矩形的最小个数,默认3,意味着有3个以上的检测标记存在时,才认为人脸存在。如果希望提供准确率可以提高,但同时有可能一些人脸无法检测。
  • flags,通常省略。
  • minSize 目标的最小尺寸,小于这个尺寸的就会被忽略。
  • maxSize 目标的最大尺寸,大于这个尺寸的就忽略。
  • objects 返回目标对象的矩形框向量组。
import cv2
# 读取待检测的图像
image = cv2.imread('fcz.jpg')
# 获取 XML 文件,加载人脸检测器
faceCascade = cv2.CascadeClassifier(r'D:\opencv\sources\data\haarcascades\haarcascade_frontalface_default.xml')
# 色彩转换,转换为灰度图像
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
# 调用函数 detectMultiScale
faces = faceCascade.detectMultiScale(
 gray,
 scaleFactor = 1.12,      # 这几个参数根据实际调调就行。
 minNeighbors = 2,
 minSize = (5,5)
)
print(faces)
# 打印输出的测试结果
print("发现{0}个人脸!".format(len(faces)))
# 逐个标注人脸
for(x,y,w,h) in faces:
    cv2.rectangle(image,(x,y),(x+w,y+w),(0,255,0),2) #矩形标注
#  cv2.circle(image,(int((x+x+w)/2),int((y+y+h)/2)),int(w/2),(0,255,0),2)
# 显示结果
cv2.imshow("dect",image)
cv2.waitKey(0)

在这里插入图片描述

正脸识别女将军和紫薯精的侧脸识别不出来。。。额,,以前觉得人脸识别应该是几千行代码 超多模块。。。结果就这,,封装的太简单不就没那味了嘛,,,狗头

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值