人脸识别经典算法实现(二)——Fisher线性判别分析

本文介绍了一种基于FisherFace的人脸识别方法,该方法利用线性判别分析(LDA)进行特征提取,并通过计算图像样本间的距离来进行分类。文中详细展示了FisherFace算法的具体实现流程,包括图像预处理、样本矩阵生成、LDA计算及分类比较。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:https://blog.youkuaiyun.com/freedom098/article/details/52088135

第二种人脸识别的经典算法是Fsiher算法,也称之为线性判别分析,我最先看到这个算法是在周志华老师的《机器学习》中,没想到在人脸识别上也有应用。

这个算法的思路和PCA差不太多,都是着眼于图像全局考虑,PCA考虑的是如何确定一组正交基可以使数据降维,线性判别分析则是考虑如何确定一组投影向量可以让数据集在投影钟尽可能大的相互区分。直观上看,区分为非就是类与类之间的差别应该更大,而类内的数据应该更加聚合。这两个指标需要在数学上定义一定的指标来衡量,从而求解出最好的投影向量。

继续做搬运工。。。。

http://blog.youkuaiyun.com/smartempire/article/details/23377385,这篇博客LDA的理论和实现讲得非常透彻了,一篇就够了!看完这篇博客你就会发现LDA的理论推导确实有些复杂,涉及的数学知识也比较多,但是它落地不难,因为你可以不看中间的推导过程,直接抓住他最后的公式编码,这不影响你做出最后结果。

程序中因为涉及到了类内的均值向量的计算,因此在组织数据的时候与PCA有不同。

代码如下:

 

 
  1. #encoding=utf-8

  2. import numpy as np

  3. import cv2

  4. import os

  5.  
  6. class FisherFace(object):

  7. def __init__(self,threshold,k,dsize):

  8. self.threshold = threshold # 阈值,暂未使用

  9. self.k = k # 指定投影w的个数

  10. self.dsize = dsize # 统一尺寸大小

  11.  
  12. def loadImg(self,fileName,dsize):

  13. '''

  14. 载入图像,灰度化处理,统一尺寸,直方图均衡化

  15. :param fileName: 图像文件名

  16. :param dsize: 统一尺寸大小。元组形式

  17. :return: 图像矩阵

  18. '''

  19. img = cv2.imread(fileName)

  20. retImg = cv2.resize(img,dsize)

  21. retImg = cv2.cvtColor(retImg,cv2.COLOR_RGB2GRAY)

  22. retImg = cv2.equalizeHist(retImg)

  23. # cv2.imshow('img',retImg)

  24. # cv2.waitKey()

  25. return retImg

  26.  
  27. def createImgMat(self,dirName):

  28. '''

  29. 生成图像样本矩阵,组织形式为行为属性,列为样本

  30. :param dirName: 包含训练数据集的图像文件夹路径

  31. :return: 包含样本矩阵的列表,标签列表

  32. '''

  33. dataMat = np.zeros((10,1))

  34. label = []

  35. dataList = []

  36. for parent,dirnames,filenames in os.walk(dirName):

  37. # print parent

  38. # print dirnames

  39. # print filenames

  40. #index = 0

  41. for dirname in dirnames:

  42. for subParent,subDirName,subFilenames in os.walk(parent+'/'+dirname):

  43. for index,filename in enumerate(subFilenames):

  44. img = self.loadImg(subParent+'/'+filename,self.dsize)

  45. tempImg = np.reshape(img,(-1,1))

  46. if index == 0 :

  47. dataMat = tempImg

  48. else:

  49. dataMat = np.column_stack((dataMat,tempImg))

  50. dataList.append(dataMat)

  51. label.append(subParent)

  52. return dataList,label

  53.  
  54. def LDA(self,dataList,k):

  55. '''

  56. 多分类问题的线性判别分析算法

  57. :param dataList: 样本矩阵列表

  58. :param k: 投影向量k的个数

  59. :return: 变换后的矩阵列表和变换矩阵

  60. '''

  61. n = dataList[0].shape[0]

  62. W = np.zeros((n,self.k))

  63. Sw = np.zeros((n,n))

  64. Sb = np.zeros((n,n))

  65. u = np.zeros((n,1))

  66. N = 0

  67. meanList = []

  68. sampleNum = []

  69.  
  70. for dataMat in dataList:

  71. meanMat = np.mat(np.mean(dataMat,1)).T

  72. meanList.append(meanMat)

  73. sampleNum.append(dataMat.shape[1])

  74.  
  75. dataMat = dataMat-meanMat

  76. sw = dataMat*dataMat.T

  77. Sw += sw

  78. print 'Sw的维度',Sw.shape

  79.  
  80. for index,meanMat in enumerate(meanList):

  81. m = sampleNum[index]

  82. u += m*meanMat

  83. N += m

  84. u = u/N

  85. print 'u的维度',u.shape

  86.  
  87. for index,meanMat in enumerate(meanList):

  88. m = sampleNum[index]

  89. sb = m*(meanMat-u)*(meanMat-u).T

  90. Sb += sb

  91. print 'Sb的维度',Sb.shape

  92.  
  93. eigVals, eigVects = np.linalg.eig(np.mat(np.linalg.inv(Sw)*Sb))

  94. eigValInd = np.argsort(eigVals)

  95. eigValInd = eigValInd[::-1]

  96. eigValInd = eigValInd[:k] # 取出指定个数的前k大的特征值

  97. print '选取的特征值',eigValInd.shape

  98. eigVects = eigVects/np.linalg.norm(eigVects,axis=0) #归一化特征向量

  99. redEigVects = eigVects[:,eigValInd]

  100. print '变换矩阵维度',redEigVects.shape

  101.  
  102. transMatList = []

  103. for dataMat in dataList:

  104. transMatList.append(redEigVects.T*dataMat)

  105. return transMatList,redEigVects

  106.  
  107. def compare(self,dataList,testImg,label):

  108. '''

  109. 比较函数,这里只是用了最简单的欧氏距离比较,还可以使用KNN等方法,如需修改修改此处即可

  110. :param dataList: 样本矩阵列表

  111. :param testImg: 测试图像矩阵,最原始形式

  112. :param label: 标签矩阵

  113. :return: 与测试图片最相近的图像文件夹,也就是类别

  114. '''

  115. testImg = cv2.resize(testImg,self.dsize)

  116. testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)

  117. testImg = np.reshape(testImg,(-1,1))

  118. transMatList,redVects = fisherface.LDA(dataList,self.k)

  119. testImg = redVects.T*testImg

  120. print '检测样本变换后的维度',testImg.shape

  121. disList = []

  122. testVec = np.reshape(testImg,(1,-1))

  123. sumVec = np.mat(np.zeros((self.dsize[0]*self.dsize[1],1)))

  124. for transMat in transMatList:

  125. for sample in transMat.T:

  126. disList.append( np.linalg.norm(testVec-sample))

  127. print disList

  128. sortIndex = np.argsort(disList)

  129. return label[sortIndex[0]/9]

  130.  
  131. def predict(self,dirName,testFileName):

  132. '''

  133. 预测函数

  134. :param dirName: 包含训练数据集的文件夹路径

  135. :param testFileName: 测试图像文件名

  136. :return: 预测结果

  137. '''

  138. testImg = cv2.imread(testFileName)

  139. dataMat,label = self.createImgMat(dirName)

  140. print '加载图片标签',label

  141. ans = self.compare(dataMat,testImg,label)

  142. return ans

  143.  
  144. if __name__=="__main__":

  145.  
  146. fisherface = FisherFace(10,20,(20,20))

  147. ans = fisherface.predict('d:/face','d:/face_test/8.bmp')

  148. print ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值