前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV 人脸检测(二)

OpenCV 人脸检测(二)

作者头像
用户6021899
发布2019-09-25 10:55:37
1.6K0
发布2019-09-25 10:55:37
举报

本篇介绍在人脸检测的基础上对眼睛进行检测。下面这个分类器用于检测眼睛。

代码语言:javascript
复制
cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')

除非是外星人,眼睛通常不会跑到脸部以外。所以我们只需在人脸矩形框的范围内检测眼睛。

以下图为例,我们想以红色矩形标记脸部区域,蓝色矩形标记眼睛区域。

代码语言:javascript
复制
import cv2
import numpy as np
from matplotlib import pyplot as plt

def detect(img):
   
    gray =cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
    front_face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')#检测正脸
    faces0 = front_face_cascade.detectMultiScale(gray, 1.1, 6)
    print("共检测到%d张人的正脸" %len(faces0))
    eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')#检测眼睛
   
    for (x, y, w, h) in faces0:
        eye_detected = False
        print(w,h)
       
        face_area = gray[y: y+h, x: x+w] # (疑似)人脸区域
        #eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0, (40,40)) #在人脸区域检测眼睛
        eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0)#在人脸区域检测眼睛
        for (ex,ey,ew,eh) in eyes:
            print(" ",ew,eh)
            #if ew/w > 0.18:
            cv2.rectangle(img, (x+ex,y+ey),(x+ex+ew, y+ey+eh), (255,0,0),2) #画蓝色色矩形框标记正脸
            eye_detected = True
        #if eye_detected: #排除掉检测不到眼睛的 疑似人脸区域
        cv2.rectangle(img, (x,y), (x+w,y+h), (0,0,255), 2) #画红色矩形框标记正脸
    return img
    
img0= cv2.imread("face.png")
img = detect(img0)
plt.subplot(1,1,1)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title("OpenCV 人脸检测",fontSize =16, color="b")
plt.show()

检测结果如下:

我们发现对于上图,人脸和眼睛的检测都产生了假阳性。花朵被检测成了人脸,鼻子和嘴巴被误认为是眼睛。

我们可以做简单合理的假设,只有检测出眼睛的疑似人脸区域才能被检测为人脸,只有尺寸适中、位置偏人脸上部的疑似眼睛区域才能被识别成眼睛。按照上述原则我们对代码进行优化:

代码语言:javascript
复制
def detect(img):
   
    gray =cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
   
    front_face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')#检测正脸
    faces0 = front_face_cascade.detectMultiScale(gray, 1.025, 5)
   
    eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye.xml')#检测眼睛
   
    n =0   
    for (x, y, w, h) in faces0:
        eye_detected = False
        face_area = gray[y: y+h, x: x+w] # (疑似)人脸区域
       
        #eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0, (40,40)) #在人脸区域检测眼睛
        quasi_eyes = eye_cascade.detectMultiScale(face_area, 1.03, 5, 0)#在人脸区域检测眼睛
        if len(quasi_eyes) ==0: continue
        quasi_eyes = tuple(filter(lambda x : x[2]/w>0.18, quasi_eyes)) # ex,ey,ew,eh; ew/w>0.18 #尺寸过滤
        if len(quasi_eyes) <2 : continue
        eyes = sorted(quasi_eyes, key=operator.itemgetter(1), reverse = False) # 排序,为了取ey最小的(顶部的)两只疑似眼睛
        ex,ey,ew,eh = eyes[0]
        cv2.rectangle(img, (x+ex,y+ey),(x+ex+ew, y+ey+eh), (255,0,0),2) #画蓝色色矩形框标记第1只眼睛
        ex,ey,ew,eh = eyes[1]
        cv2.rectangle(img, (x+ex,y+ey),(x+ex+ew, y+ey+eh), (255,0,0),2) #画蓝色色矩形框标记第2只眼睛
        eye_detected = True
        if eye_detected: #排除掉检测不到眼睛的 疑似人脸区域
            cv2.rectangle(img, (x,y), (x+w,y+h), (0,0,255), 2) #画红色矩形框标记正脸
            n += 1
    print("共检测到%d张人的正脸" % n)
    return img

两只眼睛一张脸,嗯,效果还不错。

我们可以做更多的测试:

红姑是侧脸,没检测出来也符合代码的逻辑。

有人说人是从猴子变的,看来也不是没有道理。。。

但是戴上眼镜,程序就认不出了。很好解决,我们换个眼睛检测的分类器即可:

代码语言:javascript
复制
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_eye_tree_eyeglasses.xml')#检测眼睛(可戴眼镜)

下面两个分类器可以单独检测图像的右眼和左眼,用法相同,不再赘述。

代码语言:javascript
复制
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_righteye_2splits.xml')#检测右边的眼睛(人物左眼)
eye_cascade = cv2.CascadeClassifier('./cascades/haarcascade_lefteye_2splits.xml')#检测左边的眼睛(人物右眼)
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档