1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 人脸识别系列算法原理

人脸识别系列算法原理

时间:2021-07-19 04:36:38

相关推荐

人脸识别系列算法原理

目录

1、Eigenfaces(特征脸)算法

基本思想

Eigenfaces算法过程

2、FisherFace算法

基本思想

Fisherface算法流程

3、LBPH(Local Binary Patter Histogram)算法

基本思想

LBPH 算法流程

4、算法的复现代码

1、EigenFaces算法

2、FisherFaces算法

3、LBPH算法

1、Eigenfaces(特征脸)算法

Eigenfaces是在人脸识别的计算机视觉问题中使用的一组特征向量的名称,Eigenfaces是基于PCA(主成分分析)的,所以学习Eigenfaces需要我们了解PCA的原理。

基本思想

主成分分析(PCA)是一种矩阵的压缩算法,在减少矩阵维数的同时尽可能的保留原矩阵的信息,简单来说就是将 n×m的矩阵转换成n×k的矩阵,仅保留矩阵中所存在的主要特性,从而可以大大节省空间和数据量。PCA的实现需要进行降维,也就是将矩阵进行变换,从更高的维度降到低的维度,然而PCA的降维离不开协方差矩阵。方差是描述一维数据样本本身相对于均值的偏离程度,是一种用来度量两个随机变量关系的统计量,从角度来说,其夹角越小,值越大,方向越相近,也就是越正相关。协方差矩阵度量除了是两个随机变量的关系外,还是维度与维度之间的关系,而非样本与样本之间的关系。

学习一种新的东西,尤其是知识,我们需要了解知识中的思想。我在了解和学习Eigenface算法时它的思想是图像识别首先要选择一个合适的子空间,将所有的图像集中到这个子空间中,然后在这个子空间中衡量相似性或者进行分类学习,再讲子空间变换到另一个空间中,这样的作用一是同一个类别的图像离得更近,二是不同的类别的图像会离得比较远;这样经过线性分类分开的图像在新空间就能容易分开。同时特征脸技术会寻找人脸图像分布的基本元素,即人脸图像样本集协方差矩阵的特征向量,以此来表征人脸图像。人脸图像的基本元素有很多,比如眼、面颊、唇等基本元素,这些特征向量在特征脸的图像空间中对应生成的子空间被称为子脸空间

生成了子空间之后就要进行空间构造,那么如何进行空间构造呢?首先要寻找人脸的共性,其次是要寻找个体与共性的差异,还有就是要明白共性其实是空间,个体就是向量。利用协方差矩阵把目标集中所有人脸图像的特征值进行分解,得到对应的特征向量,这些特征向量就是“特征脸”。寻找特征向量的特性,将其进行线性组合。在以每一个特征子脸为基的空间,每个人脸就是一个点,这个点的坐标就是每一个人脸在每个特征基下的的投影坐标。

Eigenfaces算法过程

获得人脸图像数据,将每一个人脸图像矩阵按行串成一维,每个人脸就是一个向量;将M个人脸在对应维度上加起来,然后求平均得到“平均脸”;将每个图像都减去平均脸向量;计算协方差矩阵;运用Eigenfaces记性人脸识别;

算法实践过程;

训练图像求出平均脸获得特征子脸进行图像重构寻找相似度高的人脸图像。

2、FisherFace算法

FisherFace是Fisher线性判别在人脸识别的应用。线性判别分析(LDA)算法思想最早由英国统计与遗传学家,现代统计科学的奠基人之一罗纳德*费舍尔(Ronald)提出。LDA算法使用统计学方法,尝试找到物体间特征的一个线性组合,在降维的同时考虑类别信息。通过该算法得到的线性组合可以用来作为一个线性分类器或者实现降维。

基本思想

线性判别分析基本思想是:将高维的模式样本投影到低维最佳矢量空间,以达到抽取重要分类信息和压缩特征空间维度的效果,投影后保证模式样本在新的子空间有最大的类间距离、最小的类内距离,即模式在该空间中有最佳的可分离性。理论和特征脸里用到的Eigenfaces有相似之处,都是对原有数据进行整体降维映射到低维空间的方法,fisherfaces和Eigenfaces都是从数据整体入手而不同于LBP提取局部纹理特征。

对降维后的样本使用Fisher线性判别方法,确定一个最优的投影方向,构造一个一维的体征空间,将多维的人脸图像投影到 fisherfaces特征空间,利用类内样本数据形成一组特征向量,这组特征向量就代表了人脸的特征。

我们知道,该算法是在样本数据映射到另外一个特征空间后,将类内距离最小化,类间距离最大化。LDA算法可以用作降维,该算法的原理和PCA算法很相似,因此LDA算法也同样可以用在人脸识别领域。通过使用PCA算法来进行人脸识别的算法称为特征脸法,而使用LDA算法进行人脸识别的算法称为费舍尔脸法。

LDAPCA相比:

相同:1、在降维的时候,两者都使用了矩阵的特征分解思想;2、两者都假设数据符合高斯分布。不同:1、LDA是有监督的降维方法,而PCA是无监督的。2、如果说数据是k维的,那么LDA只能降到(k-1)维度,而PCA不受此限制。3、从数学角度来看,LDA选择分类性能最好的投影方向,而PCA选择样本投影点具有最大方差的方向。

Fisherfaces算法Eigenfaces算法相比:

相同:两者均可以对数据进行降维;两者在降维时均使用了矩阵特征分解的思想。不同:Fisherfaces是有监督的降维方法,而是Eigenfaces无监督的降维方法;Fisherfaces除了可以用于降维,还可以用于分类。

值得一提的是,FisherFace算法识别的错误率低于哈佛和耶鲁人脸数据库测试的Eigenfaces识别结果。

Fisherface算法流程

获得人脸图像数据,然后求出人脸的均值。观察各个人脸的特征值。进行人脸鉴定,观察人脸特征,判断是否是个人。最后进行人脸识别。

3、LBPH(Local Binary Patter Histogram)算法

Local Binary Patterns Histograms即LBP特征的统计直方图,LBPHLBP(局部二值编码)特征与图像的空间信息结合在一起。如果直接使用LBP编码图像用于人脸识别。其实和不提取LBP特征区别不大,因此在实际的LBP应用中,一般采用LBP编码图像的统计直方图作为特征向量进行分类识别。

原始的LBP算子定义为在33的窗口内,以窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于或等于中心像素值,则该像素点的位置被标记为1,否则为0。这样,33邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心像素点的LBP值,并用这个值来反映该区域的纹理特征。

LBPH的维度: 采样点为8个,如果用的是原始的LBP或Extended LBP特征,其LBP特征值的模式为256种,则一幅图像的LBP特征向量维度为:64256=16384维,而如果使用的UniformPatternLBP特征,其LBP值的模式为59种,其特征向量维度为:6459=3776维,可以看出,使用等价模式特征,其特征向量的维度大大减少,这意味着使用机器学习方法进行学习的时间将大大减少,而性能上没有受到很大影响。

基本思想

建立在LBPH基础上的人脸识别法基本思想如下:首先以每个像素为中心,判断与周围像素灰度值大小关系,对其进行二进制编码,从而获得整幅图像的LBP编码图像;再将LBP图像分为个区域,获取每个区域的LBP编码直方图,继而得到整幅图像的LBP编码直方图,通过比较不同人脸图像LBP编码直方图达到人脸识别的目的,其优点是不会受到光照、缩放、旋转和平移的影响。

LBPH算法“人”如其名,采用的识别方法是局部特征提取的方法,这是与前两种方法的最大区别。

LBPH 算法流程

LBP特征提取:根据上述的均匀LBP算子处理原始图像;LBP特征匹配(计算直方图):将图像分为若干个的子区域,并在子区域内根据LBP值统计其直方图,以直方图作为其判别特征。

4、算法的复现代码

1、EigenFaces算法

(转自人脸识别经典算法实现(一)——特征脸法_恒河沙无数-CSDN博客)

#encoding=utf-8import numpy as npimport cv2import osclass EigenFace(object):def __init__(self,threshold,dimNum,dsize):self.threshold = threshold # 阈值暂未使用self.dimNum = dimNumself.dsize = dsizedef 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 retImgdef createImgMat(self,dirName):'''生成图像样本矩阵,组织形式为行为属性,列为样本:param dirName: 包含训练数据集的图像文件夹路径:return: 样本矩阵,标签矩阵'''dataMat = np.zeros((10,1))label = []for parent,dirnames,filenames in os.walk(dirName):# print parent# print dirnames# print filenamesindex = 0for dirname in dirnames:for subParent,subDirName,subFilenames in os.walk(parent+'/'+dirname):for filename in subFilenames:img = self.loadImg(subParent+'/'+filename,self.dsize)tempImg = np.reshape(img,(-1,1))if index == 0 :dataMat = tempImgelse:dataMat = np.column_stack((dataMat,tempImg))label.append(subParent+'/'+filename)index += 1return dataMat,labeldef PCA(self,dataMat,dimNum):'''PCA函数,用于数据降维:param dataMat: 样本矩阵:param dimNum: 降维后的目标维度:return: 降维后的样本矩阵和变换矩阵'''# 均值化矩阵meanMat = np.mat(np.mean(dataMat,1)).Tprint '平均值矩阵维度',meanMat.shapediffMat = dataMat-meanMat# 求协方差矩阵,由于样本维度远远大于样本数目,所以不直接求协方差矩阵,采用下面的方法covMat = (diffMat.T*diffMat)/float(diffMat.shape[1]) # 归一化#covMat2 = np.cov(dataMat,bias=True)#print '基本方法计算协方差矩阵为',covMat2print '协方差矩阵维度',covMat.shapeeigVals, eigVects = np.linalg.eig(np.mat(covMat))print '特征向量维度',eigVects.shapeprint '特征值',eigValseigVects = diffMat*eigVectseigValInd = np.argsort(eigVals)eigValInd = eigValInd[::-1]eigValInd = eigValInd[:dimNum] # 取出指定个数的前n大的特征值print '选取的特征值',eigValIndeigVects = eigVects/np.linalg.norm(eigVects,axis=0) #归一化特征向量redEigVects = eigVects[:,eigValInd]print '选取的特征向量',redEigVects.shapeprint '均值矩阵维度',diffMat.shapelowMat = redEigVects.T*diffMatprint '低维矩阵维度',lowMat.shapereturn lowMat,redEigVectsdef compare(self,dataMat,testImg,label):'''比较函数,这里只是用了最简单的欧氏距离比较,还可以使用KNN等方法,如需修改修改此处即可:param dataMat: 样本矩阵:param testImg: 测试图像矩阵,最原始形式:param label: 标签矩阵:return: 与测试图片最相近的图像文件名'''testImg = cv2.resize(testImg,self.dsize)testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)testImg = np.reshape(testImg,(-1,1))lowMat,redVects = self.PCA(dataMat,self.dimNum)testImg = redVects.T*testImgprint '检测样本变换后的维度',testImg.shapedisList = []testVec = np.reshape(testImg,(1,-1))for sample in lowMat.T:disList.append(np.linalg.norm(testVec-sample))print disListsortIndex = np.argsort(disList)return label[sortIndex[0]]def predict(self,dirName,testFileName):'''预测函数:param dirName: 包含训练数据集的文件夹路径:param testFileName: 测试图像文件名:return: 预测结果'''testImg = cv2.imread(testFileName)dataMat,label = self.createImgMat(dirName)print '加载图片标签',labelans = pare(dataMat,testImg,label)return ansif __name__ == '__main__':eigenface = EigenFace(20,50,(50,50))print eigenface.predict('d:/face','D:/face_test/1.bmp')

2、FisherFaces算法

(转自人脸识别经典算法实现(二)——Fisher线性判别分析_恒河沙无数-CSDN博客)

#encoding=utf-8import numpy as npimport cv2import osclass 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 retImgdef 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 = 0for 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 = tempImgelse:dataMat = np.column_stack((dataMat,tempImg))dataList.append(dataMat)label.append(subParent)return dataList,labeldef 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 = 0meanList = []sampleNum = []for dataMat in dataList:meanMat = np.mat(np.mean(dataMat,1)).TmeanList.append(meanMat)sampleNum.append(dataMat.shape[1])dataMat = dataMat-meanMatsw = dataMat*dataMat.TSw += swprint 'Sw的维度',Sw.shapefor index,meanMat in enumerate(meanList):m = sampleNum[index]u += m*meanMatN += mu = u/Nprint 'u的维度',u.shapefor index,meanMat in enumerate(meanList):m = sampleNum[index]sb = m*(meanMat-u)*(meanMat-u).TSb += sbprint 'Sb的维度',Sb.shapeeigVals, eigVects = np.linalg.eig(np.mat(np.linalg.inv(Sw)*Sb))eigValInd = np.argsort(eigVals)eigValInd = eigValInd[::-1]eigValInd = eigValInd[:k] # 取出指定个数的前k大的特征值print '选取的特征值',eigValInd.shapeeigVects = eigVects/np.linalg.norm(eigVects,axis=0) #归一化特征向量redEigVects = eigVects[:,eigValInd]print '变换矩阵维度',redEigVects.shapetransMatList = []for dataMat in dataList:transMatList.append(redEigVects.T*dataMat)return transMatList,redEigVectsdef 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*testImgprint '检测样本变换后的维度',testImg.shapedisList = []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 disListsortIndex = 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 '加载图片标签',labelans = pare(dataMat,testImg,label)return ansif __name__=="__main__":fisherface = FisherFace(10,20,(20,20))ans = fisherface.predict('d:/face','d:/face_test/8.bmp')print ans

3、LBPH算法

(转自人脸识别经典算法实现(三)——LBP算法_恒河沙无数-CSDN博客_lbp算法)

#encoding=utf-8import numpy as npimport osimport cv2class LBP(object):def __init__(self,threshold,dsize,blockNum):self.dsize = dsize # 统一尺寸大小self.blockNum = blockNum # 分割块数目self.threshold = threshold # 阈值,暂未使用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 retImgdef loadImagesList(self,dirName):'''加载图像矩阵列表:param dirName:文件夹路径:return: 包含最原始的图像矩阵的列表和标签矩阵'''imgList = []label = []for parent,dirnames,filenames in os.walk(dirName):# print parent# print dirnames# print filenamesfor dirname in dirnames:for subParent,subDirName,subFilenames in os.walk(parent+'/'+dirname):for filename in subFilenames:img = self.loadImg(subParent+'/'+filename,self.dsize)imgList.append(img) # 原始图像矩阵不做任何处理,直接加入列表label.append(subParent+'/'+filename)return imgList,labeldef getHopCounter(self,num):'''计算二进制序列是否只变化两次:param num: 数字:return: 01变化次数'''binNum = bin(num)binStr = str(binNum)[2:]n = len(binStr)if n < 8:binStr = "0"*(8-n)+binStrn = len(binStr)counter = 0for i in range(n):if i != n-1:if binStr[i+1] != binStr[i]:counter += 1else:if binStr[0] != binStr[i]:counter += 1return counterdef createTable(self):'''生成均匀对应字典:return: 均匀LBP特征对应字典'''self.table = {}temp = 1print type(temp)for i in range(256):if self.getHopCounter(i) <= 2:self.table[i] = temptemp += 1else:self.table[i] = 0return self.tabledef getLBPfeature(self,img):'''计算LBP特征:param img:图像矩阵:return: LBP特征图'''m = img.shape[0];n = img.shape[1]neighbor = [0]*8featureMap = np.mat(np.zeros((m,n)))for y in xrange(1,m-1):for x in xrange(1,n-1):neighbor[0] = img[y-1,x-1]neighbor[1] = img[y-1,x]neighbor[2] = img[y-1,x+1]neighbor[3] = img[y,x+1]neighbor[4] = img[y+1,x+1]neighbor[5] = img[y+1,x]neighbor[6] = img[y+1,x-1]neighbor[7] = img[y,x-1]center = img[y,x]temp = 0for k in range(8):temp += (neighbor[k] >= center)*(1<<k)featureMap[y,x] = self.table[temp]featureMap = featureMap.astype('uint8') # 数据类型转换为无符号8位型,如不转换则默认为float64位,影响最终效果return featureMapdef calcHist(self,roi):'''计算直方图:param roi:图像区域:return: 直方图矩阵'''hist = cv2.calcHist([roi],[0],None,[59],[0,256]) # 第四个参数是直方图的横坐标数目,经过均匀化降维后这里一共有59种像素return histdef compare(self,sampleImg,testImg):'''比较函数,这里使用的是欧氏距离排序,也可以使用KNN,在此处更改:param sampleImg: 样本图像矩阵:param testImg: 测试图像矩阵:return: k2值'''testImg = cv2.resize(testImg,self.dsize)testImg = cv2.cvtColor(testImg,cv2.COLOR_RGB2GRAY)testFeatureMap = self.getLBPfeature(testImg)sampleFeatureMap = self.getLBPfeature(sampleImg)# 计算步长,分割整个图像为小块ystep = self.dsize[0]/self.blockNumxstep = self.dsize[1]/self.blockNumk2 = 0for y in xrange(0,self.dsize[0],ystep):for x in xrange(0,self.dsize[1],xstep):testroi = testFeatureMap[y:y+ystep,x:x+xstep]sampleroi =sampleFeatureMap[y:y+ystep,x:x+xstep]testHist = self.calcHist(testroi)sampleHist = self.calcHist(sampleroi)k2 += np.sum((sampleHist-testHist)**2)/np.sum((sampleHist+testHist))print 'k2的值为',k2return k2def predict(self,dirName,testImgName):'''预测函数:param dirName:样本图像文件夹路径:param testImgName: 测试图像文件名:return: 最相近图像名称'''table = self.createTable()testImg = cv2.imread(testImgName)imgList,label = self.loadImagesList(dirName)k2List = []for img in imgList:k2 = pare(img,testImg)k2List.append(k2)order = np.argsort(k2List)return label[order[0]]if __name__ == "__main__":lbp = LBP(20,(50,50),5)ans = lbp.predict('d:/face','d:/face_test/9.bmp')print ans

版权声明:

本文文字部分节选自:

基于OpenCV人脸识别Eigenfaces(特征脸)算法、Fisherfaces算法、Local Binary, Patter Histogram(LBPH)算法认识_水桶冰箱的博客-CSDN博客

人脸识别系列二 | FisherFace,LBPH算法及Dlib人脸检测_I good vegetable a!-CSDN博客

代码部分转自:

人脸识别经典算法实现(一)——特征脸法_恒河沙无数-CSDN博客

人脸识别经典算法实现(二)——Fisher线性判别分析_恒河沙无数-CSDN博客

人脸识别经典算法实现(三)——LBP算法_恒河沙无数-CSDN博客_lbp算法

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。