利用facerec代码包中的eigenface进行人脸识别

1.   一个非常好的人脸识别代码包:

https://www.github.com/bytefish/facerec

https://github.com/bytefish/facerecognition_guide

http://bytefish.de/blog/eigenfaces/

http://www.bytefish.de/blog/fisherfaces/

 

第一个网址是一个非常好的人脸识别代码包地址,里面实现了eigenface和fisherface两种人脸识别方法,分别用matlab/octave和python实现;

第二个网址好像是较早的一个实现版本,但是里面包括了详细的说明文档;

第三个和第四个网址是作者的写的关于eigenface和fisherface的博客。

值得一提的是,opencvfaceRecognizer的说明文档貌似也是这位作者所写的(http://docs.opencv.org/trunk/modules/contrib/doc/facerec/index.html)。


2.   利用facerec代码包中的eigenface进行人脸识别:

2.1        训练eigenface model:

close all;
clear;
clc;

% read images
image_path = 'att_faces_select';
[X y width height names] = read_images(image_path);

% compute a model
[d,n] = size(X);
num_components = 30;
eigenface = eigenfaces(X,y,num_components);

%% plot the first (atmost) 16 eigenfaces
figure; 
title('Eigenfaces');
hold on;
for i=1:min(16, size(eigenface.W,2))
  subplot(4,4,i);
  comp = cvtGray(eigenface.W(:,i), width, height);
  imshow(comp);
  %colormap(jet(256));
  title(sprintf('Eigenface %i', i));
end

%% 3D plot of projection (first three classes, add those you want)
if(d >= 3)
  figure; hold on;
  for i = findclasses(eigenface.y, [1,2,3])
    % LineSpec: red dots 'r.'
    plot3(eigenface.P(1,i), eigenface.P(2,i), eigenface.P(3,i), 'r.'), view(45,-45);
    text(eigenface.P(1,i), eigenface.P(2,i), eigenface.P(3,i), num2str(eigenface.y(i)));
  end
end

%% save eigenfaces and names
save eigenface.mat eigenface names

首先利用read_images函数读入训练图像,read_images函数的参数是训练图像所在路径,注意,不同subject的图像应放在独自的文件夹中,read_images函数会给每个文件夹一个类别值(从1递增),并会记录每个文件夹的名字作为subject的名字。函数的输出参数X是把所有训练图像连接到一起组成的数据,其中每个二维图像都被转换为一维数据,存储成一列;输出参数y是各个图像所属类别值的集合;names是各个图像文件夹名字,即作为subject的名字。

之后调用eigenfaces函数训练eigenface,其中第三个输入参数为component个数,该参数可以省略,省略时eigenfaces函数内部取图像数目减1为component个数(是否应取类别个数减1为component个数呢?待考),输出参数为训练出的eigenface model。

之后会显示前16个eigenfaces.

利用facerec代码包中的eigenface进行人脸识别_第1张图片

之后会3d显示所有eigenface的位置,显示的是每个eigenface投影空间中三个数据组成的坐标值。Findclasses作用(???)

最后将eigenface和names保存。


2.2    预测图像

close all;
clear;
clc;


% user defined variable
threshold = 0.65;


%% load eigenface model
load eigenface.mat


%% load image
%filename = 'train_set/lcy_train/frame4_face0.jpg';
%filename = 'train_set/meilin_train/frame4_face0.jpg';
%filename = 'test_set/lcy_test/frame24_face0.jpg';
%filename = 'test_set/meilin_test/frame4_face0.jpg';
filename = 'att_faces_select/s3/2.pgm';
try
    T = double(imread(filename));
catch
    lerr = lasterror;
    fprintf(1,'Cannot read image %s', filename)
end
[height width channels] = size(T);
% greyscale the image if we have 3 channels
if(channels == 3)
    T = (T(:,:,1) + T(:,:,2) + T(:,:,3)) / 3;
end
test_image = [];
try
    test_image = [test_image, reshape(T,width*height,1)];
catch
    lerr = lasterror;
    fprintf(1,'Image cannot be added to the Array. Wrong image size?\n')
end


%% predict
k = 9;
%	Predicts nearest neighbor for given Eigenfaces model.
model = eigenface;
Q = model.W' * (test_image - model.mu);
[c, v, mean_k_dis, mean_all_dis] = my_knn(model.P, model.y, Q,  k);


%% show result
figure;
imshow(T,[]);
display(sprintf('subject: %s, mean_k_dis=%.2f, mean_all_dis=%.2f, dis_ratio=%.2f', names{c}, mean_k_dis, mean_all_dis, mean_k_dis/mean_all_dis));
display(sprintf('\tv=%i, k=%i', v, k));
if mean_k_dis/mean_all_dis < threshold
    title(names{c});
else
    title('unknown');
end

首先载入eigenface model数据;

其次载入待预测的图像数据,如果是彩色图,将其转换成灰度图;并将二维数据重新排列成一维向量数据;

之后利用训练好的eigenface model对test_image进行投影得到feature数据Q, 再对Q做knn分类,knn分类用my_knn函数实现,该函数改写自代码包中的knn函数。my_knn函数返回值包括:

c: test_image所属类别;

v:与test_image所属同一类别的neighbor个数;

mean_k_dis: Q和k个neighbor的平均距离,这k个neighbors是与Q距离最近的K个;

mean_all_dis: Q和所有vector的平均距离。

最后显示结果,从控制台显示subject名字, mean_k_dis, mean_all_dis和二者的比值,并显示v和k的值;

当mean_k_dis/mean_all_dis小于一定阈值时,认为正确识别,图像的title显示subject名字,否则认为未正确识别,图像的title显示unknown。

图像结果:


控制台输出结果:

subject: s3, mean_k_dis=3059.42, mean_all_dis=4770.58, dis_ratio=0.64
v=9, k=9



my_knn实现:

function [c, v, mean_k_dis, mean_all_dis] = my_knn(P, y, Q,  k)
	%%	My k-nearest neighbor classification.
	%%
	%%	Args:
	%%		P [dim x num_data] reference vectors
	%%		Q [dim x 1] query vector
	%%		y [1 x num_data] classes corresponding to P. (y = {1,2,...,n})
	%%		k [int] nearest neighbors used in this prediction
	%%
	%%	Returns:
	%%		c [int] Class identified by the majority of k neighbors.
	%%      v [int] Number of majority of k neighbors.
    %%      mean_k_dis [double] Mean distance of Q to the k neighbors.
    %%      mean_all_dis [double] Mean distance of Q to all vectors of P.
	
	n = size(P,2);	
	% clip k
	if (nargin == 3)
		k=1;
	elseif (k>n)
		k=n;
	end

	Q = repmat(Q, 1, n);
	distances = sqrt(sum(power((P-Q),2),1));
	[distances, idx] = sort(distances);
	y = y(idx);
	y = y(1:k);
	h = histc(y,(1:max(y)));
	[v,c] = max(h);
    
    min_k_dist = distances(1:k);
    mean_all_dis = mean(distances);
    mean_k_dis = mean(min_k_dist);
end


你可能感兴趣的:(利用facerec代码包中的eigenface进行人脸识别)