zoukankan      html  css  js  c++  java
  • 第十节、人脸识别之特征脸算法

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

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

    一 生成自己的人脸图像

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

    #1、生成自己人脸识别数据
    def generator(data):
        '''
        生成的图片满足以下条件
        1、图像是灰度格式,后缀为.pgm
        2、图像大小要一样
        
        params:
            data:指定生成的人脸数据的保存路径
        '''
        '''
        打开摄像头,读取帧,检测帧中的人脸,并剪切,缩放
        '''
        name = input('my name:')
        #如果路径存在则删除
        path = os.path.join(data,name)
        if os.path.isdir(path):
            #os.remove(path)   #删除文件
            #os.removedirs(path)   #删除空文件夹
            shutil.rmtree(path)    #递归删除文件夹
            
        #创建文件夹
        os.mkdir(path)
        
        #创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
        face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')
        
        #打开摄像头    
        camera = cv2.VideoCapture(0)
        cv2.namedWindow('Dynamic')
        #计数
        count = 1
        
        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:
                    #在原图像上绘制矩形
                    cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
                    #调整图像大小 和ORL人脸库图像一样大小
                    f = cv2.resize(frame[y:y+h,x:x+w],(92,112))
                    #保存人脸
                    cv2.imwrite('%s/%s.pgm'%(path,str(count)),f)
                    count += 1                
                cv2.imshow('Dynamic',frame)            
                #如果按下q键则退出
                if cv2.waitKey(100) & 0xff == ord('q') :
                    break
        camera.release()
        cv2.destroyAllWindows()

    程序运行后,我们需要输入自己的姓名,这里我输入zy,并在data路径下生成了一个zy文件夹,下面保存着采集到的图像:

    二 人脸识别(OpenCV)

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

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

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

    1、准备数据

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

    #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)
            if os.path.isdir(subjectPath):                
                #每一个文件夹下存放着一个人的照片    
                names.append(subDirname)
                for fileName in os.listdir(subjectPath):
                    imgPath = os.path.join(subjectPath,fileName)
                    img = cv2.imread(imgPath,cv2.IMREAD_GRAYSCALE)
                    images.append(img)
                    labels.append(label)
                label += 1
        images = np.asarray(images)
        labels = np.asarray(labels)
        return images,labels,names

    2、人脸识别

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

    def FaceRec(data):    
        #加载训练数据
        X,y,names=LoadImages('./face')
        
        model = cv2.face.EigenFaceRecognizer_create()
        model.train(X,y)
        
        #创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
        face_cascade = cv2.CascadeClassifier('./haarcascades/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()

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

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

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

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

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

    源代码:

    # -*- coding: utf-8 -*-
    """
    Created on Thu Aug 16 19:41:19 2018
    
    @author: lenovo
    """
    
    '''
    调用opencv库实现人脸识别
    '''
    import numpy as np
    import cv2
    import os
    import shutil
    
    #读取pgm图像,并显示     
    def ShowPgm(filepath):
        cv2.namedWindow('pgm')
        img = cv2.imread(filepath)
        cv2.imshow('pgm',img)
        print(img.shape)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
                 
    
    
    #1、生成自己人脸识别数据
    def generator(data):
        '''
        生成的图片满足以下条件
        1、图像是灰度格式,后缀为.pgm
        2、图像大小要一样
        
        params:
            data:指定生成的人脸数据的保存路径
        '''
        '''
        打开摄像头,读取帧,检测帧中的人脸,并剪切,缩放
        '''
        name = input('my name:')
        #如果路径存在则删除
        path = os.path.join(data,name)
        if os.path.isdir(path):
            #os.remove(path)   #删除文件
            #os.removedirs(path)   #删除空文件夹
            shutil.rmtree(path)    #递归删除文件夹
            
        #创建文件夹
        os.mkdir(path)
        
        #创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
        face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')
        
        #打开摄像头    
        camera = cv2.VideoCapture(0)
        cv2.namedWindow('Dynamic')
        #计数
        count = 1
        
        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:
                    #在原图像上绘制矩形
                    cv2.rectangle(frame,(x,y),(x+w,y+h),(255,0,0),2)
                    #调整图像大小 和ORL人脸库图像一样大小
                    f = cv2.resize(frame[y:y+h,x:x+w],(92,112))
                    #保存人脸
                    cv2.imwrite('%s/%s.pgm'%(path,str(count)),f)
                    count += 1                
                cv2.imshow('Dynamic',frame)            
                #如果按下q键则退出
                if cv2.waitKey(100) & 0xff == ord('q') :
                    break
        camera.release()
        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)
            if os.path.isdir(subjectPath):                
                #每一个文件夹下存放着一个人的照片    
                names.append(subDirname)
                for fileName in os.listdir(subjectPath):
                    imgPath = os.path.join(subjectPath,fileName)
                    img = cv2.imread(imgPath,cv2.IMREAD_GRAYSCALE)
                    images.append(img)
                    labels.append(label)
                label += 1
        images = np.asarray(images)
        labels = np.asarray(labels)
        return images,labels,names
    
    
            
    
    def FaceRec(data):    
        #加载训练数据
        X,y,names=LoadImages('./face')
        
        model = cv2.face.EigenFaceRecognizer_create()
        model.train(X,y)
        
        #创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
        face_cascade = cv2.CascadeClassifier('./haarcascades/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 = './face'
        #生成自己的人脸数据
        #generator(data)
        FaceRec(data)
    View Code

    三 自己实现特征脸

    上面我们介绍了调用OpenCV实现的特征脸,但是我们有时候也想自己实现一下,并不想直接调用别人的库。

    假设我们有m个样本,每一个样本图片都是$w×h$大小的,可以看做$n×1$的列向量$x_i€R^n,n=w×h$,那么训练集$S={x_1,x_2,...,x_m}$,我们利用PCA把原始向量$x_i$从高维空间$R^n$变换到低维空间$R^k,k<<n$。

    PCA算法的主要步骤:

    1、先求训练集$S$的均值向量$ar{x}=frac{1}{m}sumlimits_{i=1}^{m}x_i$;

    2、向量取均值$Φ_i=x_i-ar{x}$;

    3、我们定义$A=[Φ_1,Φ_2,...,Φ_m]$,协方差矩阵$C=frac{1}{m}AA^T$;

    4、特征值分解$Cu_i=λ_iu_i$;

    我们知道协方差矩阵是一个高维矩阵$C€R^{n×n}$,如果直接进行特征分解,无疑是非常消耗资源也很费时的。特征脸算法做了一个非常巧妙的变换,我们先来看$A^TA$的特征值分解,因为$A^TA€R^{m×m}$,与$C$比起来,维度要小得多。我们可以得到:

    $$A^TAv_i=β_iv_i$$

    假设$β_1,β_2,β_3,...,β_m$是$A^TA$的特征值,$v_1,v_2,v_3,...,v_m$是特征值对应的特征向量。(考虑重根$β_i$)

    左乘$A$我们可以得到:

    $$AA^TAv_i=β_iAv_i$$

    即:$CAv_i=β_iAv_i$

    所以我们可以看到$β_1,β_2,β_3,...,β_m$也是$AA^T$的特征值,$Av_1,Av_2,Av_3,...,Av_m$是特征值对应的特征向量。但是实际上$AA^T$应该有$n$个特征值(考虑重根),以及$n$个线性无关的特征向量。

    又由于$A^TA$的$m$个特征值与特征向量对应着$AA^T$的前$m$个最大的特征值以及特征值相对应的特征向量。(这句话我也不怎么明白,$A^TA$的m个特征值为什么就是$AA^T$n个特征值中最大的前m个?)

    所以通过这种变换, 可以非常快速地求出$AA^T$的特征向量$u_i=Av_i,i=1,2,...,m$;

    注意:采用这种求特征值的方法要求$k≤m$,也就是说降维后的维数不能大于样本数。

    5、将m个特征值从大到小排序,截取前$k$个特征值及对应的特征向量。组成变换矩阵$P=[e_1,e_2,e_3...,e_k]^T,P€R^{k×n}$,$e_i$为特征向量$e_i€R^{n×1}$,则把高维向量$Φ_i$降维到低维向量$Ω_i$的变换公式为:$Ω_i = PΦ_i,Ω_i€R^{n×1},Φ_i€R^{k×1}$,由于我们训练集中有m个样本,我们先将训练集中的每个人脸图像映射到低维空间$Ω_1,Ω_2,...,Ω_m$;

    6、给定一个测试样本$x$,先做去均值$Φ=x-ar{x}$,然后再映射到低维空间,得到低维向量$Ω$,然后我们可以通过KNN来进行分类,通过计算$Ω$与$Ω_1,Ω_2,...,Ω_m$的距离,然后进行从小到大排序,选取前g个样本,分别获取每个样本对应的类别,通过投票的方式得到测试样本的类别。

     下面为实现代码:

    # -*- coding: utf-8 -*-
    """
    Created on Fri Aug 17 17:53:30 2018
    
    @author: lenovo
    """
    
    '''
    自己实现一个人脸识别
    '''
    
    '''
    人脸识别经典算法实现(一)——特征脸法:https://blog.csdn.net/freedom098/article/details/52088064
    第一种比较经典的算法就是特征脸法,本质上其实就是PCA降维,这种算法的基本思路是,把二维的图像先灰度化,
    转化为一通道的图像,之后再把它首尾相接转化为一个列向量,假设图像大小是20*20的,那么这个向量就是400维
    ,理论上讲组织成一个向量,就可以应用任何机器学习算法了,但是维度太高算法复杂度也会随之升高,所以需要
    使用PCA算法降维,然后使用简单排序或者KNN都可以。
    
    PCA降维:将一组N维向量降到K维,PCA通过寻找K个单位正交基,使得原始数据变换到这组基后各个字段两两间协方差
    为0,而字段的方差尽可能大
    http://blog.codinglabs.org/articles/pca-tutorial.html
    '''
    import numpy as np
    import cv2
    import os
    from sklearn import neighbors
    
    def load_images(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)
            if os.path.isdir(subjectPath):                
                #每一个文件夹下存放着一个人的照片    
                names.append(subDirname)
                for fileName in os.listdir(subjectPath):
                    imgPath = os.path.join(subjectPath,fileName)
                    img = cv2.imread(imgPath,cv2.IMREAD_GRAYSCALE)
                    images.append(img)
                    labels.append(label)
                label += 1
        images = np.asarray(images)
        labels = np.asarray(labels)
        return images,labels,names
    
    
    class EigenFace(object):
        def __init__(self,dimNum=150,n_neighbors=3,dsize=(100,100)):
            '''
            构造函数:初始化参数
            
            params:
                dimNum:PCA降维后的维度k
                n_neighbors:knn的参数n_neighbors
                dsize:对输入图像进行预处理,指定图像预处理时缩放的尺寸
            '''
            self.__dimNum = dimNum
            self.__dsize = dsize
            self.__mean = 0.0
            self.__knn = neighbors.KNeighborsClassifier(n_neighbors)
    
                    
        def __pca(self,X):
            '''
            使用PCA对数据进行降维
            
            params:
                X:源数据,形状为[m,n]  m为样本数,n为样本的维数
            return:
                降维后的训练集数据[m,k] 和变换矩阵P = [k,n]
            '''
            #[n,m]
            X = X.T
            #均值化矩阵 [n,]
            mean = np.reshape(np.mean(X,axis=1),(-1,1))
            self.__mean = mean
            #去均值  [n,m] - [n,1]
            diff = X - mean              
            '''
            求协方差矩阵 
            这里不去直接去求np.dot(diff,diff.T)的的特征向量和特征值,而是通过求np.dot(diff.T,diff)的特征向量和特征值变换得到
            主要是因为np.dot(diff,diff.T)为[n,n]
            np.dot(diff.T,diff)为[m,m]
            特征数远大于样本数,所以直接对[n,n]矩阵求特征值比较慢
            '''
            cov = np.dot(diff.T,diff)/diff.shape[1]              
            '''
            计算[m,m]的协方差矩阵的特征值[m,]和特征向量[m,m]  
            '''
            eigVals,eigVects = np.linalg.eig(cov)            
            #通过左乘diff得到[n,n]矩阵的特征向量[n,m]
            eigVects = np.dot(diff,eigVects)
            print('特征向量维度:',eigVects.shape)          
            #对特征值进行排序 返回排序后的索引顺序,从小到大排序
            eigValIndex = np.argsort(eigVals)
            #从大到小排序
            eigValIndex = eigValIndex[::-1]
            #取出指定个数的前k大的特征值
            eigValIndex = eigValIndex[:self.__dimNum]      
            #归一化特征向量
            eigVects = eigVects/np.linalg.norm(eigVects,axis=0)        
            #变换矩阵[k,n]
            transMat = (eigVects.T)[eigValIndex,:]        
            #计算经过变换矩阵变换后的新数据  [k,n]x[n,m] = [k,m] 
            lowMat = np.dot(transMat,diff)
            #[m,k]
            lowMat = lowMat.T
            print('降维后的矩阵lowMat维度为:',lowMat.shape)   
            return lowMat,transMat
        
           
        def __prepare(self,images):
            '''
            对图片进行预处理,统一尺寸,直方图均衡化(防止曝光不均衡)
            
            params:
                images:训练集数据,要求为灰度图片  [m,height,width]  m为样本数,height为高,width为宽
            return:
                处理之后的数据 [m,n]  n = dsize[0]x dsize[1] 即特征数
            '''
            new_images = []
            for image in images:
                #缩放
                re_img = cv2.resize(image,self.__dsize)        
                #直方图均衡化
                hist_img = cv2.equalizeHist(re_img)
                #转换成一行数据
                hist_img = np.reshape(hist_img,-1)
                new_images.append(hist_img)
            new_images = np.asarray(new_images)
            return new_images
        
        
        def fit(self,X_train,Y_train):        
            '''
            训练,这里使用KNN算法
            
            params:
                X_train:训练集数据,要求为灰度图片  [m,height,width]  m为样本数,height为高,width为宽        
                Y_train:训练集标签 [m,]         
            '''       
            #对图片数据进行预处理 [M,N]
            X_train = self.__prepare(X_train)
            #对图片数据进行降维处理    X_train_pca:[m,k]  __transMat:[n,k]
            X_train_pca,self.__transMat = self.__pca(X_train)
            #开始训练
            self.__knn.fit(X_train_pca,Y_train)
          
        
        
        def predict(self,X_test):
            '''
            开始预测
            
            params:
                X_test:测试图片,要求为灰度图片 [m,hight,width]  
                
            return:
                Y_pred:[m,1] 返回预测的标签
            '''
            if len(X_test.shape) == 2:
                X_test = np.expand_dims(X_test,axis=0)        
            #对数据进行预处理 [m,n]
            X_test = self.__prepare(X_test)
            #计算经过变换矩阵变换后的新数据  [m,k]
            X_test_pca = np.dot(self.__transMat,X_test.T-self.__mean)
            X_test_pca = X_test_pca.T
            Y_pred = self.__knn.predict(X_test_pca)
            return Y_pred
        
        
    if __name__=='__main__': 
        face = EigenFace(100)
        
        #准备训练集数据
        X_train,Y_train,names = load_images('./face')
        face.fit(X_train,Y_train)
    
        #创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器.
        face_cascade = cv2.CascadeClassifier('./haarcascades/haarcascade_frontalface_default.xml')
        
        #打开摄像头    
        camera = cv2.VideoCapture(0)
        cv2.namedWindow('Dynamic')
        
        print('开始预测')
        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]
                    Y_pred = face.predict(roi_gray)
                    name = names[Y_pred[0]]     
                    print('Label:%s'%(name))
                    cv2.putText(frame,name,(x,y-20),cv2.FONT_HERSHEY_SIMPLEX,1,255,2)
    
                cv2.imshow('Dynamic',frame)            
                #如果按下q键则退出
                if cv2.waitKey(100) & 0xff == ord('q') :
                    break
        camera.release()
        cv2.destroyAllWindows()

    我们在介绍原理的时候,训练集矩阵$S$,每一列都对应一个样本,然而在代码实现的时候,我们传入的训练集是每一行对应一个样本,所以在__pca()函数中对输入数据做了一个转置,同理在输入数据降维之后输出时我们也做了一个转置,使得输出的矩阵每一行对应一个样本。

    参考文献

    [1]Python计算特征值与特征向量案例

    [2]人脸识别经典算法实现(一)——特征脸法

    [3]机器学习: 特征脸算法 EigenFaces

    [4]PCA的数学原理

  • 相关阅读:
    [WPF系列] window自定义
    [WPF系列]-Prism+EF
    C#基础-事件 继承类无法直接引发基类的事件
    [WPF系列] 高级 调试
    [WPF系列]-DynamicResource与StaticResource的区别
    [WPF系列]-DataBinding 绑定计算表达式
    [WPF系列]- Style
    [WPF系列]-基础 TextBlock
    [WPF系列]-ListBox
    [WPF系列]-DataBinding 枚举类型数据源
  • 原文地址:https://www.cnblogs.com/zyly/p/9498857.html
Copyright © 2011-2022 走看看