顔認識経典アルゴリズム実現(二)——Fisher線形判別分析


第2種の顔認識の経典アルゴリズムはFsiherアルゴリズムで、線形判別分析とも呼ばれ、私が最初にこのアルゴリズムが周志華先生の「機械学習」の中で見たが、顔認識にも応用されているとは思わなかった.
このアルゴリズムの構想とPCAの差はあまり多くなく,画像のグローバルな考慮に着目し,PCAは直交基のセットがデータを次元ダウンさせることができることをどのように決定するかを考慮し,線形判別解析は投影ベクトルのセットが投影時計でできるだけ大きく相互に区別できるようにする方法を考慮した.直感的に見ると、非是クラスとクラスの違いはもっと大きく、クラス内のデータはもっと集約されるべきだ.この2つの指標は,数学的に一定の指標を定義して測定し,最適な投影ベクトルを解く必要がある.
運搬工を続けます...
http://blog.csdn.net/smartempire/article/details/23377385ああ、このブログLDAの理論と実現はとても透徹していて、1編で十分です!このブログを見てみると、LDAの理論的な導出は確かに複雑で、数学の知識も多いが、それは難しくない.中間の導出過程を見ずに、彼の最後の公式の符号化を直接つかむことができ、これはあなたの最後の結果に影響を与えないからだ.
プログラムではクラス内の平均ベクトルの計算に関わるため,データを整理する際にPCAと異なる.
コードは次のとおりです.
#encoding=utf-8
import numpy as np
import cv2
import os

class FisherFace(object):
    def __init__(self,threshold,k,dsize):
        self.threshold = threshold #   ,    
        self.k = k         #     w   
        self.dsize = dsize #       

    def loadImg(self,fileName,dsize):
        '''
            ,     ,    ,      
        :param fileName:      
        :param dsize:       。    
        :return:     
        '''
        img = cv2.imread(fileName)
        retImg = cv2.resize(img,dsize)
        retImg = cv2.cvtColor(retImg,cv2.COLOR_RGB2GRAY)
        retImg = cv2.equalizeHist(retImg)
        # cv2.imshow('img',retImg)
        # cv2.waitKey()
        return retImg

    def createImgMat(self,dirName):
        '''
                ,         ,    
        :param dirName:                
        :return:          ,    
        '''
        dataMat = np.zeros((10,1))
        label = []
        dataList = []
        for parent,dirnames,filenames in os.walk(dirName):
            # print parent
            # print dirnames
            # print filenames
            #index = 0
            for dirname in dirnames:
                for subParent,subDirName,subFilenames in os.walk(parent+'/'+dirname):
                    for index,filename in enumerate(subFilenames):
                        img = self.loadImg(subParent+'/'+filename,self.dsize)
                        tempImg = np.reshape(img,(-1,1))
                        if index == 0 :
                            dataMat = tempImg
                        else:
                            dataMat = np.column_stack((dataMat,tempImg))
                dataList.append(dataMat)
                label.append(subParent)
        return dataList,label

    def LDA(self,dataList,k):
        '''
                      
        :param dataList:       
        :param k:     k   
        :return:              
        '''
        n = dataList[0].shape[0]
        W = np.zeros((n,self.k))
        Sw = np.zeros((n,n))
        Sb = np.zeros((n,n))
        u = np.zeros((n,1))
        N = 0
        meanList = []
        sampleNum = []

        for dataMat in dataList:
            meanMat = np.mat(np.mean(dataMat,1)).T
            meanList.append(meanMat)
            sampleNum.append(dataMat.shape[1])

            dataMat = dataMat-meanMat
            sw = dataMat*dataMat.T
            Sw += sw
        print 'Sw   ',Sw.shape

        for index,meanMat in enumerate(meanList):
            m = sampleNum[index]
            u += m*meanMat
            N += m
        u = u/N
        print 'u   ',u.shape

        for index,meanMat in enumerate(meanList):
            m = sampleNum[index]
            sb = m*(meanMat-u)*(meanMat-u).T
            Sb += sb
        print 'Sb   ',Sb.shape

        eigVals, eigVects = np.linalg.eig(np.mat(np.linalg.inv(Sw)*Sb))
        eigValInd = np.argsort(eigVals)
        eigValInd = eigValInd[::-1]
        eigValInd = eigValInd[:k] #         k     
        print '      ',eigValInd.shape
        eigVects = eigVects/np.linalg.norm(eigVects,axis=0) #       
        redEigVects = eigVects[:,eigValInd]
        print '      ',redEigVects.shape

        transMatList = []
        for dataMat in dataList:
            transMatList.append(redEigVects.T*dataMat)
        return transMatList,redEigVects

    def compare(self,dataList,testImg,label):
        '''
            ,                ,     KNN   ,          
        :param dataList:       
        :param testImg:       ,     
        :param label:     
        :return:               ,     
        '''
        testImg = cv2.resize(testImg,self.dsize)
        testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)
        testImg = np.reshape(testImg,(-1,1))
        transMatList,redVects = fisherface.LDA(dataList,self.k)
        testImg = redVects.T*testImg
        print '          ',testImg.shape
        disList = []
        testVec = np.reshape(testImg,(1,-1))
        sumVec = np.mat(np.zeros((self.dsize[0]*self.dsize[1],1)))
        for transMat in transMatList:
            for sample in transMat.T:
                disList.append( np.linalg.norm(testVec-sample))
        print disList
        sortIndex = np.argsort(disList)
        return label[sortIndex[0]/9]

    def predict(self,dirName,testFileName):
        '''
            
        :param dirName:              
        :param testFileName:        
        :return:     
        '''
        testImg = cv2.imread(testFileName)
        dataMat,label = self.createImgMat(dirName)
        print '      ',label
        ans = self.compare(dataMat,testImg,label)
        return ans

if __name__=="__main__":
   
    fisherface = FisherFace(10,20,(20,20))
    ans = fisherface.predict('d:/face','d:/face_test/8.bmp')
    print ans