Python语言OpenCV开发之人脸检测和识别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Eric_lmy/article/details/80962707

前言

使计算机视觉成为极具吸引力学科的原因之一就是:它正在逐步的变成现实,人脸检测就是例证。在现实生活中人脸检测可用于各行各业,而OpenCV提供了人脸检测的算法。
本节会讲述OpenCV中人脸检测函数以及如何识别人脸。

正文

1、 Haar级联
人脸检测技术主要涉及到Haar特征、积分图和Haar级联三大类。Haar特征分为四类:边缘特征、线性特征、中心特征和对角线特征,将这些特征组合成特征模板。计算Haar的特征值需要计算图像中封闭矩形区域的像素值之和,在不断改变模版大小和位置的情况下,需要计算大量的多重尺度区域,这可能会遍历每个矩形的每个像素值且同一个像素如果被包含在不同的矩形中会被重复遍历多次,这就导致了大量的计算和高复杂度,因此提出积分图的概念。Harr级联是一个基于Haar特征的级联分类器,级联分类器是什么?它是一个把弱分类器串联成强分类器的过程。弱分类器和强分类器分别是什么?弱分类器是性能受限的分类器,它们没法正确地区分所有事物。如果你的问题很简单 弱分类结果可接受。强分类器可以正确的对数据进行分类。
建立一个实时系统需要保证分类器运行良好并且足够简单。唯一需要考虑到的是简单分类器不够精确,若试图更精确就会变成计算密集型且运行速度慢。精确度和速度的取舍在机器学习中相当常见。所以串联一群弱分类器形成一个统一的强分类器可以解决这个问题。弱分类器不需要太精确,串联起来形成的强分类器具有高精确度。
1.1 获取Haar级联数据
去OpenCV官网下载OpenCV源码,解压出来会有一个data/haarcascades的目录,这个文件夹下包含了所有OpenCV的人脸检测的XML文件。这些文件可用于检测静态图片、视频和摄像头所得到的图像中的人脸。如下图所示:
enter image description here
这些文件在下面的程序当中会用到。这些人脸级联数据·文件需要的事正面的人脸图像。
2、 人脸检测
在静态图像或视频中检测人脸的操作是非常相似的,视频人脸检测只是从摄像头读取每帧图像,然后 静态图像中的人脸检测方法进行检测。当然,视频人脸检测还涉及其他的概念,例如跟踪,而静态图像中的人脸加成呢就没有这样的概念,但他们的基本理论是一致的。
2.1 在静态图像中检测人脸
首先是加载图像,其次是检测人脸,检测到人脸后在人脸周围绘制矩形框。实例如下:

import cv2  
filename = 'test.jpg'

def detect(filename):
    face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')# 声明face_cascade为CascadeClassifier对象,它负责人脸检测。

    img = cv2.imread(filename)# 加载图像
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 转换为灰度图像
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)# 人脸检测
    for (x,y,w,h) in faces:
        img = cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)# 绘制矩形框
    cv2.imshow('dd', img)# 显示
    cv2.imwrite('dd.jpg', img)# 保存
    cv2.waitKey(0)

detect(filename)

说明:face_cascade.detectMultiScale()函数的参数处理图像为,其他的分别是scaleFactor和minNeighbors,分别表示人脸检测过程中每次迭代时图像的压缩率以及每个人脸矩形保留近邻数目的最小值,可在官方文档中查看所有选项的内容。
enter image description here
短短几行代码就能检测数人脸,是不是很神奇啊。
2.2 在视频中检测人脸
在视频帧上重复上面的检测过程就能完成视频中的人脸检测。
步骤如下:1打开摄像头\视频文件,读取帧,检测人脸,扫描检测到的人脸中的眼睛,然后绘制矩形框;

import cv2

def detect():
    face_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier('haarcascades/haarcascade_eye.xml')
    camera = cv2.VideoCapture(0)
    while(True):
        ret, frame = camera.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x,y,w,h) in faces:
            img = cv2.rectangle(frame, (x,y), (x+w,y+h), (255,0,0), 2)
            roi_gray = gray[y:y+h, x:x+w]
            eyes = eye_cascade.detectMultiScale(roi_gray, 1.03, 5, 0, (40, 40))
            for (ex,ey,ew,eh) in eyes:
                cv2.rectangle(img, (x+ex,y+ey), (x+ex+ew,y+ey+eh), (0,255,0), 2)

        cv2.imshow('camera', frame)
        if cv2.waitKey(int(1000/12)) & 0xff == ord("q"):
            break
    camera.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    detect()

enter image description here
3、 识别人脸
人脸检测时人脸识别的基础。人脸识别就是一个程序能识别出图像中的人脸。实现方法之一就是利用一系列分好类的图像(人脸数据库)来训练程序,并基于这些图像进行识别。这就是OpenCV人脸识别的过程。人脸识别模块的另一个重要的特征是:每个识别都具有置信度(confidence)评分,因此可在实际应用中通过对其设置阈值来进行筛选。人脸数据库可以通过两种方式获取,1是自己制作,2是从互联网上获取(互联网上有免费的人脸图像)。这里将使用自己生成的方式制作人脸图像进行识别。
3.1 生成人脸识别数据
图像要满足的要求:
1.图像是灰度格式,后缀为.pgm
2.图像形状为正方形
3.图像的大小要一直

    import cv2 
    import numpy as np 
    import sys 
    import os
    face_cascade = cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml')
    eye_cascade = cv2.CascadeClassifier('../haarcascades/haarcascade_eye.xml')
    camera = cv2.VideoCapture(0)
    count = 0
    while(True):
        ret, frame = camera.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x,y,w,h) in faces:
            img = cv2.rectangle(frame, (x,y), (x+w,y+h), (255,0,0), 2)
            f = cv2.resize(gray[y:y+h, x:x+w], (200, 200))

            cv2.imwrite('jm1/%s.pgm' % str(count), f)
            count+=1

        cv2.imshow('camera', frame)
        if cv2.waitKey(int(1000/12)) & 0xff == ord("q"):
            break
    camera.release()
    cv2.destroyAllWindows()

说明:这个过程为:人脸检测,裁剪灰度帧的区域,将其大小调整为200x200像素,保存到指定的文件夹中,文件后缀是.pgm。(采集很多图片)。
运行脚本,脸对着摄像头(可多做些表情出来)。如图:
enter image description here
为了进行区别,我还伪造了其他人脸的图像进行识别;jm和jm2中的其他人的图像数据,jm1是自己的。
enter image description here
3.2 人脸识别
上面得到了这些数据,需要将这些样本加载到人脸识别的算法中。首先创建一个.csv的文件,文件格式如下:

jm/1.pgm;0
.
.
.
jm/16.pgm;0
jm/17.pgm;0
jm/18.pgm;0
jm1/1.pgm;1
jm1/2.pgm;1
.
.
jm1/16.pgm;1
jm1/17.pgm;1
jm1/18.pgm;1
jm2/1.pgm;2
.
.
jm2/17.pgm;2
jm2/18.pgm;2

分别表示某个人;人脸的ID。人脸ID就和对应的人脸对应起来了。这样在算法中逐行对这个文件读取进行识别计算。

    import cv2 
    import numpy as np 
    import sys 
    import os

    names = ['choumei','lmy','kuxiao']# 图像对应的人脸的人名
    if len(sys.argv) < 2:
        print("USAGE: xxx.py </path/to/images> [</path/to/store/images/at>]")
        sys.exit()

    [X,y] = read_images(sys.argv[1])
    # print(sys.argv[1])
    print(y)
    # print(X)
    y = np.asarray(y, dtype=np.int32)

    if len(sys.argv) == 3:
        out_dir = sys.argv[2]

    # 这里是提供了三种不同的识别方法,分别是基于Eigenfaces、Fisherfaces和LBPH的。
    model = cv2.face.EigenFaceRecognizer_create()#cv2.face.createEigenFaceRecognizer()
    # model = cv2.face.FisherFaceRecognizer_create()#cv2.face.createFisherFaceRecognizer()
    # model = cv2.face.LBPHFaceRecognizer_create()#cv2.face.createLBPHFaceRecognizer()

    model.train(np.asarray(X), np.asarray(y))
    camera = cv2.VideoCapture(0)
    face_cascade = cv2.CascadeClassifier('../haarcascades/haarcascade_frontalface_default.xml')

    while (True):
        read, img = camera.read()
        faces = face_cascade.detectMultiScale(img, 1.3, 5)
        for (x,y,w,h) in faces:
            img = cv2.rectangle(img, (x,y), (x+w,y+h), (255,0,0), 2)
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            roi = gray[x:x+w, y:y+h]
            try:
                roi = cv2.resize(roi, (200,200), interpolation=cv2.INTER_LINEAR)
                params = model.predict(roi)
                print("Label:%s, Confidence:%.2f" % (params[0], params[1]))
                cv2.putText(img, names[params[0]], (x, y-20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
            except:
                continue
        cv2.imshow('camera', img)
        if cv2.waitKey(int(1000/12)) & 0xff == ord('q'):
            break
    cv2.destroyAllWindows()

运行方式是:python xxx.py . # 注意要加上路径,这是为了找到.csv文件
说明:函数predict()返回的有两个元素的数组,第一个是所识别个体的标签,第二个是置信度评分。所有的算法都有一个置信度评分阈值,用来衡量所有识别人脸与沿模型的差距,0表示完全匹配。
enter image description here
结语:
人脸检测和人脸识别是计算机视觉不断发展的分支,其算法也在不断发展,现在已经应用到了很多领域。检测和识别的精度大部分取决于训练数据的质量,因此,要为应用程序提供高质量的人脸数据库,采集数据的时候尽量使用高清摄像头。谢谢!

猜你喜欢

转载自blog.csdn.net/Eric_lmy/article/details/80962707