主成分分析-简单人脸识别(二)
一):人脸预准备
(文章说明:正常的人脸识别时,需要的是足够多的样本来进行训练,以期达到准确率高的目的。这里,只是尝试运用PCA算法基本上实现人脸的识别。)
那么我所使用到的人脸模板就是简单的12张处理过的人脸图像(很多是直接从网上下载的,有涉及到肖像权的请通知哈~_~!)。正常情况下,为了使算法更好,怎么也得好多个不同的人脸图片吧,对每张脸来说,怎么也得好几副不同的图像才可以达到很好的效果。(作为简单介绍性实验就先用这些单一的模板)。
对于每张人脸的大小和比例剪切将直接影响到结果的好坏,这里就尽量选取人脸中心的部分,避免图片中含有较多的头发、图片太暗等等。我这里把每张图片处理成150*180像素大小的,为了便于一次性显示,这里将图片叠在一起如下所示,想做同样实验的可以自己去找图片处理咯。
二):图片储存与预处理
在进行PCA分析图片之前,首先得明白图片作为一个样本的输入格式,怎么样输入便于函数的整体处理等等。我们知道,对于一副图像来说,它是一个矩阵形式存在,彩色图像更是复杂,所以在这里处理时,首先对图像进行灰度处理。既然一副图是一个矩阵,那么怎么把所有的人脸样本整合在一块呢?这里参考别人的做法,把一副M*N的图像重新变换成1*(M*N)的图像,matlab中的函数是reshape函数。这样每一个人脸变成1行多列的数据,在把所有的图像按行的形式叠加起来就形成了a*b的样本空间,其中a就表示样本个数,b就是样本的初始维度,而我们要做的不就是通过PCA方法来降低维度b吗?
根据上面对数据存储的方式编写程序如下(前提是你的图像得事先处理成相同大小的,并且导入到目录文件夹才行):
%--------------函数说明-------------
% 整合输入的人脸样本
% 输出:样本矩阵
%-----------------------------------
function ImgData = imgdata()
%用法: ImgData = imgdata();
namud = 0.5; %原始图片缩小倍数
%分别导入图片
pic1 = rgb2gray(imread('1.jpg')); pic1 = imresize(pic1,namud);
pic2 = rgb2gray(imread('2.jpg')); pic2 = imresize(pic2,namud);
pic3 = rgb2gray(imread('3.jpg')); pic3 = imresize(pic3,namud);
pic4 = rgb2gray(imread('4.jpg')); pic4 = imresize(pic4,namud);
pic5 = rgb2gray(imread('5.jpg')); pic5 = imresize(pic5,namud);
pic6 = rgb2gray(imread('6.jpg')); pic6 = imresize(pic6,namud);
pic7 = rgb2gray(imread('7.jpg')); pic7 = imresize(pic7,namud);
pic8 = rgb2gray(imread('8.jpg')); pic8 = imresize(pic8,namud);
pic9 = rgb2gray(imread('9.jpg')); pic9 = imresize(pic9,namud);
pic10 = rgb2gray(imread('10.jpg')); pic10 = imresize(pic10,namud);
pic11 = rgb2gray(imread('11.jpg')); pic11 = imresize(pic11,namud);
pic12 = rgb2gray(imread('12.jpg')); pic12 = imresize(pic12,namud);
[m,n] = size(pic1); %取图片大小
% 下面采用一个细胞体结构的数据类型存储多个矩阵
pic_all = {pic1,pic2,pic3,pic4,pic5,pic6,pic7,pic8,pic9,pic10,pic11,pic12};
for i=1:12%把m*n的矩阵变换成1*(m*n)的矩阵ImgData(i,:) = reshape(pic_all{i},1,m*n);
end
%讲数据范围缩小到0到1之间
ImgData = double(ImgData)/255;
说明一下,为什么要缩小一倍,后面在PCA求取协方差与提取特征向量的时候考虑到数据量太大的缘故,如果效果不好的话可以改变这个系数。这样就把原始数据图像所有样本全部存入到一个矩阵中。
三):主成分分析
得到了样本矩阵,接下来是对该矩阵进行特征值与特征向量的提取,以达到降维的目的。这部分原理基础在上一篇介绍过了:
http://blog.csdn.net/on2way/article/details/42175439
那么直接编程序实现:
<span style="font-size:18px;">%--------------函数说明-------------
%-----简单主成分分析算法
%-----输入:样本集合矩阵:img
% 降维的维数 :k
%-----输出:细胞结构体数据 :Cell_all
%-----------------------------------
function Cell_all = PCA(img,k)
%reshape函数:改变句矩阵的大小,矩阵的总元素个数不能变
%img = [1,2;2,1;3,3;3,6;6,3];
% k = 2;
% img = double(img);
[m,n] = size(img); %取大小
img_mean = mean(img); %求每列平均值
img_mean_all = repmat(img_mean,m,1);%复制m行平均值至整个矩阵
Z = img - img_mean_all;
T = Z'*Z;%协方差矩阵
[V,D] = eigs(T,k);%计算T中最大的前k个特征值与特征向量
img_new = img*V*D; %低维度下的各个脸的数据
Cell_all = {img_new,V,D};</span>
可能会注意到上面的img_new = img*V*D;这里把特征值矩阵也乘上了,本质上特征值的大小代表的是这个向量方向上的对原始数据的影响程度,乘上以后个人理解就是加大了低维里面的不同维度之间的这种差异性。我也试过不乘这个D,发现效果还没有乘上好,索性就乘上了。
函数返回的是一个结构体的数据,这里比较有趣的是对特征向量V的分析。
如果我们选取的k=30的话,得到V的大小为6750*30(这里一副人脸变换后的大小是1*6750了),表示有30维的特征向量(取的是特征值最大的前30个)。
这里如果我们单把第一主分量、第二主分量等等对应的特征向量以图片的形式显示出来会怎样?比如选取V中的第一列所有数据(成分最大的向量方向),再把它变换成原图片的大小的样子,再显示出来,这就形成了所谓的特征脸,
程序如下(V已经知道了):
namud = 0.5;
V = Cell_all{2};
V = V';
pic = V(1,:); %取第一个最大的主成分
pic = reshape(pic,180*namud,150*namud); %变换成图片大小
imshow(pic ,[]);
运行后结果如下:
这就是第一主成分下的特征向量脸。
那么我们再把第二大特征向量、第三大特征向量等等都显示出来:
namud = 0.5;
V = Cell_all{2};
V = V';
[m,n] = size(V);%取大小
for i=1:m
pic{i} = V(i,:);
pic{i} = reshape(pic{i},180*namud,150*namud);
end
p=pic{1};imshow(p,[]);
subplot(2,5,1);p=pic{1};imshow(p,[]);
subplot(2,5,2);p=pic{2};imshow(p,[]);
subplot(2,5,3);p=pic{3};imshow(p,[]);
subplot(2,5,4);p=pic{4};imshow(p,[]);
subplot(2,5,5);p=pic{5};imshow(p,[]);
subplot(2,5,6);p=pic{6};imshow(p,[]);
subplot(2,5,7);p=pic{7};imshow(p,[]);
subplot(2,5,8);p=pic{8};imshow(p,[]);
subplot(2,5,9);p=pic{9};imshow(p,[]);
subplot(2,5,10);p=pic{10};imshow(p,[]);
这里给出前10个的程序,再给出接着的后10的程序(省略了,只用改一下相关pic里面的数字就可以了),一共前20个特征向量的图像(30维里面,还有10个就不显示了),得到结果为:
前10个:
前11~20个:
可以看到,到13主分量以后的分量上的特征脸,基本上特征向量已经不再是表示一个人脸的某部分特征了,而是一些其他方面的噪声(可能吧),也就是说可能只是前13个分量在起作用,或者说其实把这些样本降维到13维下是不是最好的呢?
四):检验识别效果
有了上面计算出来的特征向量以及特征值的基础后,接下来我们来重新输入一个人脸图像,看看识别的怎么样。这里直接以上述人脸排列的序号作为识别的结果返回。
有一个问题就是怎么定义待检测的脸与样本中的脸的差别呢?我们上面计算了,原始样本脸在新维度(30维)下的脸的数据,是不是就是img_new = img*V*D;这个值,那么来一个新的脸,同样先预处理(先缩小,在拉申成1行数据),处理后假设为x(1行n列了),那么x在新的低维度空间里面的数据是什么呢?直接相乘V与D吧,也就是xx = x*V*D ;有了原始样本和待检测样本在低维空间的数据,要判断待检测样本与哪个样本最相近,直接求取高维空间中点与点之间的欧氏距离不就可以了,想象一下三维坐标中,两个点如果很像,靠的很近,那么两个点之间的距离是不是很小?Matlab中求点距离直接用求范数的函数norm就可以。
基于此来编写程序如下:
<span style="font-size:18px;">%--------------函数说明-------------
%-----人脸匹配
%-----输入:细胞结构体数据Cell_all(包括样本集合,特征值与特征向量)
% 想要识别的人脸(彩色图像)
%-----输出:匹配的结果
%-----------------------------------
function FaceFind = facefind(Cell_all,img2find)
%细胞结构体的调用
img_all = Cell_all{1};
[m1,n1] = size(img_all);
V = Cell_all{2};
D = Cell_all{3};
namud = 0.5; %图片缩小的倍数
%对需要识别的图像进行灰度等的处理
pic = rgb2gray(img2find); %灰度处理
pic = imresize(pic,namud); %变换大小
[m2,n2] = size(pic);
pic = reshape(pic,1,m2*n2); %重新排列
pic = double(pic)/255;
pic_done = pic*V*D; %处理完的数据
%% 归一化 --》避免运算出现特别大的数据
Ma = max(max(pic_done));
Mi = min(min(pic_done));
pic_done = pic_done/(Ma - Mi);
%%
for i=1:m1% 归一化 --》避免运算出现特别大的数据Ma1 = max(img_all(i,:));Mi1 = min(img_all(i,:));img_all(i,:) = img_all(i,:)/(Ma1 - Mi1);%求范数--》把他们之间的几何距离作为评判与哪一个人脸最近的标准error(i) = norm(img_all(i,:)-pic_done);
end
%找到其中最近的就认为是所要识别的人脸
FaceFind = find(error == min(error));
% FaceFind = error;</span><span style="font-size:14px;">
</span>
上述中有一些需要对数据进行大小调整,避免数据太大运行慢。
准备完成了就来进行实验吧,试验之前得先找到要待测脸,并且又得与原始样本不一样,考虑样本难找(得去专业人脸数据库中去找),直接自己手工制作吧(把某副原始样本PS下,人为制造不同~—~)(第三个样本就不是PS了,而是博主直接自己贡献出来了,找了张不同的图片,哈哈!~—~!)。
对这三幅图像分别进行匹配,运行函数facefind如下:
>> FaceFind1 = facefind(Cell_all,test2),
FaceFind2 = facefind(Cell_all,test1),
FaceFind3 = facefind(Cell_all,test)
FaceFind1 =
1
FaceFind2 =
10
FaceFind3 =
2
对应的结果就是原始样本的下列:
从结果来看第一张和第三张正确,第二张错了(。。。话说样本中第一与第十的美女样本确实很像呀),原因是人为制造的干扰过多?当然主要还是样本量太少,训练不够所致,算法上也是最简单的实验那种,还可以有很多优化改进。有机会去下载人脸数据库来实验实验,兴许结果会好些。
补充:PCA人脸数据库下的实验
PCA实验人脸库-人脸识别(四)
主成分分析-简单人脸识别(二)相关推荐
- 语音控制+人脸识别——二次开发 Parrot 无人机!
继"如何用100美元和 TensorFlow 来造一个能'看'东西的机器人" 之后,Lukas 又一最新力作. 在"造"出能进行物体识别的机器人后,下一步就很清 ...
- iOS黑科技之(AVFoundation)动态人脸识别(二)
iOS黑科技之(AVFoundation)动态人脸识别(二) 上一篇介绍了Core Image实现的静态人脸识别, 这里介绍AVFoundation的强大功能之一的动态人脸识别 一. 首先介绍一些人脸 ...
- Python三十行代码实现简单人脸识别
Python三十行代码实现简单人脸识别 一.库介绍 opencv,face_recognition,numpy,以及dlib 注意: 安装opencv速度可能过慢,需要更换国内镜像源,参考:https ...
- 2 找图像连通域_MATLAB--数字图像处理 简单人脸识别
简单人脸识别 思路 找到图像中连通域面积最大的那块连通域. i=imread('face.jpg'); I=rgb2gray(i); BW=im2bw(I); %利用阈值值变换法将灰度图像转换成二进制 ...
- MATLAB--数字图像处理 简单人脸识别
简单人脸识别 思路 找到图像中连通域面积最大的那块连通域. i=imread('face.jpg'); I=rgb2gray(i); BW=im2bw(I); %利用阈值值变换法将灰度图像转换成二进制 ...
- Android之OpenCv简单人脸识别功能(Bitmap)
Android之OpenCv简单人脸识别功能 OpenCv的下载 下载地址 - https://opencv.org/releases/ doc 文档目录 samples 示例代码 sdk 编译后的动 ...
- 基于主成分分析的人脸识别及表情识别
1.绘制训练集ex7data1.mat的二维图像,所有点在二维平面上的位置: 2.所求的特征向量U的主元1为-0.70711-0.70711i,主元2为-0.70711+0.70711i.所以主成分1 ...
- 机器学习算法之PCA(主成分分析)人脸识别,最小重构误差和最大化散度证明,PCA主成分分析原理剖析,PCA人脸识别matlab实现,PCA人脸识别python实现
目录 PCA介绍 PCA大致思路 PCA人脸识别(特征脸法) matlab代码实现 Python代码实现 PCA几何解释 PCA证明最小重构误差和最大散度等价 实验结果 PCA介绍 主成分分析(Pri ...
- 基于OpenCV的简单人脸识别系统
目录 1. 调用库函数 2. 调用摄像头并设置窗口 3. 设置图片正负样本数据集的路径 4. 调用人脸检测器 5. 正负样本载入 6.提取人脸区域 7. 建立LBPH人脸识别模型 8. 实时检测 9. ...
最新文章
- pandas KeyError [‘1‘] not found in axis 错误的解决方法
- spring:《spring实战》读后感三
- 在 centos6 上安装 LAMP
- c语言中有bool型变量吗?
- .php on line 0,启动禅道项目管理软件时,报PHP Warning: PHP Startup: in Unknown on line 0解决方法...
- 「编程面试题库」,大佬开发的一款小程序~
- 数据库SQL基础知识点
- python中有数组吗_python里面有数组吗
- Word 2003中打开最近操作过的文档的两种推荐的方法
- js中addEventListener第三个参数涉及到的事件捕获与冒泡
- Atitit custom popup 弹窗 techweo layers目录Custom div 1Open 2关闭popup 3关闭事件 3Custom div<!-- pw
- 2021年立秋是什么时候?立秋的习俗有哪些?
- python 使用公司邮箱发邮件_python 使用腾讯企业邮箱发送邮件
- 如何使用CubeMx生成一个DFU工程
- 嵌入式Linux开发常用命令总结
- 利用python提取基因cDNA长度,exon数量,pep长度和PI
- 算法时间复杂度计算方法
- 习题4-5 换硬币 将一笔零钱换成5分、2分和1分的硬币,要求每种硬币至少有一枚,有几种不同的换法?
- 大一C语言总结贴(持更) Part 3 计算圆周率
- 如何在 Linux 中找出内存消耗最大的进程