人脸识别算法是什么意思?

本教程的操作环境:windows7系统和Dell G3电脑。

人脸识别是通过视频采集设备获取用户的面部图像,然后利用核心算法对人脸的面部位置、脸型、角度进行计算分析,再与自身数据库中已有的模板进行比对,进而判断用户的真实身份。

人脸识别算法是指在检测到人脸,定位到人脸的关键特征点后,经过预处理,可以切出主要的人脸区域,送入后端的识别算法。识别算法要完成人脸特征的提取,并与库存中的已知人脸进行比较,完成最终的分类。

人脸识别算法有四种:基于人脸特征点的识别算法、基于整张人脸图像的识别算法、基于模板的识别算法和基于神经网络的识别算法。

人脸识别算法原理;

系统的输入一般是一幅或一系列身份未定的人脸图像,以及人脸数据库中若干幅身份已知或对应编码的人脸图像,而输出则是一系列相似度得分,表示待识别人脸的身份。

人脸识别的三种经典算法

1,特征脸(Eigenfaces)算法

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

基本思想

主成分分析(PCA)是一种矩阵压缩算法,可以降低矩阵的维数,尽可能保留原矩阵的信息。简单来说,就是把n×m的矩阵转换成n×k的矩阵,只保留矩阵的主要特征,从而大大节省空间和数据。PCA的实现需要降维,即将矩阵从高维转换到低维。然而,PCA的降维离不开协方差矩阵。方差描述的是一维数据样本与均值的偏差,是一种用来衡量两个随机变量之间关系的统计量。从角度上看,角度越小,数值越大,方向越近,即正相关越多。协方差矩阵度量的不仅仅是两个随机变量之间的关系,更是维度之间的关系,而不是样本之间的关系。

学习一个新事物,尤其是知识,需要了解知识中的思想。我在理解和学习特征脸算法的时候,它的思想是图像识别首先要选择一个合适的子空间,把所有的图像集中在这个子空间里,然后在这个子空间里进行相似度的度量或者进行分类学习,然后再谈子空间到另一个空间的变换。这有以下作用:一是同类的图像更近,二是不同类的图像更远;这样,通过线性分类分离的图像可以很容易地在新的空间中分离。同时,特征人脸技术会找到人脸图像分布的基本元素,即人脸图像样本集的协方差矩阵的特征向量,以此来表征人脸图像。人脸图像的基本元素有很多,比如眼睛、脸颊、嘴唇等基本元素。这些特征向量在特征脸的图像空间中生成的子空间称为子脸空间。

子空间生成后,就要构造空间,那么如何构造空间呢?首先要寻找人脸的* * *其次要寻找个体和* * *的区别最后要明白* * *其实是一个空间,个体是一个矢量。利用协方差矩阵对目标集中所有人脸图像的特征值进行分解,得到相应的特征向量。这些特征向量就是“特征面”。求特征向量的特征,线性组合。在基于每个特征子面的空间中,每个面都是一个点,这个点的坐标就是每个面在每个特征基下的投影坐标。

特征脸算法过程

获取人脸图像数据,将每个人脸图像矩阵按行串成一维,每个人脸为一个向量;

把对应维度的M张脸加起来,然后平均,得到“平均脸”;

从每个图像中减去平均人脸向量;

计算协方差矩阵;

基于特征脸记忆的人脸识别:

算法练习流程;

训练图像

找到平均脸

获取特征子面

执行图像重建。

寻找相似度高的人脸图像。

2.FisherFace算法

FisherFace是Fisher线性判别式在人脸识别中的应用。线性判别分析(LDA)算法的思想最早是由英国统计学家和遗传学家、现代统计科学的奠基人之一罗纳德提出的。LDA算法利用统计方法,试图找到对象之间特征的线性组合,在降维的同时考虑类别信息。该算法得到的线性组合可以用作线性分类器或降维。

基本思想

线性判别分析的基本思想是将高维模式样本投影到低维最优向量空间,从而提取重要的分类信息,压缩特征空间的维数。投影后的模式样本保证在新的子空间中具有最大的类间距离和最小的类内距离,即模式在这个空间中具有最好的可分性。特征脸中使用的理论和特征脸有相似之处,都是将原始数据的全维降低到低维空间的方法。在从整个数据中提取局部纹理特征方面,fisherfaces和Eigenfaces不同于LBP。

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

我们知道,该算法在样本数据映射到另一个特征空间后,最小化类内距离,最大化类间距离。LDA算法可以用于降维,其原理与PCA算法非常相似,因此LDA算法也可以用于人脸识别领域。使用PCA算法进行人脸识别的算法称为特征脸方法,而使用LDA算法进行人脸识别的算法称为Fisher人脸方法。

与PCA相比,LDA:

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

相同:两者都可以降低数据的维度;两者都在降维中使用了矩阵特征分解的思想。

不同:Fisherfaces是有监督的降维方法,而Eigenfaces是无监督的降维方法;Fisherfaces不仅可以用于降维,还可以用于分类。

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

Fisherface算法流程

获取人脸图像数据,然后计算人脸的平均值。

观察每张脸的特征值。

进行人脸识别,观察面部特征,判断是否为个人。

最后进行人脸识别。

3.LBPH(局部二元模式直方图)算法

局部二值模式直方图是LBP特征的统计直方图,LBPH结合了LBP特征和图像的空间信息。如果LBP编码图像直接用于人脸识别。其实提取LBP特征和不提取LBP特征差别不大。因此,在实际的LBP应用中,一般采用LBP编码图像的统计直方图作为分类识别的特征向量。

最初的LBP算子被定义为将33°窗口内的八个相邻像素的灰度值与作为阈值的窗口的中心像素进行比较。如果外围像素值大于等于中心像素值,则像素点的位置标记为1,否则为0。这样就可以比较33邻域内的8个点,生成8位二进制数(通常转换成十进制数,即LBP码,***256种),即可以得到窗口中心像素点的LBP值,这个值可以用来反映这个区域的纹理特征。

LBPH的尺寸:有8个采样点。如果使用原始LBP或扩展LBP特征,则一幅图像的LBP特征向量维数为:64256=16384维,而如果使用UniformPatternLBP特征,则LBP值有59个模式。其特征向量的维数为:6459=3776。可以看出,使用等价模式特征大大降低了其特征向量的维数,这意味着使用机器学习方法的学习时间会大大减少,但性能不会受到太大影响。

基本思想

基于LBPH的人脸识别方法的基本思想是:首先以每个像素为中心,判断与周围像素灰度值的关系,并进行二进制编码,从而得到整幅图像的LBP编码图像;然后将LBP图像划分为四个区域,得到每个区域的LBP编码直方图,进而得到整幅图像的LBP编码直方图。通过比较不同人脸图像的LBP编码直方图,达到人脸识别的目的。它的优点是不受光照、缩放、旋转和平移的影响。

顾名思义,LBPH算法采用局部特征提取的方法,这是与前两种方法最大的区别。

算法流程

LBP特征提取:根据统一的LBP算子对原始图像进行处理;

LBP特征匹配(直方图计算):将图像分成若干子区域,根据子区域内的LBP值统计其直方图,以直方图作为其区别特征。

4.算法的复制代码

1),特征脸算法。

#编码=utf-8

将numpy作为np导入

导入cv2

导入操作系统

类别特征面(对象):

def __init__(self,threshold,dimNum,dsize):

self . threshold = threshold # threshold尚未使用。

self.dimNum = dimNum

self.dsize = dsize

def loadImg(自身,文件名,尺寸):

'''

加载图像,灰度化,统一大小,直方图均衡化。

:param fileName:图像文件名

:paramsize:统一大小。元组形式

:返回:图像矩阵

'''

img = cv2.imread(文件名)

retImg = cv2.resize(img,dsize)

retImg = cv2.cvtColor(retImg,cv2。彩色_ RGB 2灰色)

retImg = cv2.equalizeHist(retImg)

# cv2.imshow('img ',retImg)

# cv2.waitKey()

返回重定位

def createImgMat(self,dirName):

'''

生成图像样本矩阵,该矩阵被组织为行为属性并作为样本列出。

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

:返回:样本矩阵,标签矩阵

'''

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

label = []

对于父目录,目录名,os.walk中的文件名(目录名):

#打印父项

#打印目录名

#打印文件名

指数= 0

对于目录名中的目录名:

对于os.walk中的子父项、子文件名、子文件名(父+'/'+目录名):

对于子文件名中的文件名:

img = self . load img(sub pent+'/'+filename,self.dsize)

tempImg = NP . shape(img,(-1,1))

如果索引== 0:

dataMat = tempImg

否则:

dataMat = NP . column _ stack((dataMat,tempImg))

label.append(子部分+'/'+文件名)

指数+= 1

返回数据表,标签

def PCA(self,dataMat,dimNum):

'''

PCA函数,用于数据降维。

:param dataMat:样本矩阵

:param dimNum:降维后的目标维度。

:返回:降维后的样本矩阵和变换矩阵。

'''

#平均矩阵

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

打印'平均矩阵尺寸',表示矩阵形状

diffMat = dataMat-meanMat

#求协方差矩阵,因为样本维数远大于样本数,所以不要直接求协方差矩阵,采用以下方法。

cov mat =(diff mat . t * diff mat)/float(diff mat . shape[1])#规范化

#covMat2 = np.cov(dataMat,bias=True)

# print '基本方法计算的协方差矩阵是',covMat2。

打印“协方差矩阵维数”,covMat.shape

eigVals,EIG vects = NP . linalg . EIG(NP . mat(cov mat))

打印“特征向量维数”,特征向量。形状

打印“特征值”,特征值

eigVects = diffMat*eigVects

eigValInd = np.argsort(eigVals)

EIG valind = EIG valind[::-1]

EigValInd = eigValInd[:dimNum] #取出指定数字的前n个特征值。

打印“选定特征值”,eigValInd

EIG vectors = EIG vectors/NP . linalg . norm(EIG vectors,axis = 0) #归一化特征向量

redeigwects = EIG vects[:,eigValInd]

打印“选定的特征向量”,重新设计向量。形状

打印'平均矩阵维数',差异矩阵形状

lowMat = redEigVects。t *差分格式

打印'低维矩阵维度',lowMat.shape

返回lowMat,重新设计

定义比较(自身、数据、测试、标签):

'''

比较函数,这里只使用最简单的欧几里德距离比较,还可以使用KNN等方法,如果需要在这里修改的话。

:param dataMat:样本矩阵

:参数测试:原始形式的测试图像矩阵。

:参数标签:标签矩阵

:return:与测试图像最接近的图像文件名。

'''

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

testImg = cv2.cvtColor(testImg,cv2。彩色_ RGB 2灰色)

testImg = NP . shape(testImg,(-1,1))

lowMat,redVects = self。PCA(dataMat,self.dimNum)

testImg = redVects。t *测试

打印“检测样品的转换尺寸”,testimg.shape。

disList = []

testVec = NP . shape(testImg,(1,-1))

适用于lowMat中的样品。t:

dislist . append(NP . linalg . norm(test vec-sample))

打印列表

sortIndex = np.argsort(disList)

返回标签[sortIndex[0]]

定义预测(自身,目录名,测试文件名):

'''

预测功能

:param dirName:包含定型数据集的文件夹的路径。

:param testFileName:测试图像文件名。

:返回:预测结果

'''

testImg = cv2 . im read(test filename)

dataMat,label = self.createImgMat(目录名)

打印“加载图片标签”,标签

ans = self.compare(数据、测试、标签)

返回答案

if __name__ == '__main__ ':

eigenface = EigenFace(20,50,(50,50))

打印特征脸。Predict ('d:/face ',' d:/face _ test/1。BMP') 2)、FisherFaces算法。

#编码=utf-8

将numpy作为np导入

导入cv2

导入操作系统

类FisherFace(对象):

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

self . threshold = threshold # threshold,尚未使用。

Self.k = k #指定投影的数量w。

Self.dsize = dsize #统一大小

def loadImg(自身,文件名,尺寸):

'''

加载图像,灰度化,统一大小,直方图均衡化。

:param fileName:图像文件名

:paramsize:统一大小。元组形式

:返回:图像矩阵

'''

img = cv2.imread(文件名)

retImg = cv2.resize(img,dsize)

retImg = cv2.cvtColor(retImg,cv2。彩色_ RGB 2灰色)

retImg = cv2.equalizeHist(retImg)

# cv2.imshow('img ',retImg)

# cv2.waitKey()

返回重定位

def createImgMat(self,dirName):

'''

生成图像样本矩阵,该矩阵被组织为行为属性并作为样本列出。

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

:返回:包含样本矩阵的列表,标签列表

'''

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

label = []

数据列表= []

对于父目录,目录名,os.walk中的文件名(目录名):

#打印父项

#打印目录名

#打印文件名

#index = 0

对于目录名中的目录名:

对于os.walk中的子父项、子文件名、子文件名(父+'/'+目录名):

对于索引,枚举中的文件名(子文件名):

img = self . load img(sub pent+'/'+filename,self.dsize)

tempImg = NP . shape(img,(-1,1))

如果索引== 0:

dataMat = tempImg

否则:

dataMat = NP . column _ stack((dataMat,tempImg))

dataList.append(数据材质)

label.append(子部分)

返回数据列表,标签

def LDA(self,dataList,k):

'''

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

:参数数据列表:样本矩阵列表

:param k:投影向量的数量k

:返回:转换后的矩阵列表和转换后的矩阵。

'''

n =数据列表[0]。形状[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 = []

对于dataList中的dataMat:

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

meanList.append(meanMat)

sample num . append(datamat . shape[1])

dataMat = dataMat-meanMat

sw =数据矩阵*数据矩阵。T

软件+=软件

打印“软件尺寸”,软件形状

对于索引,枚举中的mean mat(mean list):

m = sample num[索引]

u += m*meanMat

N += m

u = u/N

打印“u形的尺寸”

对于索引,枚举中的mean mat(mean list):

m = sample num[索引]

sb = m*(meanMat-u)*(meanMat-u)。T

Sb += sb

打印“某人的尺寸”,某人的形状

eigVals,EIG vects = NP . Lina LG . EIG(NP . mat(NP . Lina LG . inv(Sw)* Sb))

eigValInd = np.argsort(eigVals)

EIG valind = EIG valind[::-1]

EigValInd = eigValInd[:k] #取指定个数的前k个特征值。

打印“选定特征值”,特征值有效。形状

EIG vectors = EIG vectors/NP . linalg . norm(EIG vectors,axis = 0) #归一化特征向量

redeigwects = EIG vects[:,eigValInd]

打印“转换矩阵维度”,重定向。形状

transMatList = []

对于dataList中的dataMat:

trans matlist . append(redeig vects。T*dataMat)

返回transMatList,redEigVects

定义比较(自身、数据列表、测试、标签):

'''

比较函数,这里只使用最简单的欧几里德距离比较,还可以使用KNN等方法,如果需要在这里修改的话。

:参数数据列表:样本矩阵列表

:参数测试:原始形式的测试图像矩阵。

:参数标签:标签矩阵

:return:最接近测试图像的图像文件夹,即类别。

'''

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

testImg = cv2.cvtColor(testImg,cv2。彩色_ RGB 2灰色)

testImg = NP . shape(testImg,(-1,1))

transMatList,redVects = fisherface。LDA(数据表,self.k)

testImg = redVects。t *测试

打印“检测样品的转换尺寸”,testimg.shape。

disList = []

testVec = NP . shape(testImg,(1,-1))

sum vec = NP . mat(NP . zeros((self . dsize[0]* self . dsize[1],1)))

对于transMatList中的transMat:

用于transMat中的样品。t:

dislist . append(NP . linalg . norm(test vec-sample))

打印列表

sortIndex = np.argsort(disList)

返回标签[sortIndex[0]/9]

定义预测(自身,目录名,测试文件名):

'''

预测功能

:param dirName:包含定型数据集的文件夹的路径。

:param testFileName:测试图像文件名。

:返回:预测结果

'''

testImg = cv2 . im read(test filename)

dataMat,label = self.createImgMat(目录名)

打印“加载图片标签”,标签

ans = self.compare(数据、测试、标签)

返回答案

if __name__=="__main__ ":

fisherface = FisherFace(10,20,(20,20))

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

打印ans3),LBPH算法

#编码=utf-8

将numpy作为np导入

导入操作系统

导入cv2

LBP类(对象):

def __init__(self,threshold,dsize,blockNum):

Self.dsize = dsize #统一大小

Self.blockNum = blockNum #划分的块数

self . threshold = threshold # threshold,尚未使用。

def loadImg(自身,文件名,尺寸):

'''

加载图像,灰度化,统一大小,直方图均衡化。

:param fileName:图像文件名

:paramsize:统一大小。元组形式

:返回:图像矩阵

'''

img = cv2.imread(文件名)

retImg = cv2.resize(img,dsize)

retImg = cv2.cvtColor(retImg,cv2。彩色_ RGB 2灰色)

retImg = cv2.equalizeHist(retImg)

# cv2.imshow('img ',retImg)

# cv2.waitKey()

返回重定位

def loadImagesList(self,dirName):

'''

加载图像矩阵列表

:param目录名:文件夹路径

:返回:包含最原始图像矩阵的列表和标签矩阵。

'''

imgList = []

label = []

对于父目录,目录名,os.walk中的文件名(目录名):

#打印父项

#打印目录名

#打印文件名

对于目录名中的目录名:

对于os.walk中的子父项、子文件名、子文件名(父+'/'+目录名):

对于子文件名中的文件名:

img = self . load img(sub pent+'/'+filename,self.dsize)

ImgList.append(img) #原始图像矩阵被添加到列表中,不做任何处理。

label.append(子部分+'/'+文件名)

返回imgList,标签

def getHopCounter(self,num):

'''

计算二进制序列是否只改变两次。

:参数编号:编号

:return: 01更改次数

'''

binNum = bin(数量)

binStr = str(binNum)[2:]

n = len(binStr)

如果n =中心)*(1扩展知识:人脸识别算法研究的难点

人脸识别算法的研究由来已久,大多数算法在背景简单的情况下都能很好的处理。但是人脸识别的应用范围很广,而且只是简单的图像测试,远远不能满足实际需求。所以人脸识别算法还有很多难点。

照明

光照是机器视觉,尤其是人脸识别中的老问题,算法还没到能用的程度。

态度

与光照问题类似,姿态问题也是人脸识别研究中需要解决的技术难点。对姿态的研究相对较少,大多数人脸识别算法主要是针对正面或接近正面的人脸图像。当俯仰或者左右严重时,人脸识别算法的识别率也会急剧下降。

避难所

遮挡对于非合作条件下的人脸图像采集来说是一个非常严重的问题,尤其是在监控环境中,被监控对象经常佩戴眼镜、帽子等饰品,可能会使采集到的人脸图像不完整,从而影响后期的特征提取和识别,甚至导致人脸识别算法的失败。

年龄变化

随着年龄的变化,面部容貌也在发生变化,尤其是青少年,这种变化更为明显。对于不同的年龄段,人脸识别算法的识别率是不同的。

图像质量

人脸图像的来源可能多种多样,由于采集设备的不同,获得的人脸图像质量也不尽相同,特别是对于那些分辨率低、噪声大、质量差的人脸图像,如何有效地识别人脸是一个需要关注的问题。同样,对于高分辨率图像,对人脸识别算法的影响需要进一步研究。

缺少样品

基于统计学习的人脸识别算法是人脸识别领域的主流算法,但是统计学习方法需要大量的训练。由于人脸图像在高维空间的分布是一种不规则的流行分布,所以能够得到的样本只是人脸图像空间中很小的一部分。如何解决小样本下的统计学习问题,需要进一步研究。

海量数据

传统的人脸识别算法如PCA和LDA可以很容易地在小规模数据中训练和学习。但是,对于大量的数据,这些方法的训练过程是困难的,甚至可能崩溃。

大规模人脸识别

随着人脸数据库的增长,人脸算法的性能会下降。