OpenCv学习笔记7--人脸识别之特征脸算法

此opencv系列博客只是为了记录本人对<>的学习笔记,所有代码在我的github主页https://github.com/RenDong3/OpenCV_Notes.

欢迎star,不定时更新...

人脸检测是OpenCV的一个很不错的功能,它是人脸识别的基础。什么是人脸识别?其实就是一个程序能够识别出给定图像或者视频中的人脸。实现这一目标的方法之一是用一系列分好类的图像(人脸数据库)来训练,并基于这些图像进行识别。

人脸识别所需要的人脸库可以通过两种方式来获得:自己获得图像或从人脸数据库免费获得可用的人脸图像,互联网上有许多人脸数据库,这里以ORL人脸库(包含40个人的每人10张人脸的共400张人脸)为例,ORL人脸库中每一张图像大小为92x112,我们要想对这些样本进行人脸识别,必须要在包含人脸的样本图像上进行人脸识别。除了要识别ORL人脸库,我们也还想要识别出自己,所以我们还需要准备自己的图像。

一 生成自己的人脸图像

我们通过摄像头采集自己的人脸,大约10张图像就可以,我们需要把图像调整为92x112的大小,并且保存到一个指定文件夹,文件名后缀为.pgm。代码如下:

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import os
'''

       created on  10:24:27 2018-11-18

       @author:ren_dong
        
       人脸识别  调用摄像头进行个人头像数据采集,作为数据库
       
       只是在原来检测人脸目标框的基础上,添加了resize()函数进行图像的resize,
       然后调用imwrite()函数进行保存到指定路径下
        
'''

def Generate_name():

    # data = input('data:')
    #
    # name = input('input your name:')
    #
    # path = os.path.join(data, name)
    #
    # if os.path.isdir(path):
    #     os.remove(path)
    #     os.removedirs(path)

    #
    # os.mkdir(path)

    face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml')

    camera = cv2.VideoCapture(0)
    cv2.namedWindow('myself')
    count  = 1

    while(True):

        ret, frame = camera.read()

        if ret:
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

            faces = cv2.CascadeClassifier.detectMultiScale(face_cascade, gray, 1.3, 5)

            for (x, y, w, h) in faces:
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)

                f = cv2.resize(gray[y:y+h, x:x+w], (92, 112))

                cv2.imwrite('./data/ren_dong/%s.pgm' % str(count), f)

                count += 1

            cv2.imshow('myself', frame)

            if cv2.waitKey(35) & 0xff == ord('q'):
                break

    camera.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    Generate_name()

这里在cv2.imwrite()函数中我指定了存储路径,所以大神的前几行我给注释了,程序运行后在data文件夹下会有ren_dong文件夹存放了十张后缀名为.pgm的图片.

OpenCv学习笔记7--人脸识别之特征脸算法_第1张图片

 这里data下还包含从orl人脸数据库下载的其他40类人脸图片数据.

二 人脸识别(OpenCV)

OpenCV 3有三种人脸识别的方法,它们分别基于不同的三种算法,Eigenfaces,Fisherfaces和Local Binary Pattern Histogram。

这些方法都有一个类似的过程,即都使用分好类的训练数据集来进行训练,对图像或视频中检测到的人脸进行分析,并从两方面来确定:是否识别到目标;目标真正被识别到的置信度的衡量,这也称为置信度评分,在实际应用中可以通过设置阈值来进行筛选,置信度高于该阈值的人脸将会被丢弃。

这里我们主要来介绍一下利用特征脸进行人脸识别的方法,特征脸法,本质上其实就是PCA降维,这种算法的基本思路是,把二维的图像先灰度化,转化为一通道的图像,之后再把它首尾相接转化为一个列向量,假设图像大小是20*20的,那么这个向量就是400维,理论上讲组织成一个向量,就可以应用任何机器学习算法了,但是维度太高算法复杂度也会随之升高,所以需要使用PCA算法降维,然后使用简单排序或者KNN都可以。

1、准备数据

我们先来准备训练所需要的数据,这里我们需要的数据有训练的图像,每个图像对应的标签以及标签对应的真实姓名。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import os

'''

       created on  10:24:27 2018-11-18

       @author:ren_dong

       人脸识别  
       利用数据进行数据集制作

'''


# 2、读取ORL人脸数据库 准备训练数据
def LoadImages(data):
    '''
    加载数据集
    params:
        data:训练集数据所在的目录,要求数据尺寸大小一样
    ret:
        images:[m,height,width]  m为样本数,height为高,width为宽
        names:名字的集合
        labels:标签
    '''
    images = []
    labels = []
    names = []

    label = 0
    # 过滤所有的文件夹
    for subDirname in os.listdir(data):

        subjectPath = os.path.join(data, subDirname)
        #subjectpath即每一类所在的文件夹
        if os.path.isdir(subjectPath):
            # 每一个文件夹下存放着一个人的照片
            names.append(subDirname)
            ##得到图片名字filename

            for fileName in os.listdir(subjectPath):
                #路径拼接,得到图片路径
                imgPath = os.path.join(subjectPath, fileName)
                #遍历路径按照文件名 读取图片
                img = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE)
                #添加images
                images.append(img)
                #添加label
                labels.append(label)
            label += 1
    images = np.asarray(images)
    labels = np.asarray(labels)
    return images, labels, names


if __name__ == '__main__':
    data  = './data'
    LoadImages(data)

 此程序对数据集进行label的添加,用来下一步的训练.

2、人脸识别

有了训练数据之后,我们就可以直接调用OpenCV 3的人脸识别库进行训练,训练好之后,就可以进行识别:

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import os
import shutil

'''

       created on  10:24:27 2018-11-18

       @author:ren_dong

       人脸识别  调用摄像头进行个人头像数据采集,作为数据库

       只是在原来检测人脸目标框的基础上,添加了resize()函数进行图像的resize,
       然后调用imwrite()函数进行保存到指定路径下

'''

# -*- coding: utf-8 -*-
"""
Created on Thu Aug 16 19:41:19 2018

@author: lenovo
"""

'''
调用opencv库实现人脸识别
'''

# 读取pgm图像,并显示
def ShowPgm(filepath):
    cv2.namedWindow('pgm')
    img = cv2.imread(filepath)
    cv2.imshow('pgm', img)
    print(img.shape)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 2、读取ORL人脸数据库 准备训练数据
def LoadImages(data):
    '''
    加载数据集
    params:
        data:训练集数据所在的目录,要求数据尺寸大小一样
    ret:
        images:[m,height,width]  m为样本数,height为高,width为宽
        names:名字的集合
        labels:标签
    '''
    images = []
    labels = []
    names = []

    label = 0
    # 过滤所有的文件夹
    for subDirname in os.listdir(data):

        subjectPath = os.path.join(data, subDirname)
        #subjectpath即每一类所在的文件夹
        if os.path.isdir(subjectPath):
            # 每一个文件夹下存放着一个人的照片
            names.append(subDirname)
            ##得到图片名字filename

            for fileName in os.listdir(subjectPath):
                #路径拼接,得到图片路径
                imgPath = os.path.join(subjectPath, fileName)
                #遍历路径按照文件名 读取图片
                img = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE)
                #添加images
                images.append(img)
                #添加label
                labels.append(label)
            label += 1
    images = np.asarray(images)
    labels = np.asarray(labels)
    return images, labels, names


def FaceRec(data):
    # 加载训练数据
    X, y, names = LoadImages('./data')


    model = cv2.face.EigenFaceRecognizer_create()
    model.train(X, y)

    # 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
    face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml')

    # 打开摄像头
    camera = cv2.VideoCapture(0)
    cv2.namedWindow('Dynamic')

    while (True):
        # 读取一帧图像
        ret, frame = camera.read()
        # 判断图片读取成功?
        if ret:
            gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            # 人脸检测

            faces = face_cascade.detectMultiScale(gray_img, 1.3, 5)
            for (x, y, w, h) in faces:
                # 在原图像上绘制矩形
                frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
                roi_gray = gray_img[y:y + h, x:x + w]

                try:
                    # 宽92 高112
                    roi_gray = cv2.resize(roi_gray, (92, 112), interpolation=cv2.INTER_LINEAR)
                    params = model.predict(roi_gray)
                    print('Label:%s,confidence:%.2f' % (params[0], params[1]))
                    cv2.putText(frame, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)
                except:
                    continue

            cv2.imshow('Dynamic', frame)
            # 如果按下q键则退出
            if cv2.waitKey(100) & 0xff == ord('q'):
                break
    camera.release()
    cv2.destroyAllWindows()


if __name__ == '__main__':
    # ShowPgm('./face/s1/1.pgm')
    data = './data'
    # 生成自己的人脸数据
    # generator(data)
    FaceRec(data)

 这里我们cv2.face.EigenFaceRecognizer_create()创建人脸识别模型,通过图像数组和对应标签数组来训练模型,EigenFaceRecognizer_create()函数有两个可以设置的重要参数:第一个是想要保留的主成分数目,第二个是指定的置信度阈值,这是一个浮点数。

接下来,重复与人脸检测操作类似的过程。通过在检测到的人脸上进行人脸识别,注意这里有两个步骤:

1、将检测到人脸调整为指定的大小92x112,即与训练集图像尺寸一样;

2、调用prdict()函数进行预测,该函数返回有两个元素的数组,第一个元素是所识别个体的标签,第二个是置信度评分,用来衡量所识别人脸与原模型的差距,0表示完全匹配。

注意:Eigenfaces/Fisherfaces和LBPH的置信度评分值完全不同,Eigenfaces和Fisherfaces将产生0到20000的值,而任意低于4000到5000的评分都是相当可靠的识别。LBPH有着类似的工作方式,但是一个好的识别参考值要低于50,任意高于80的参数值都被认为是低的置信度评分。

 

另外本人大量引用大神的博客,这里给出原文链接,原博客中还进行了特征脸算法的原理推导和coding,进行了自定义的人脸检测,本人并未对此部分进行复现,所以感兴趣的童鞋可以移步到大神的博客主页观看,不仅排版比我好,而且界面简洁,我很喜欢,我的博客只是记录用的,不要怪我的杂乱..  [捂脸]

你可能感兴趣的:(OpenCV笔记,opencv,人脸检测,人脸识别)