Eigenface(PCA)人脸识别实验

2024-01-09 22:10

本文主要是介绍Eigenface(PCA)人脸识别实验,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、ORL数据集简介

ORL人脸数据集一共包含40个不同人的400张图像,是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。

此数据集下包含40个目录,每个目录下有10张图像,每个目录表示一个不同的人。所有的图像是以PGM格式存储,灰度图,图像大小宽度为92,高度为112。对每一个目录下的图像,这些图像是在不同的时间、不同的光照、不同的面部表情(睁眼/闭眼,微笑/不微笑)和面部细节(戴眼镜/不戴眼镜)环境下采集的。所有的图像是在较暗的均匀背景下拍摄的,拍摄的是正脸(有些带有略微的侧偏)。

每个目录分别命名为sx,其中x表示受试者编号(在1到40之间)。在每一个目录所选受试者的10张不同的图像,分别命名为:y.pgm,其中y表示特定对象的不同面部表情、细节(1到10之间)。

ORL人脸数据集下载地址

2、PCA变换原理

在人脸识别过程中,一般把图片看成是向量进行处理,高等数学中我们接触的一般都是二维或三维向量,向量的维数是根据组成向量的变量个数来定的,例如就是一个二维向量,因为其有两个参量。而在将一幅图像抽象为一个向量的过程中,我们把图像的每个像素定为一维,对于一幅的普通图像来说,最后抽象为一个维的高维向量,如此庞大的维数对于后续图像计算式来说相当困难,因此有必要在尽可能不丢失重要信息的前提下降低图像维数,PCA就是降低图像维数的一种方法。图像在经过PCA变换之后,可以保留任意数量的对图像特征贡献较大的维数分量,也就是你可以选择降维到30维或者90维或者其他,当然最后保留的维数越多,图像丢失的信息越少,但计算越复杂。

3、、数据提取与处理

%matplotlib inline
# 导入所需模块
import matplotlib.pyplot as plt
import numpy as np
import os
import cv2
# plt显示灰度图片
def plt_show(img):plt.imshow(img,cmap='gray')plt.show()# 读取一个文件夹下的所有图片,输入参数是文件名,返回文件地址列表
def read_directory(directory_name):faces_addr = []for filename in os.listdir(directory_name):faces_addr.append(directory_name + "/" + filename)return faces_addr# 读取所有人脸文件夹,保存图像地址在faces列表中
faces = []
for i in range(1,41):faces_addr = read_directory('C:/Users/ASUS/Desktop/att_faces/s'+str(i))for addr in faces_addr:faces.append(addr)# 读取图片数据,生成列表标签
images = []
labels = []
for index,face in enumerate(faces):# enumerate函数可以同时获得索引和值image = cv2.imread(face,0)images.append(image)labels.append(int(index/10+1))

先读取ORL数据集下的所有图像,同时生成列表标签。下图表示一共有400个标签、400张图像、图像的数据类型以及标签的值。

print(len(labels))
print(len(images))
print(type(images[0]))
print(labels)

在这里插入图片描述

# 画出最后20组人脸图像
# 创建画布和子图对象
fig, axes = plt.subplots(10,20,figsize=(20,10),subplot_kw = {"xticks":[],"yticks":[]} #不要显示坐标轴)
# 图片x行y列,画布x宽y高
# 填充图像
for i, ax in enumerate(axes.flat):ax.imshow(images[i+200],cmap="gray") #选择色彩的模式

以下即位最后20组人脸图像:
在这里插入图片描述

4、PCA降维

接下来把每张图片数据降到一维,每张图片的维度是1×10304,与图片的大小92×112=10304相符,将其转换为numpy数组,方便后面的计算。

# 图像数据矩阵转换为一维
image_data = []
for image in images:data = image.flatten()# a是个矩阵或者数组,a.flatten()就是把a降到一维,默认是按横的方向降image_data.append(data)
print(image_data[0].shape)
# 转换为numpy数组
X = np.array(image_data)
y = np.array(labels)
print(type(X))
print(X.shape)

接下来导入sklearn的PCA模块,根据标签,使用train_test_split()划分数据集,训练PCA模型,保留100个维度,输出100个特征脸,可以发现越到后面人脸越模糊,意味着所占的比重越小。

# 导入sklearn的pca模块
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split# 画出每个图像数据降到一维后的矩阵
import pandas as pd
data = pd.DataFrame(X)
data.head()

在这里插入图片描述

# 划分数据集
x_train,x_test,y_train,y_test = train_test_split(X, y, test_size=0.2) # train训练,test测试# 训练PCA模型
pca=PCA(n_components=100) # 保留100个纬度
pca.fit(x_train) # 训练过程# 返回训练集和测试集降维后的数据集
x_train_pca = pca.transform(x_train) # 转换过程
x_test_pca = pca.transform(x_test)
print(x_train_pca.shape) # 320个训练集,保留了100个特征
print(x_test_pca.shape) # 80个测试集,保留了100个特征V = pca.components_
V.shape
# 100个特征脸
# 创建画布和子图对象
fig, axes = plt.subplots(10,10,figsize=(15,15),subplot_kw = {"xticks":[],"yticks":[]} #不要显示坐标轴)
#填充图像
for i, ax in enumerate(axes.flat):ax.imshow(V[i,:].reshape(112,92),cmap="gray") #reshape规定图片的大小,选择色彩的模式

在这里插入图片描述
查看降维后每个新特征向量所占的信息量占原始数据总信息量的百分比,将其相加,可以得到特征所携带的数据是原始数据的90.056%,从10304维降低到100维,却能够保留90%的信息,这就是PCA降维的魅力所在。

# 该选择多少个特征呢?
# 属性explained_variance_ratio,查看降维后每个新特征向量所占的信息量占原始数据总信息量的百分比
# 又叫做可解释方差贡献率
pca.explained_variance_ratio_

在这里插入图片描述

# 返回特征所携带的数据是原始数据的多少
pca.explained_variance_ratio_.sum()

画出特征个数和所携带信息数的曲线图。

# 画出特征个数和所携带信息数的曲线图,总共画了150个特征
explained_variance_ratio = []
for i in range(1,151): pca=PCA(n_components=i).fit(x_train)explained_variance_ratio.append(pca.explained_variance_ratio_.sum())
plt.plot(range(1,151),explained_variance_ratio)
plt.show()

在这里插入图片描述

5、使用OpenCV的EigenFace算法进行识别

原理:将训练集图像和测试集图像都投影到特征向量空间中,再使用聚类方法(最近邻或k近邻等)得到测试集中的每个图像最近的图像,进行分类即可。

cv2.face.EigenFaceRecognizer_create()创建人脸识别的模型,通过图像数组和对应标签数组来训练模型。

predict()函数进行人脸预测,该函数会返回两个元素的数组,第一个是识别个体的标签;第二个是置信度,越小匹配度越高,0表示完全匹配。

getEigenValues() 获得特征值,getEigenVectors() 特征向量,getMean() 均值。

使用OpenCV的EigenFace算法进行识别,首先创建、训练模型,然后挑选一张测试集图片进行预测,此处选择第一张测试集图片,预测的结果是第13个人的图像,与真实结果相符测试集的识别准确率为96%。

# 模型创建与训练
model = cv2.face.EigenFaceRecognizer_create()
model.train(x_train,y_train)
# 预测
res = model.predict(x_test[0])
print(res)

输出:(13, 1653.922120378922)

y_test[0]

输出:13

# 测试数据集的准确率
ress = []
true = 0
for i in range(len(y_test)):res = model.predict(x_test[i])if y_test[i] == res[0]:true = true+1else:print(i)print('测试集识别准确率:%.2f'% (true/len(y_test)))

输出:
10
36
53
测试集识别准确率:0.96

6、自定义图片测试

重新构建训练模型,将所有的图片用作训练集,同样保留100个维度,与测试集保持一致,输入自定义的图片,输入的图片是被画过两笔的第一个人的图片。

# 降维
pca=PCA(n_components=100)
pca.fit(X)
X = pca.transform(X)# 将所有数据都用作训练集
# 模型创建与训练
model = cv2.face.EigenFaceRecognizer_create()
model.train(X,y)
# 输入图片识别,同时进行灰度处理
# 此图片是s1文件夹里的图片画了两笔
img = cv2.imread('C:/Users/ASUS/Desktop/test.jpg',0)
plt_show(img)
print(img.shape)

在这里插入图片描述

imgs = []
imgs.append(img)# 矩阵
image_data = []
for img in imgs:data = img.flatten()image_data.append(data)test = np.array(image_data)
test.shape

输出:(1, 10304)

# 用训练好的pca模型给图片降维
test = pca.transform(test)
test[0].shape

输出:(100,)

res = model.predict(test)
res
print('人脸识别结果:',res[0])

输出:人脸识别结果: 1

参考博客:opencv基于PCA降维算法的人脸识别(att_faces)

使用Eigenface重构近似的人脸图像

Fisherface(FLD)人脸识别实验

如果你觉得还不错,那就给我点个赞吧(* ̄︶ ̄)

这篇关于Eigenface(PCA)人脸识别实验的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/588608

相关文章

STM32(十一):ADC数模转换器实验

AD单通道: 1.RCC开启GPIO和ADC时钟。配置ADCCLK分频器。 2.配置GPIO,把GPIO配置成模拟输入的模式。 3.配置多路开关,把左面通道接入到右面规则组列表里。 4.配置ADC转换器, 包括AD转换器和AD数据寄存器。单次转换,连续转换;扫描、非扫描;有几个通道,触发源是什么,数据对齐是左对齐还是右对齐。 5.ADC_CMD 开启ADC。 void RCC_AD

HNU-2023电路与电子学-实验3

写在前面: 一、实验目的 1.了解简易模型机的内部结构和工作原理。 2.分析模型机的功能,设计 8 重 3-1 多路复用器。 3.分析模型机的功能,设计 8 重 2-1 多路复用器。 4.分析模型机的工作原理,设计模型机控制信号产生逻辑。 二、实验内容 1.用 VERILOG 语言设计模型机的 8 重 3-1 多路复用器; 2.用 VERILOG 语言设计模型机的 8 重 2-1 多

深度学习实战:如何利用CNN实现人脸识别考勤系统

1. 何为CNN及其在人脸识别中的应用 卷积神经网络(CNN)是深度学习中的核心技术之一,擅长处理图像数据。CNN通过卷积层提取图像的局部特征,在人脸识别领域尤其适用。CNN的多个层次可以逐步提取面部的特征,最终实现精确的身份识别。对于考勤系统而言,CNN可以自动从摄像头捕捉的视频流中检测并识别出员工的面部。 我们在该项目中采用了 RetinaFace 模型,它基于CNN的结构实现高效、精准的

61.以太网数据回环实验(4)以太网数据收发器发送模块

(1)状态转移图: (2)IP数据包格式: (3)UDP数据包格式: (4)以太网发送模块代码: module udp_tx(input wire gmii_txc ,input wire reset_n ,input wire tx_start_en , //以太网开始发送信

LTspice模拟CCM和DCM模式的BUCK电路实验及参数计算

关于BUCK电路的原理可以参考硬件工程师炼成之路写的《 手撕Buck!Buck公式推导过程》.实验内容是将12V~5V的Buck电路仿真,要求纹波电压小于15mv. CCM和DCM的区别: CCM:在一个开关周期内,电感电流从不会到0. DCM:在开关周期内,电感电流总会到0. CCM模式Buck电路仿真: 在用LTspice模拟CCM电路时,MOS管驱动信号频率为100Khz,负载为10R(可自

HCIA--实验十:路由的递归特性

递归路由的理解 一、实验内容 1.需求/要求: 使用4台路由器,在AR1和AR4上分别配置一个LOOPBACK接口,根据路由的递归特性,写一系列的静态路由实现让1.1.1.1和4.4.4.4的双向通信。 二、实验过程 1.拓扑图: 2.步骤: (下列命令行可以直接复制在ensp) 1.如拓扑图所示,配置各路由器的基本信息: 各接口的ip地址及子网掩码,给AR1和AR4分别配置

OpenGL/GLUT实践:流体模拟——数值解法求解Navier-Stokes方程模拟二维流体(电子科技大学信软图形与动画Ⅱ实验)

源码见GitHub:A-UESTCer-s-Code 文章目录 1 实现效果2 实现过程2.1 流体模拟实现2.1.1 网格结构2.1.2 数据结构2.1.3 程序结构1) 更新速度场2) 更新密度值 2.1.4 实现效果 2.2 颜色设置2.2.1 颜色绘制2.2.2 颜色交互2.2.3 实现效果 2.3 障碍设置2.3.1 障碍定义2.3.2 障碍边界条件判定2.3.3 障碍实现2.3.

pta-2024年秋面向对象程序设计实验一-java

文章申明:作者也为初学者,解答仅供参考,不一定是最优解; 一:7-1 sdut-sel-2 汽车超速罚款(选择结构) 答案: import java.util.Scanner;         public class Main { public static void main(String[] arg){         Scanner sc=new Scanner(System

如何校准实验中振镜频率的漂移

在实验过程中,使用共振扫描振镜(如Cambridge Technology的8kHz振镜)时,频率漂移是一个常见问题,尤其是在温度变化或长期运行的情况下。为了确保实验的准确性和稳定性,我们需要采取有效的校准措施。本文将介绍如何监测、调节和校准振镜频率,以减少漂移对实验结果的影响。 1. 温度管理和稳定性控制 振镜的频率变化与温度密切相关,温度的升高会导致机械结构的变化,进而影响振镜的共

实验C语言“union”的最基础语法

目标 最近在看Rust的“菜鸟教程”,看到 Rust 枚举类 时我发现它所定义的“枚举类”虽然也能像C语言枚举类那样使用,但是多了些功能:对于某个枚举的成员,还可以附带独特的数据,这让我想起了C语言中的union。 而我事实上对union没有使用经验,我自己写程序的时候不用它,看其他的项目的程序时印象里也没见过它。所以我对union的设计意图理解不深(可能只是为了节省内存?)。本篇的目标是对其