基于OpenCV的人脸及笑脸检测

基于OpenCV的人脸及笑脸检测

写在前面

你好,我是禅墨!

好久,没见!要从一个玩笑说起

今天禅墨和小凯打赌:

小凯:这儿有一堆(200+)图片,看谁能快速地挑出带有笑脸的图片

禅墨:就你?说赌约吧

小凯:你不是惦记K210吗?就它了

禅墨:成交!给我一点时间。

准备工作

  1. 首先要快速地分拣出微笑的照片,就是进行人脸检测
  2. 然后在人脸区域对特征进行检测,通过对比嘴型的特征,找出笑脸
  3. 结果预览

在这里插入图片描述

OpenCV haar分类器

图片处理用什么?当然是OpenCV啊

既然是检测笑脸,如果通过特征的方式,那就绕不开Hear特征分类器

Haar-like特征最早是由Papageorgiou等人用于物体检测的数字图像特征,而ViolaJones在此基础上,使用3种类型4种形式的特征。

Haar特征分为三类:边缘特征、线性特征、中心特征和对角线特征,组合成特征模板。特征模板内有白色和黑色两种矩形,并定义该模板的特征值为白色矩形像素和减去黑色矩形像素和。Haar特征值反映了图像的灰度变化情况。例如:脸部的一些特征能由矩形特征简单的描述,如:眼睛要比脸颊颜色要深,鼻梁两侧比鼻梁颜色要深,嘴巴比周围颜色要深等。但矩形特征只对一些简单的图形结构,如边缘、线段较敏感,所以只能描述特定走向(水平、垂直、对角)的结构。
这类矩形特征模板由两个或多个全等的黑白矩形相邻组合而成,而矩形特征值是白色矩形的灰度值的和减去黑色矩形的灰度值的和,矩形特征对一些简单的图形结构,如线段、边缘比较敏感。如果把这样的矩形放在一个非人脸区域,那么计算出的特征值应该和人脸特征值不一样,所以这些矩形就是为了把人脸特征量化,以区分人脸和非人脸。

如果自己找人脸训练特征的话,需要花费时间和大量的素材,那今天就采用OpenCV官方给出的训练结果!

导入检测器

face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
smile_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_smile.xml')

检测过程

不管是检测人脸还是检测笑脸,都会用到 detectMultiScale() 函数进行标记

此函数的作用是,在输入图像中检测不同尺寸的对象,返回包含对象的矩形框。

  1. image——输入图像
  2. scaleFactor——表示每轮检测图像齿轮减少的比例
  3. minNeighbors——指明对象要至少被检测到几次才能判定对象确实存在
  4. minSize——检测对象的最小尺寸
  5. 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了

关于那些问题,欢迎在评论区交流!

微信公众号兴趣路人甲在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章