基于OpenCV的人脸及笑脸检测
文章目录
- 基于OpenCV的人脸及笑脸检测
- 写在前面
- 准备工作
- OpenCV haar分类器
- 检测过程
- 输出结果
- 有些问题
- 解决问题
- 写在后面
写在前面
你好,我是禅墨!
好久,没见!要从一个玩笑说起
今天禅墨和小凯打赌:
小凯:这儿有一堆(200+)图片,看谁能快速地挑出带有笑脸的图片
禅墨:就你?说赌约吧
小凯:你不是惦记K210吗?就它了
禅墨:成交!给我一点时间。
准备工作
- 首先要快速地分拣出微笑的照片,就是进行人脸检测
- 然后在人脸区域对特征进行检测,通过对比嘴型的特征,找出笑脸
- 结果预览
OpenCV haar分类器
图片处理用什么?当然是OpenCV啊
既然是检测笑脸,如果通过特征的方式,那就绕不开Hear特征分类器
Haar-like特征最早是由Papageorgiou等人用于物体检测的数字图像特征,而Viola和Jones在此基础上,使用3种类型4种形式的特征。
Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。
如果自己找人脸训练特征的话,需要花费时间和大量的素材,那今天就采用OpenCV官方给出的训练结果!
导入检测器
face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
smile_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_smile.xml')
检测过程
不管是检测人脸还是检测笑脸,都会用到 detectMultiScale() 函数进行标记
此函数的作用是,在输入图像中检测不同尺寸的对象,返回包含对象的矩形框。
- image——输入图像
- scaleFactor——表示每轮检测图像齿轮减少的比例
- minNeighbors——指明对象要至少被检测到几次才能判定对象确实存在
- minSize——检测对象的最小尺寸
- maxSize——检测对象的最大尺寸
# 检测脸部
faces = face_cascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30),
flags=cv2.CASCADE_SCALE_IMAGE)
print('Detected ', len(faces), " face")
在人脸检测之后,需要标记出人脸位置,然后在此位置内进行笑脸的检测
# 标记位置
for (x, y, w, h) in faces:
img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
# cv2.circle(img, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 1)
roi_gray = gray[y: y + h, x: x + w]
roi_color = img[y: y + h, x: x + w]
#笑脸
smile = smile_cascade.detectMultiScale(roi_gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(30, 30))
for (sx, sy, sw, sh) in smile:
cv2.rectangle(roi_color, (sx, sy), (sx + sw, sy + sh), (0, 255, 0), 2)
为了更直观的在图片窗口反映结果,在左上角对结果进行标记
需要用到 putText() 函数
label = 'Result: Detected ' + str(len(faces)) +" faces !"
cv2.putText(img, label, (10, 20),
cv2.FONT_HERSHEY_COMPLEX,
0.3, (0, 0, 0), 1)
各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字体粗细。
输出结果
有些问题
来看多人的
大家都发现了吧,会圈出一些不是笑脸的地方,特别有意思的是衣服上的达芬奇都能够圈出来,说明还是训练结果还是很好的
一方面可能与像素有关,另一方面也可能与训练结果有关,个人猜测是特征种类不够多,特征不太明显
解决问题
为什么会出现这个呢,好吧,完全是我个人问题,为了图省事,detectMultiScale()函数没有写全,现在补上(已更新代码块)
需要注意的是不同的图片需要调minNeighbors的值
如果想要做一个完整的,就仿照上面标记人脸数的方法判断,
出人脸的跳出,具体怎么搞就不多说了,
目前成功率95%以上
贴出正常状态图片
再来看美女
写在后面
好了,今天就到这里了,去撸K210了
关于那些问题,欢迎在评论区交流!
微信公众号:兴趣路人甲