PCA算法:从一组照片中获取特征脸(特征向量)

2024-05-30 05:58

本文主要是介绍PCA算法:从一组照片中获取特征脸(特征向量),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文介绍了对一组照片进行PCA处理的过程和结果。本文使用OpenCV的PCA处理函数,参考了夏天的味道的博客opencv pca。本文使用的照片来源于YelaFaces(直接Baidu就能找到在CSDN上的下载链接,就不上传了)。

一、操作步骤

PCA处理的基本步骤为:

1、获取m个样本,每个样本有n个特征。

2、每个样本作为一行,构成m*n的举证A。

3、将矩阵转置再乘以自己得到C=A(t)*A。

4、求出矩阵C的特征值及特征向量,特征向量即为特征脸。

二、代码及解释

#include "stdafx.h"
#include <string>
#include <opencv2\opencv.hpp> 
using namespace std;
using namespace cv;int _tmain(int argc, _TCHAR* argv[])
{//获取了mean_faceint num_sample = 38;int norm_row = 64, norm_col = 56;int num;Mat imgs = loadImages(num);Mat mean_face = Mat(norm_row, norm_col, CV_8UC1);vector<int> mean_face_total;mean_face_total.resize(norm_row * norm_col);for (int i = 0; i < num; i++){for (int j = 0; j < norm_row * norm_col; j++){mean_face_total.at(j) += imgs.at<uchar>(i * norm_row * norm_col + j);//eigen_face_total[j] += imgs.at<uchar>(i * 192 * 168 + j);}}for (int j = 0; j < norm_row * norm_col; j++){mean_face.at<uchar>(j) = (uchar)(mean_face_total.at(j) / num);}imwrite("C:/Users/dhj555/Desktop/YelaFaces/eigen_face/0001.jpg", mean_face);imshow("eigen_face", mean_face);//1、初始化数据CvMat* pData = cvCreateMat(num_sample, norm_row * norm_col, CV_32FC1);CvMat* pMean = cvCreateMat(1, norm_row * norm_col, CV_32FC1);//每个数标志一个特征值CvMat* pEigVals = cvCreateMat(1, min(num_sample, norm_row * norm_col), CV_32FC1);//每行表示一个特征向量CvMat* pEigVecs = cvCreateMat(min(num_sample, norm_row * norm_col), norm_row * norm_col, CV_32FC1);for (int i = 0; i < num_sample; i++){for (int j = 0; j < norm_row * norm_col; j++)cvmSet(pData, i, j, imgs.at<uchar>(i * norm_row * norm_col + j));}//2、PCA处理cvCalcPCA(pData, pMean, pEigVals, pEigVecs, CV_PCA_DATA_AS_ROW);//3、选出前P个特征向量(主成份),然后投影,结果保存在pResult中,pResult中包含了P个系数//CvMat* pResult = cvCreateMat(num_sample, 20, CV_32FC1);//cvProjectPCA(pData, pMean, pEigVecs, pResult);//4、重构, 结果保存在pRecon中//CvMat* pRecon = cvCreateMat(num_sample, norm_row*norm_col, CV_32FC1);//cvBackProjectPCA(pResult, pMean, pEigVecs, pRecon);//5、显示重构的图像//Mat mRecon = Mat(pRecon);//4、显示与保存特征向量for (int i = 0; i < min(num_sample, norm_row * norm_col); i++){float min = LLONG_MAX, max = LLONG_MIN, span = 0.0;for (int index = 0; index < norm_row*norm_col; index++){float d = cvmGet(pEigVecs, i, index);if (d>max)max = d;if (d < min)min = d;}span = max - min;Mat eigen_face = Mat(norm_row, norm_col, CV_8UC1);for (int index = 0; index < norm_row*norm_col; index++){float d = cvmGet(pEigVecs, i, index);eigen_face.at<uchar>(index) = (d - min) / span * 255.0;}char buffer[128];sprintf_s(buffer, "C:/Users/dhj555/Desktop/YelaFaces/eigen_face/001/1-000%d.jpg", i);string imgPath(buffer);imshow(imgPath, eigen_face);printf("%d st:\t%f\n", i, cvmGet(pEigVals, 0, i));imwrite(imgPath, eigen_face);}
}
1、第9至16行:声明变量。
2、第18至32行:读取文件到imgs中,总共读取了38张人脸,并将每张人脸缩放为64*56大小,所以imgs为38行,64*56列的矩阵。
3、第34至40行:声明了PCA计算相关的矩阵,具体说明见代码注释。
4、第42至46行:将imgs中的数据写入pData中,以用于PCA计算。
5、第49行:调用OpenCV的函数计算特征值及特征向量。
6、第64至88行:根据特征值导出特征脸并保存显示。

三、实验结果

求出的特征值及相应的特征脸(至上传了前11个,总共38个,可以在这里 下载查看所有的):
特征值特征脸
0 st:   1512882.000000
1 st:   316433.875000
2 st:   268737.531250
3 st:   248890.359375
4 st:   177919.671875
5 st:   139744.718750
6 st:   112001.937500
7 st:   108768.914063
8 st:   85501.773438
9 st:   72161.312500
10 st:  67518.437500
11 st:  62258.648438


 

这篇关于PCA算法:从一组照片中获取特征脸(特征向量)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

Java发送SNMP至交换机获取交换机状态实现方式

《Java发送SNMP至交换机获取交换机状态实现方式》文章介绍使用SNMP4J库(2.7.0)通过RCF1213-MIB协议获取交换机单/多路状态,需开启SNMP支持,重点对比SNMPv1、v2c、v... 目录交换机协议SNMP库获取交换机单路状态获取交换机多路状态总结交换机协议这里使用的交换机协议为常

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

C#使用iText获取PDF的trailer数据的代码示例

《C#使用iText获取PDF的trailer数据的代码示例》开发程序debug的时候,看到了PDF有个trailer数据,挺有意思,于是考虑用代码把它读出来,那么就用到我们常用的iText框架了,所... 目录引言iText 核心概念C# 代码示例步骤 1: 确保已安装 iText步骤 2: C# 代码程

Spring Boot中获取IOC容器的多种方式

《SpringBoot中获取IOC容器的多种方式》本文主要介绍了SpringBoot中获取IOC容器的多种方式,包括直接注入、实现ApplicationContextAware接口、通过Spring... 目录1. 直接注入ApplicationContext2. 实现ApplicationContextA

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

Python获取浏览器Cookies的四种方式小结

《Python获取浏览器Cookies的四种方式小结》在进行Web应用程序测试和开发时,获取浏览器Cookies是一项重要任务,本文我们介绍四种用Python获取浏览器Cookies的方式,具有一定的... 目录什么是 Cookie?1.使用Selenium库获取浏览器Cookies2.使用浏览器开发者工具

Java获取当前时间String类型和Date类型方式

《Java获取当前时间String类型和Date类型方式》:本文主要介绍Java获取当前时间String类型和Date类型方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录Java获取当前时间String和Date类型String类型和Date类型输出结果总结Java获取