第十節、人臉識別之特征臉算法


人臉檢測是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$的均值向量$\bar{x}=\frac{1}{m}\sum\limits_{i=1}^{m}x_i$;

2、向量取均值$Φ_i=x_i-\bar{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-\bar{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的數學原理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM