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的数学原理

  • 相关阅读:
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 455 分发饼干
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    Java实现 LeetCode 454 四数相加 II
    FFmpeg解码H264及swscale缩放详解
    linux中cat more less head tail 命令区别
    C语言字符串操作总结大全(超详细)
    如何使用eclipse进行嵌入式Linux的开发
  • 原文地址:https://www.cnblogs.com/zyly/p/9498857.html
Copyright © 2011-2022 走看看