基于kNN的人脸识别算法

2021/8/14 20:06:04

本文主要是介绍基于kNN的人脸识别算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

  • 摘要:

    本次实验尝试通过将人脸的图像转化为特征向量,然后训练数据集,通过计算欧拉距离找到与待测人脸最接近的k个人脸,这样对人脸进行归类识别实现一个基于KNN 的人脸识别算法,来达到人脸识别的入门级学习。

  • 算法简介:

    KNN算法假设给定一个训练数据集,其中的实例类别已定。分类时,对新的实例,根据其 k 个最近邻的训练实例的类别,通过多数表决等方式进行预测。因此,KNN算法不具有显式的学习过程。
    KNN算法实际上利用训练数据集对特征向量空间进行划分,并作为其分类的“模型”。 k值的选择、距离度量以及分类决策规则是k近邻算法的三个基本要素。

  • 算法流程:

    1.假设有一个带有标签的样本数据集(训练样本集),其中包含每条数据与所属分类的对应关系。遍历训练数据集,计算预测样本与其他每一个样本点的距离,按照由近到远排序。完成训练得到训练后的数据集After training Data Set

    2.定义一个KNN参数k 值(1<=k<=20),表示纳入投票决策的样本数

    3.输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较(进行测试集的测试)。
    4.取前 k个样本数据对应的分类标签。求 k 个数据中出现次数最多的分类标签作为新数据的分类。

  • 实验环境:

    python版本为:python-3.8.1,所需运行库有matplotlib、numpy及pillow

  • 源代码

    import matplotlib.pyplot as plt
    from PIL import Image, ImageFilter
    import numpy
    import heapq
    
    dataBase="data_base"
    persons=[]
    faces=[]
    for i in range(1, 41):
        persons.append("s" + str(i))
    for i in range(1, 11):
        faces.append(str(i) + ".pgm")
    
    def parseImageToVector(path):
        """
        功能:将图像转换为特征矢量
        输入:图像的路径
        返回值:特征向量(numpy一维数组)
        """
        img = numpy.array(Image.open(path)) 
        return img.flatten()
    
    def eularDistance(vec1, vec2):
        """
        功能:计算两个特征向量的eular距离
        输入:特征向量1,2
        返回值:欧拉距离
        """
        return numpy.sum(numpy.square(vec1-vec2))
    
    def trainSetInitialization(faces):
        """
        功能:初始化训练数据集
        输入:用作训练集的人脸ID列表
        返回值:初始化的数据集,(数据, 标签, 图像)元组列表
        """
        trainSet = []
        for person in persons:
            for face in faces:
                imgPath = dataBase + "/" + person + "/" + str(face) + ".pgm"
                imgVec = parseImageToVector(imgPath)
                trainSet.append((imgVec, person, str(face)))
        return trainSet
    
    def faceRecognition(face, trainSet, k):
        """
        功能:识别人脸,计算训练数据集中的哪张脸与此脸相同(KNN实现)
        输入:face数组中的测试脸,trainDataSet训练后的数据,kNN参数
        返回:数据集中最相同的面孔的标签
        """
        heap = [] #小根堆,储存(距离,标号,人脸)元组
        neighbors = [] # 保存前k个点的信息
        result = {} # { key : val } 表示一组k近邻点中 { 标签 : 标签数量(1<=n<=k) }
        # 计算前k个最近的点,压入小根堆heap
        for trainData in trainSet:
            # trainData[1]对应person标签, trainData[0]对应该标签下的某个特征向量
            heapq.heappush(heap, (eularDistance(face, trainData[0]), trainData[1], trainData[2]) ) 
    
        # 找到前k个最近的点中数量最多的标签,并加入结果result
        for i in range(k):
            first = heapq.heappop(heap)
            top = first[1] # 标签
            topImg = first[2] # 图像
            neighbors.append((top, topImg))
            if top in result:
                result[top] = result[top] + 1
            else:
                result[top] = 1
        maximum = (None, 0)
        for label in result:
            if result[label] > maximum[1]:
                maximum = (label, result[label])
        # 显示信息
        print("测试所属标签:" + maximum[0])
        print("各标签对应的数量" + str(result))
        print("与目标k近邻的人脸信息:")
        for neighbor in neighbors:
            path = dataBase + "/" + neighbor[0] + "/" + neighbor[1] + ".pgm"
            print(path)
        print("-------------分界线--------------")
        return maximum[0]
    
    def main():
        fault = 0
        total = 0
        kList = []
        misclassificationRateList = []
        for k in range(1, 21):
            for testIndex in range(1, 11):
                # 初始化训练集
                trainImages = []
                for trainImage in range(1,11):
                    trainImages.append(trainImage)
                trainImages.remove(testIndex)
                trainSet = trainSetInitialization(trainImages)
    
                # 测试
                for person in persons:
                    path = dataBase + "/" + person + "/" + str(testIndex) + ".pgm"
                    faceVec = parseImageToVector(path)
                    print("测试人脸的路径:" + path)
                    result = faceRecognition(faceVec, trainSet, k)
                    if person != result:
                        fault = fault + 1
                    total = total + 1
            kList.append(k)
            misclassificationRateList.append(fault / total)
            print("misclassification rate:", fault / total)
        # 显示图像   
        plt.plot(kList, misclassificationRateList, alpha=0.7)
        plt.xticks(kList, kList)
        plt.ylabel("Misclassification Rate")
        plt.show()
    
    if __name__ == "__main__":
        main()
    
  • 实验结果及分析:

    报告pdf



这篇关于基于kNN的人脸识别算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程