ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

基于kNN的人脸识别算法

2021-08-14 19:32:12  阅读:188  来源: 互联网

标签:kNN 人脸识别 训练 标签 算法 人脸 print path 数据


  • 摘要:

    本次实验尝试通过将人脸的图像转化为特征向量,然后训练数据集,通过计算欧拉距离找到与待测人脸最接近的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,人脸识别,训练,标签,算法,人脸,print,path,数据
来源: https://www.cnblogs.com/lygin/p/15141587.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有