基于主成分分析(PCA)的人脸识别算法

2023-11-11

本次实战的所有数据、文献、代码及输出均在以下百度云链接。

链接:https://pan.baidu.com/s/1tR3VCyHxL7EZx_su_3mxNg
提取码:siso

1. 要求

实战的数据及要求如下:

  1. 用到的数据库为XM2VTS中的前20个人。每个人有8张照片,分4个时段拍摄, 每个时段两张,每个时段间隔1个月。8张照片的编号为 1_1, 1_2 (拍摄于第一时段), 2_1, 2_2(拍摄于第二时段), 3_1, 3_2(拍摄于第三时段), 4_1, 4_2(拍摄于第四时段)。而20个人的照片分别在20个数据文件夹中。
    :图片也可从 http://www.ee.surrey.ac.uk/CVSSP/xm2vtsdb/自行下载
  2. 所有图像都经过剪切,只留下了人脸的部分。
  3. 程序使用1_1, 1_2, 2_1, 2_2这4幅图像进行训练,用3_1, 3_2, 4_1, 4_2这4幅图像进行测试,统计出准确率。
  4. 所参照的论文为 Face recognition using eigenfaces

2. 主成分分析(PCA)

    主成分分析(Principal Component Analysis,PCA)是一种典型的降维算法,属于非监督学习。其主要思想是通过正交变换将一组可能存在相关性的变量转换为一组线性不相关的变量。
具体推导笔记如下:(打公式太累了,直接贴图)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 主成分分析在人脸识别中的应用

具体应用步骤如下:

  1. 对于一张2-D(比如说N*N维)图像,我们在处理时通常将其向量化为N²*1的列向量。如果有M张图像,则最后处理得到N²*M维的数据矩阵
  2. 通过对N²*M维度的数据取平均,可以得到N²*1的平均脸图
  3. 将N²*M维度的数据矩阵减去平均脸图像,得到N²*M维的差值矩阵 Φ Φ Φ
  4. 求差值矩阵的N²*N²维协方差矩阵 C = Φ Φ ′ C=ΦΦ' C=ΦΦ
  5. 对协方差矩阵C进行特征值分解, C = U Σ U ′ C=U\Sigma U' C=UΣU。首先对特征值进行降序排序,再根据能量百分率准则选择合适的特征值数目及对应数目的特征向量,通常百分率取0.99或者0.95
  6. 假设选取的特征向量数目为K,那么对应特征脸图的数目也为K,得到N²*K维的变换矩阵U。将差值矩阵投影到K个特征脸图上,得到K*M维的权重矩阵 Y = U ′ M Y=U'M Y=UM。权重向量可以用来识别不同的人脸,这样看,相当于把一个N²维的数据降到了K维
  7. 对测试图像进行分类时,先将其列向量化,再减去平均脸图,然后投影到K个平均脸图上得到该测试图像的权重向量。最后计算测试图像权重向量与M张训练图像权重向量的距离,根据欧氏距离最小准则,选择距离最小的权重向量对应的类别作为测试图像的分类结果

注:这些特征向量就是特征脸图,它反映了人脸图中的变化特性,特征脸图对应的特征值越大,说明图像数据投影在这个特征脸图方向上的方差越大。同时也说明,如果保留所有的特征值,那么每一个人脸图都可以看作这些特征脸图的线性组合。那些较小的特征值对应的是噪声的影响,舍弃它们对应的特征脸图几乎不会对分类结果造成影响,因为它们包含的能量是极小的。

Small Tip:
    一张图片的维度为N*N,M张图片列向量化后维度为N²*M,使得协方差矩阵C的维度为N²*N²。当N非常大时,直接对C进行特征值分解会导致计算非常慢,常常引起内存爆表,该怎么解决呢?
                                          C = Φ Φ ′ C=ΦΦ' C=ΦΦ
                                          C ′ = Φ ′ Φ C'=Φ'Φ C=ΦΦ
假设 v i v_i vi C C C的第 i i i个特征向量, e i e_i ei C ′ C' C的第 i i i个特征向量。
                                         C ′ e i = λ e i C'e_i=\lambda e_i Cei=λei
                                        Φ ′ Φ e i = λ e i Φ'Φe_i=\lambda e_i ΦΦei=λei
                                       Φ Φ ′ Φ e i = λ Φ e i ΦΦ'Φe_i=\lambda Φe_i ΦΦΦei=λΦei
                                        C Φ e i = λ Φ e i CΦe_i=\lambda Φe_i CΦei=λΦei
C v i = λ v i Cv_i=\lambda v_i Cvi=λvi
                                          v i = Φ e i v_i=Φe_i vi=Φei
因此可以先求得 C ′ C' C的特征向量,再通过左乘差值矩阵得到C的特征向量。
这种方法的好处是将对N²*N²矩阵进行特征值分解变成了对M*M矩阵进行特征值分解,大大减少了计算量。

4. 实现代码

这次代码基于matlab,具体实现如下:
读取图片数据:

% readFiles.m
% directory表示图片所在文件夹,mode表示读取训练图像数据还是测试图像数据
function [ Images, Labels ] = readFiles( directory, mode)

    trainingdata=struct('filename',[]);   % 把训练/测试图片的名字存入trainingdata结构体
    switch(mode)
        case 'train'
            trainingdata(1).filename=['1_1Cropped'];
            trainingdata(2).filename=['1_2Cropped']; 
            trainingdata(3).filename=['2_1Cropped'];
            trainingdata(4).filename=['2_2Cropped'];
        case 'test'
            trainingdata(1).filename=['3_1Cropped'];
            trainingdata(2).filename=['3_2Cropped']; 
            trainingdata(3).filename=['4_1Cropped'];
            trainingdata(4).filename=['4_2Cropped'];
    end

    DIR = dir(directory);
    DIR(1:2) = [];      % 去除... 两个文件夹
    newM = 128;     % 新图片的尺寸
    newN = 128;
    Images = zeros(newM*newN, 80);	% 训练/测试都有80张图片
    Labels = zeros(1, 80);		% 训练/测试图像对应的标签
    count = 0;
    for i =1:length(DIR)
        if DIR(i).isdir
            SUBDIR = dir([directory,'\',DIR(i).name]);      % 依次遍历各个子目录
            SUBDIR(1:2) = [];
            for j = 1:length(SUBDIR)
                if length(SUBDIR(j).name)>14        % 如果是剪切后的图片,提取如1_1Cropped字符串
                    string =  SUBDIR(j).name(end-13:end-4);
                    flag = 0;
                    for k = 1:length(trainingdata)
                        if strcmp(string, trainingdata(k).filename)     % 和训练/测试图片名称作比较, 如果是标记为flag=1
                            flag = 1;
                            break
                        end
                    end
                    if flag ==1
                        count = count+1;        % 记录用于训练/测试的数量
                        A = imread([directory,'\',DIR(i).name,'\',SUBDIR(j).name]);     % 读取该训练/测试图片
                        if length(size(A)) == 3
                            A = rgb2gray(A);		% rgb转灰度图
                        end
                        A = imresize(A,[newM,newN]);	% 会自动进行插值运算
                        Images(:, count) = uint8(reshape(A, newM*newN, 1));
                        Labels(1, count) = str2num(DIR(i).name);
                    end
                end
            end
        end
    end
    disp([num2str(count) ' pictures for ' mode 'ing total.'])
end

主程序:

% faceRecognizePca.m
clc; clear all; close all;
directory = 'database';
M = 128;
N = 128;
% 获取训练/测试人脸图
[trainImages, trainLabels] = readFiles(directory, 'train');
[testImages, testLabels] = readFiles(directory, 'test');
% 平均人脸图
meanImages = mean(trainImages, 2);
meanImg = uint8(reshape(meanImages, [M, N]));
imshow(meanImg);
imwrite(meanImg, 'output/meanFace.jpg', 'jpg');

%% 求协方差矩阵
reduceImages = trainImages - repmat(meanImages, 1, 80);
% 由于图片维度很大,所以我们选择先求M'*M,再通过变换求回来
C = reduceImages'*reduceImages;
[vec, sigma] = eig(C);
V = reduceImages*vec;
sigma = diag(sigma);
% 将特征值由大到小进行排序
[sigma, idx] = sort(sigma, 'descend');
V = V(:, idx);
% 根据能量百分率准则,提取占总能量99%的特征图
k = sum((cumsum(sigma)/sum(sigma))<=0.99);
eigImages = V(:, 1:k);
figure();
% 画出前9张特征脸
for i = 1 : 9
    subplot(3,3,i);
    imshow(reshape(eigImages(:, i), [M, N]));
    imwrite(reshape(eigImages(:, i), [M, N]), ['output/eigenFace' num2str(i) '.jpg'], 'jpg')
end

%% 利用欧氏距离最小准则来进行分类
% 将训练图片和测试图片投影到特征图上获得权重向量
trainW = eigImages'*trainImages;
testW = eigImages'*testImages;
predTest = zeros(size(testLabels));
for i = 1 : size(testImages, 2)
    diff = sqrt(sum((repmat(testW(:, i), 1, 80)-trainW).^2, 1));
    [~, minIdx] = min(diff);	% 找到欧氏距离最小对应的权重向量
    predTest(i) = testLabels(minIdx);
end
acc = sum(predTest==testLabels)/size(testImages, 2);
disp(['Accuracy of the test images is ' num2str(acc*100) '%.'])

实验过程中得到的一些中间结果:

平均脸图

图1 :平均脸图
在这里插入图片描述
图2:前9个特征值对应的特征脸图

    由于只进行了PCA对数据进行降维,且使用简单的欧式距离最小准则对测试图像进行分类,最后的分类准确率为77.5%。


结语:以上内容和代码加入了自己的想法和验证,如有不当之处还请指正。
欢迎转载,标明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于主成分分析(PCA)的人脸识别算法 的相关文章

  • MATLAB 是否已有 YAML 库/解析器?

    我想使用 YAML 跨多种语言交流一些数据 将其视为 与语言无关的序列化 其中一种语言是 MATLAB 但我似乎找不到该语言的 YAML 库 我在 Google 上检查了 matlab yaml 和 matlab yaml parse 似乎
  • Matlab 的快速 JSON 解析器

    您知道 Matlab 中有一个非常快速的 JSON 解析器吗 目前我正在使用JSONlab http www mathworks com matlabcentral fileexchange 33381 jsonlab a toolbox
  • 如何建立数据流挖掘的滑动窗口模型?

    我们遇到的情况是 流 来自传感器的数据或服务器上的点击流数据 采用滑动窗口算法 我们必须将最后 例如 500 个数据样本存储在内存中 然后 这些样本用于创建直方图 聚合并捕获有关输入数据流中异常的信息 请告诉我如何制作这样的滑动窗 如果您询
  • 使用 python 在网络上部署 matlab 应用程序

    您好 我想使用 python 在网络上部署 matlab 应用程序 有没有办法做到这一点 我已按照数学工作网站上的文档将我的应用程序转换为 jar 文件 java 类 有人能指出我前进的正确方向吗 事实上 您的 Matlab 代码打包为 J
  • Microsoft Visual C++ 2008 和 R2007b 的 Mex 类型

    我想对 vs2008 和 matlab2007b 使用 mex 类型 我尝试了下面的代码 include
  • 将 3d 矩阵重塑为 2d 矩阵

    我有一个 3d 矩阵 n by m by t 在 MATLAB 中表示n by m一段时间内网格中的测量值 我想要一个二维矩阵 其中空间信息消失了 只有n m随着时间的推移测量t剩下 即 n m by t 我怎样才能做到这一点 你需要命令r
  • 在 MATLAB 中用两个值替换向量值

    我必须创建一个以向量作为输入的函数v和三个标量a b and c 该函数替换了的每个元素v等于a有一个二元素数组 b c 例如 给定v 1 2 3 4 and a 2 b 5 c 5 输出将是 out 1 5 5 3 4 我的第一次尝试是尝
  • 在 Matlab 中快速加载大块二进制文件

    我有一些相当大的 int16 格式的数据文件 256 个通道 大约 75 1 亿个样本 每个文件约 40 50 GB 左右 它以平面二进制格式编写 因此结构类似于 CH1S1 CH2S1 CH3S1 CH256S1 CH1S2 CH2S2
  • 整数的十进制表示形式中的分隔数字

    例如 我想将用户输入作为整数输入 45697 并将前两位数字存储在数组 向量或其他内容中 例如 4 5 6 9 7 这样我就可以使用一些函数调用来检查前两个值 4 5 并对它们进行计算 问题 我不知道如何存储恢复前两个值 有没有简单的函数调
  • 优化 MATLAB 代码(嵌套 for 循环计算相似度矩阵)

    我正在 MATLAB 中基于欧几里德距离计算相似度矩阵 我的代码如下 for i 1 N M N is the size of the matrix x for whose elements I am computing similarit
  • 单元格的 Fieldnames 函数的等效项

    正如标题所说 只是想知道是否有一个函数可以用作字段名 http www mathworks co uk help matlab ref fieldnames html 但适用于单元格 所以如果我有类似的东西 a imread redsqua
  • 为什么 MATLAB 本机函数 cov(协方差矩阵计算)使用与我预期不同的除数?

    给定一个 M 维和 N 个样本的数据矩阵数据 例如 data randn N M 我可以计算协方差矩阵 data mu data ones N 1 mean data cov matrix data mu data mu N 如果我使用原生
  • 为什么 MATLAB 在打印大量 (.png) 图形时速度会变慢?

    我正在将大量数字打印为 png 文件 每个图都是数据矩阵中的一列图 我获取 png 文件并将它们串在一起形成动画 我的问题是 前几百张图像打印得很快 但创建每个新图形的时间却迅速增加 从前几百个 png 文件的约 0 2 秒到第 800 个
  • 如何加载具有可变文件名的 .mat 文件?

    select all mat files oar dir oar mat n oar name loop through files for l 1 length oar load pat oar l lt this is the mat
  • MATLAB - GUI 和 OPC 服务器

    我想在 MATLAB 中设计一个图形用户界面 可以使用 MATLAB 的过程控制对象链接和嵌入 OPC 工具箱连续读取数据 我怎样才能实现这个 我已经设计了图形用户界面 但我无法将数据读入图形用户界面 就这样做 type opctoolMA
  • 归一化互相关的基础知识

    我正在尝试使用范数校正2 归一化互相关 http en wikipedia org wiki Cross correlation Normalized cross correlation 来自 MATLAB 用于计算发育中胚胎中移动形状的速
  • 垂直子图的单一颜色条

    我想让下面的 MATLAB 图有一个沿着两个子图延伸的颜色条 像这样的事情 使用图形编辑器手动完成 Note 这与提出的问题不同here https stackoverflow com questions 39950229 matlab t
  • 检查图像中是否有太薄的区域

    我正在尝试验证雕刻机的黑白图像 更多的是剪贴画图像 不是照片 我需要考虑的主要事情之一是区域的大小 或线条的宽度 因为机器无法处理太细的线条 所以我需要找到比给定阈值更细的区域 以此图为例 竖琴的琴弦可能太细而无法雕刻 我正在阅读有关 Ma
  • 在 MATLAB 中模拟 C++ 模板

    我试图找出创建 C 模板或 Java 通用对象的替代方案的最佳方法 出于多种不同的原因 我过去曾多次想这样做 但现在我想做的是为几个相关的类创建 saveobj 和 loadobj 函数 我的想法是 我想要一组通用的例程来创建默认结构 然后
  • 我如何编写一个名为 dedbi 的 MATLAB 函数,它将输入 xtx 作为字符串并返回另一个字符串 xtxx 作为输出。

    dedbi 反转单词 即 a 将被 z 替换 b 将被 y 替换 c 将被 x 替换 依此类推 dedbi 将对大写字母执行相同的操作 即将字符串 A 替换为 Z 将 B 替换为 Y 将 C 替换为 X 依此类推 如果我给函数这个字符串 a

随机推荐

  • chatgpt赋能python:Python面向对象编程

    Python面向对象编程 Python是一种支持面向对象编程范式的高级编程语言 在Python中 面向对象编程可以很容易实现 同时也可以让代码更加简洁 可读性更高 什么是面向对象编程 面向对象编程 Object Oriented Progr
  • webpack安装遇到问题 webpack -v得到不是版本号信息

    webpack v得到不是版本号信息且vscode终端打包时报错如下 如图所示 使用npm install webpack webpack cli global 安装完webpack后 运行webpack v却出现如下错误 查阅资料分析原因
  • 清除dell服务器面板告警信息,dell服务器报警信息资料.doc

    沈阳鑫微明信息 技术支持 024沈阳鑫微明信息 技术支持 024DELL服务器LCD信息代码 DELL服务器LCD信息代码的意思 E1114Temp Ambient系统周围环境温度超出允许范围 E1116Temp Memory内存已超过允许
  • element-plus获取表格的所有选中项

    1 在el table中定义 selection change事件
  • 生产redis线程池获取不到资源问题排查

    1 查看错误日志7点报redis clients jedis exceptions JedisExhaustedPoolException Could not get a resource since the pool is exhaust
  • NSGA-II算法实战(附MATLAB源码)

    1 NSGA II算法原理 NSGA II算法全称非支配排序遗传算法II Non dominated Sorting Genetic Algorithm II NSGA II 该算法是由 NSGA 改进而来的 用于解决复杂的 多目标优化问题
  • centos7如何配置静态ip?

    1 切换到root用户 su root 2 获取可用IP地址 dhclient 这一步成功后 用ifconfig命令查看已分配的可用ip 并写到下面网卡配置中 本例中是 192 168 154 132 3 编辑网卡配置 修改标记部分 vim
  • 【前后端分离博客】学习笔记05 --- canal

    一 概述 使用canal rabbitMQ 实现 MySQL 和 Elasticsearch 的数据同步 图解 流程如下 给mysql开启binlog功能 mysql完成增 删 改操作都会记录在binlog中 canal监听binlog变化
  • caffe源码导读(六)layer.hpp头文件解析

    文章目录 一 前篇 二 正文layer hpp头文件解析 三 layer cpp相关的一些理解 四 关于序列化以及第57行为什么要先reset的小例子 本篇为基于 lt 深度学习21天实战caffe gt 所做的学习笔记 如果错误 欢迎指导
  • Ruby on rails 或 Ruby Goliath 利用redis + sidekiq 实现异步处理机制

    使用背景 在平常工作中 出于性能考虑 很多工作或者任务可以放到后台悄悄咪咪地执行 而在接口层或者界面交互的地方 给用户快速返回 利用Redis Sidekiq的组合方式 能够在Ruby on Rails web框架或者Ruby Goliat
  • 帧差法、光流法、背景减除法

    运动目标检测是指在序列图像中检测出变化区域并将运动目标从背景图像中提取出来 通常情况下 目标分类 跟踪和行为理解等后处理过程仅仅考虑图像中对应于运动目标的像素区域 因此运动目标的正确检测与分割对于后期处理非常重要然而 由于场景的动态变化 如
  • Java限制泛型可用类型与泛型通配的方式

    1 限制泛型可用类型概念 1 在定义泛型类别时 默认在实例化泛型类型的时候可以使用任何类型 但是如果想要限制泛型类型时 只能用某个特定的类型或者是其子类型才能实例化该类型时 可以定义类型时 使用extends关键字指定这个类型必须是继承某个
  • Apollo配置参数读取后再做替换

    1 先描述业务场景 在Apollo上做配置 然后读取配置 然后做替换 2 一路坎坷 2 1 在Apollo上配置 但是vlue包含有占位符 获取配置报错 Injection of autowired dependencies failed
  • docker mysql镜像忽略表名大小写

    1 安装mysql镜像 docker pull mysql 2 运行mysql docker run net host restart always privileged true v usr docker dat mysql data v
  • Linux基础学习笔记(五)——文件的ACL权限

    Linux基础学习笔记 五 文件的ACL权限 文章目录 Linux基础学习笔记 五 文件的ACL权限 前言 什么是ACL控制 setfacl getfacl mask 最大有效ACL权限 默认的ACL权限和递归的ACL权限 小结 前言 这一
  • Action行动算子 及相应的举例

    7 Action行动算子 转换算子 起始就是记录了数据的一个操作流程 RDD1 gt RDD2 gt RDD3 gt RDD4 流式运算现象 RDD1 到 RDD4 之间维护血缘关系 操作行为 RDD的转换算子是lazy加载 不执行行动算子
  • angular : 自定义组件双向绑定 [(ngModel)]

    NG VALUE ACCESSOR 用于为表单控件提供 ControlValueAccessor interface ControlValueAccessor writeValue obj any void registerOnChange
  • Java进阶9--多线程

    Java进阶9 多线程 文章目录 Java进阶9 多线程 概述 一个线程的生命周期 线程的优先级 创建一个线程 通过实现 Runnable 接口来创建线程 通过继承Thread来创建线程 Thread 方法 实例 通过 Callable 和
  • next.js 源码解析 - getStaticProps、getStaticPaths 篇

    好久前写了关于 getStaticProps 和 getStaticPaths 的内容 然而半年过去了源码解析就一直忘记了 不久前有人提醒才想起来 补下坑 本文主要是解读下 getStaticProps getStaticPaths 相关的
  • 基于主成分分析(PCA)的人脸识别算法

    本次实战的所有数据 文献 代码及输出均在以下百度云链接 链接 https pan baidu com s 1tR3VCyHxL7EZx su 3mxNg 提取码 siso 1 要求 实战的数据及要求如下 用到的数据库为XM2VTS中的前20