文章首发于我的个人博客

1、前言

在基于PCA的人脸识别算法中,二维人脸图像要先转换为一维向量。这就导致人脸图像向量将达到高维空间,由于其协方差矩阵维度很高而且训练样本很少,因此很难评估协方差矩阵的准确性。虽然我们可以通过SVD的方法来简化计算,但是将二维图像转换为一维向量,丢失了图像行列的相关信息。而2DPCA是基于二维图像矩阵的,这种处理方法不需要事先把图像转成一维向量,图像的协方差矩阵可以通过原始图像矩阵直接构造出来。

3、2DPCA推导

2.1 首先定义一个线性变换方程

Y=AXY = AX Y=AX

  • 上式中A为原始图像矩阵,X是一组正交基(特征子空间),Y是图像投影到特征子空间后的数据。

2.2 构造投影特征的协方差矩阵

SX=E(Y−EY)(Y−EY)TSx=E[AX−E(AX)][AX−E(AX)]TSx=E[(A−EA)X][(A−EA)X]TS_X = E(Y-EY)(Y-EY)^T \\ S_x = E[AX-E(AX)][AX-E(AX)]^T \\ S_x = E[(A-EA)X][(A-EA)X]^T SX​=E(Y−EY)(Y−EY)TSx​=E[AX−E(AX)][AX−E(AX)]TSx​=E[(A−EA)X][(A−EA)X]T

2.3 构造图像协方差矩阵

Gt=E[(A−EA)T)(A−EA)]G_t = E[(A-EA)^T)(A-EA)] Gt​=E[(A−EA)T)(A−EA)]

  • 矩阵GtG_tGt​叫做图像协方差矩阵。容易验证,GtG_tGt​是一个nxn正定矩阵。我们可以使用训练样本来评估GtG_tGt​,假设共有M个训练图像样本,第j个训练样本由Aj(j=1,2,...,M)A_j(j=1,2,...,M)Aj​(j=1,2,...,M)由mxn矩阵构成,并且所有样本的平均图像为$\bar{A} 。那么,。那么,。那么,G_t$可简化为

Gt=1M∑j=1M(Aj−Aˉ)T(Aj−Aˉa)G_t = \frac{1}{M}\sum_{j=1}^{M}(A_j-\bar{A})^T(A_j-\bar{A}a) Gt​=M1​j=1∑M​(Aj​−Aˉ)T(Aj​−Aˉa)

2.4 计算图像协方差矩阵的特征值和特征向量

  • 得到图像协方差矩阵GtG_tGt​后,计算GtG_tGt​的特征值λi\lambda_iλi​和特征向量viv_ivi​。
  • 对特征值进行排序,取前d个特征值对应的特征向量作为特征子空间。

w={v1,v2,...,vd}w = \{v_1,v_2,...,v_d\} w={v1​,v2​,...,vd​}

2.5 特征提取(将图像映射到特征子空间)

Yk=wTAkY_k = w^TA_k Yk​=wTAk​

  • www为特征向量构成的矩阵(其维度为mxt),AkA_kAk​为第k个图像样本。

V=[Y1,Y2,...,Yd]V = [Y_1,Y_2,...,Y_d] V=[Y1​,Y2​,...,Yd​]

2.6 分类识别

d=∑j=1d∣∣Yk(i)−Yk(j)∣∣2d = \sum_{j=1}^{d}||Y_k^{(i)}-Y_k^{(j)}||_2 d=j=1∑d​∣∣Yk(i)​−Yk(j)​∣∣2​

2.7 图像重建

A^=wV\hat{A} = wV A^=wV

3、2DPCA图像重建结果

  • t=26是前t个特征值的和占所有特征值和的前99%取值。

  • 代码实现
void PcaAchieve::PCA2D_achieve(){//数据集的划分按自己情况...std::string train_image_path = "../images/ORL_faces_train_3/s";int per_class_num = 8;   //每一个类别的样本数int class_nums = 40;    //类别数//图像样本矩阵  (40 x 112 x 92)std::vector<cv::Mat> all_train_image;//平均脸      (112 x 92)cv::Mat average_face(112, 92, CV_32FC1, cv::Scalar(0));for (int i = 1; i <= 40; i++) {std::string train_image_sub_path = train_image_path + std::to_string(i);cv::Mat per_image(112, 92, CV_32FC1, cv::Scalar(0));for (int j = 1; j <= per_class_num; j++) {std::string image_path = train_image_sub_path + "/" + std::to_string(j) + ".png";std::cout << image_path << std::endl;cv::Mat image = cv::imread(image_path, 0);image.convertTo(image, 5, 1.0/255);per_image += image;}cv::Mat average_image = per_image / 8;average_face += average_image;all_train_image.push_back(average_image);}average_face /= class_nums;cv::imshow("average_face", average_face);cv::waitKey(0);//计算协方差矩阵 (112 x 92) x (92 x 112)cv::Mat conv(112, 112, CV_32FC1, cv::Scalar(0));for (int i = 0; i < class_nums; i++) {//去均值脸cv::Mat decenter_image = all_train_image[i] - average_face;conv += decenter_image * cv::Mat(decenter_image.t());}cv::Mat eigen_values;cv::Mat eigen_vectors;cv::eigen(conv, eigen_values, eigen_vectors);float eigen_value_sum;for (int j = 0; j < eigen_values.rows; j++) {eigen_value_sum += eigen_values.at<float>(j, 0);std::cout << eigen_values.at<float>(j, 0) << std::endl;}float lamb = 0;int t = 0;for (; t < eigen_values.rows; t++) {lamb += eigen_values.at<float>(t, 0);std::cout << lamb / eigen_value_sum << std::endl;if (lamb / eigen_value_sum >= 0.99) {break;}}std::cout << "get_t:" << t << std::endl;t = 5;//(112 x t)cv::Mat L_eigen_vec(112, t, 5, cv::Scalar(0));for (int i = 0; i < t; i++) {L_eigen_vec(cv::Rect(i, 0, 1, 112)) += eigen_vectors(cv::Rect(i, 0, 1, 112));}cv::Mat temp(t, 112, 5, cv::Scalar(0));for (int i = 0; i < t; i++) {temp(cv::Rect(0, i, 112, 1)) += eigen_vectors(cv::Rect(0, i, 112, 1));}std::cout << "-------------";cv::Mat test_image = cv::imread("../images/ORL_faces_test_3/s1/10.png", 0);test_image.convertTo(test_image, CV_32FC1, 1.0/255);test_image -= average_face;//将样本映射到特征子空间 (t x 112) x (112 x 92) = (t x 92)cv::Mat Y_test = cv::Mat(L_eigen_vec.t()) * test_image;//样本重建 (112 x t) x (t x 92)cv::Mat rebuild_image = L_eigen_vec * Y_test;rebuild_image += average_face;cv::imshow("rebuild_image", rebuild_image);cv::waitKey(0);
}

4、2DPCA人脸识别结果

  • 2DPCA识别人脸准确率
特征子空间维度 (112 x 1) (112 x 2) (112 x 3) (112 x 5) (112 x 10) (112 x 26) (112 x 40)
识别准确率(%) 41.25 58.75 70 73.75 83.75 90 91.25
  • 代码
void recg_face_with_2dpca()
{/***人脸识别部分***///将训练集投影到特征子空间std::vector<cv::Mat> train_sub;for (auto iter = all_train_image.begin(); iter != all_train_image.end(); iter++) {train_sub.push_back(cv::Mat(L_eigen_vec.t()) * (*iter-average_face));}//读取测试集图像std::string test_image_path = "../images/ORL_faces_test_3/s";int right = 0;for (int i = 1; i <= 40; i++) {std::string test_image_sub_path = test_image_path + std::to_string(i);cv::Mat per_image(112, 92, CV_32FC1, cv::Scalar(0));for (int j = 0; j < 2 ; j++) {std::string image_path = test_image_sub_path + "/" + std::to_string(j+9) + ".png";cv::Mat test_image = cv::imread(image_path, 0);test_image.convertTo(test_image, 5, 1.0 / 255);test_image -= average_face;cv::Mat test_image_sub = cv::Mat(L_eigen_vec.t()) * test_image;int result = compute_face_dist(train_sub, test_image_sub);std::cout << "result:" << result << std::endl;if (result == i)right++;}}std::cout << t << "  recg right :" << right << "recg accracy:" << (float)(right / 80.0) << std::endl;
}int PcaAchieve::compute_face_dist(std::vector<cv::Mat>& train_sub, cv::Mat test_image) {std::vector<float> dist_vector;for (auto iter = train_sub.begin(); iter != train_sub.end(); iter++) {float temp = cv::norm(*iter, test_image);dist_vector.push_back(temp);}auto position = std::min_element(dist_vector.begin(), dist_vector.end());int result = position - dist_vector.begin();return result + 1;
}

5、参考资料

[1] Jian Yang, D. Zhang, A. F. Frangi and Jing-yu Yang, “Two-dimensional PCA: a new approach to appearance-based face representation and recognition,” in IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 26, no. 1, pp. 131-137, Jan. 2004, doi: 10.1109/TPAMI.2004.1261097.

[2] 图像的 2DPCA 与 2D2DPCA 特征提取

[3] 【python】双向二维PCA(2D-2D PCA)算法实现

2DPCA的原理推导与实现相关推荐

  1. (各种均衡算法在MIMO中的应用对比试验)最小均方误差(MMSE)原理推导以及在MIMO系统中对性能的改善。

    文档和程序地址:下载地址 各种均衡算法在MIMO中的应用对比试验,内附原理推导,对比实验说明和结果等.包括MMSE,ZF,ZF-SIC等.代码附有原理推导小论文.仅供参考

  2. 深入理解XGBoost,优缺点分析,原理推导及工程实现

    本文的主要内容概览: 1. XGBoost简介 XGBoost的全称是eXtreme Gradient Boosting,它是经过优化的分布式梯度提升库,旨在高效.灵活且可移植.XGBoost是大规模 ...

  3. 从计算机视觉(slam)和摄影测量两个维度进行BA算法原理推导

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 摄影测量作为历史悠久的学科,在3D视觉里面很多算法发挥着重要的作用:而slam 的出现对摄影测量是某种 ...

  4. layer output 激活函数_一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)...

    在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...

  5. 深度学习(神经网络) —— BP神经网络原理推导及python实现

    深度学习(神经网络) -- BP神经网络原理推导及python实现 摘要 (一)BP神经网络简介 1.神经网络权值调整的一般形式为: 2.BP神经网络中关于学习信号的求取方法: (二)BP神经网络原理 ...

  6. Excel-个人所得税计算与原理推导

    Excel-个人所得税计算与原理推导 题目: 个人所得税的计算应为(工资-3500)*对应级别的税率-速扣数. 工资少于3500不扣税. 速扣数的意义是工资减去3500后直接乘以对应级别的税率所多扣除 ...

  7. 一文彻底搞懂BP算法:原理推导+数据演示+项目实战(下篇)

    在"一文彻底搞懂BP算法:原理推导+数据演示+项目实战(上篇)"中我们详细介绍了BP算法的原理和推导过程,并且用实际的数据进行了计算演练.在下篇中,我们将自己实现BP算法(不使用第 ...

  8. 14 最小二乘估计原理推导和线性回归的外推等

    14 最小二乘估计原理推导和线性回归的外推等 标签:机器学习与数据挖掘 (此篇R代码对应本博客系列<12 R语言手册(第五站 多元回归>) 1.简单最小二乘估计的推导   先说个历史:最小 ...

  9. EM算法的原理推导及解释

    文章目录 EM算法的原理推导及解释 前置知识:极大似然估计(Maximum Likelihood) 核心部分:期望最大化算法(Expectation Maximum) 实例:EM求解"三硬币 ...

最新文章

  1. java 连连看_java—连连看-实现封装
  2. 小甲鱼 OllyDbg 教程系列 (四) : 逆向 VisualSite Designer 之 硬件断点
  3. Java高级语法笔记-文件读写
  4. iPhone13系列预计5499起;蔚来回应31岁企业家“自动驾驶”车祸去世;小米取消MIX4防丢失模式无卡联网服务|极客头条...
  5. ios 配置java环境变量_Ios 入门 ----基本的控件
  6. php POST,HTTP_RAW_POST_DATA, and php://input
  7. Shiro - Shiro简介;Shiro与Spring Security区别;Spring Boot集成Shiro
  8. Java 正则表达式
  9. java分页之页面分页—@易小川
  10. ftp服务器连接不了文件路径,Serv-U和CuteFTP无法连接FTP服务器问题解答
  11. ffmpeg时间戳校正到相同或+1
  12. 【数学】微分(Differential)的定义,微分与导数的区别
  13. 调用高德地图API接口,实现地铁站经纬度采集
  14. PTA:输出较大或较小值(c++,函数模板)
  15. linux+4k+桌面壁纸,Ubuntu 20.04 LTS Focal Fossa 高清晰 4K 默认壁纸来了
  16. Flink运行时架构及各部署模式下作业提交流程
  17. 三、使用HM进行简单的视频隐写demo
  18. Oracle 表空间详解(tablespace)
  19. 交互设计书单--西南交大课程推荐
  20. Markdown For Typora

热门文章

  1. 3D游戏开发中的矩阵详解
  2. 崩坏3服务器维护2月8号,崩坏3影骑士月轮将在2月8日更新后正式登场
  3. 【ES6学习】对象的解构赋值
  4. 运营商SGSN与GGSN作用
  5. 法外狂徒——格雷福斯
  6. java中使用Calendar日期类获得下一个月有多少天
  7. mysql 索引的模糊查询_MYSQL语法(模糊查询,视图,索引)
  8. 使用python替换word模版中的内容
  9. ECCV2020-DETR笔记
  10. 物联网项目开发实战案例