[未答复] 基于lda的人脸识别matlab代码错误

[复制链接]
liuyang1997 发表于 2021-5-2 10:49:40
clear all;

% 框架适用于:每个人拥有相同数量的图片

% 可选数据集:"ORL" "Yale" "COIL""AR"
dataset_name = "ORL";

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% ORL
if (dataset_name == "ORL")
    load('ORL4646.mat');
    people_num = 40; % 人(类)数
    total_pic_num = 400; % 总图片数量
    row = 46; % 行
    column = 46; % 列
    train_pic_num_of_each = 6; % 每个人的训练图片数
    data = ORL4646;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Yale
if (dataset_name == "Yale")
    load('Yale5040165.mat');
    people_num = 15; % 人(类)数
    total_pic_num = 165; % 总图片数量
    row = 50; % 行
    column = 40; % 列
    train_pic_num_of_each = 7; % 每个人的训练图片数
    data = Yale5040165;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% COIL
if (dataset_name == "COIL")
    load('COIL100.mat');
    people_num = 100; % 人(类)数
    total_pic_num = 7200; % 总图片数量
    row = 32; % 行
    column = 32; % 列
    train_pic_num_of_each = 44; % 每个人的训练图片数
    data = double(COIL100); % 原始数据
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% AR
if (dataset_name == "AR")
    load('AR120p20s50by40.mat');
    people_num = 120; % 人(类)数
    total_pic_num = 2400; % 总图片数量
    row = 50; % 行
    column = 40; % 列
    train_pic_num_of_each = 12; % 每个人的训练图片数
    data = AR120p20s50by40; % 原始数据
end

% 以上是不同数据集的数据初始化处理
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 数据分类

dimension = row * column; % 图片维度
pic_num_of_each = total_pic_num / people_num; % 每个人的图片数
test_pic_num_of_each = pic_num_of_each - train_pic_num_of_each; % 每个人的测试图片数

% 重塑后一列是一张脸
reshaped_faces = reshape(data, dimension, total_pic_num);

% 取出每个人图片的一定数量作为测试数据,剩下作为训练数据
test_data_index = [];
train_data_index = [];
for i=0:people_num-1
    test_data_index = [test_data_index pic_num_of_each*i+1:pic_num_of_each*i+test_pic_num_of_each];
    train_data_index = [train_data_index pic_num_of_each*i+test_pic_num_of_each+1:pic_num_of_each*(i+1)];
end
test_data = reshaped_faces(:, test_data_index);
train_data = reshaped_faces(:,train_data_index);
% waitfor(show_faces(train_data));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 降维算法

% 算每个类的平均
p = 1; % k 表示每一张图
people_mean = zeros(dimension, people_num); % 每个人的所有脸的平均为一列
for i=1:people_num
    % 求一列(即一个人)的均值
    temp = people_mean(:,i);
    % 遍历每个人的train_pic_num_of_each张用于训练的脸,相加算平均
    for j=1:train_pic_num_of_each
        temp = temp + train_data(:,p);
        p = p + 1;
    end
    people_mean(:,i) = temp / train_pic_num_of_each;
end

% 算类类间散度矩阵Sb
Sb = zeros(dimension, dimension);
all_mean = mean(train_data, 2); % 全部的平均
for i=1:people_num
    % 以每个人的平均脸进行计算,这里减去所有平均,中心化
    centered_data = people_mean(:,i) - all_mean;
    Sb = Sb + centered_data * centered_data';
end
Sb = Sb / people_num;

% 算类内散度矩阵Sw
Sw = zeros(dimension, dimension);
p = 1; % p表示每一张图片
for i=1:people_num % 遍历每一个人
    for j=1:train_pic_num_of_each % 遍历一个人的所有脸计算后相加
        centered_data = train_data(:,p) - people_mean(:,i);
        Sw = Sw + centered_data * centered_data';
        p = p + 1;
    end
end
Sw = Sw / (people_num * train_pic_num_of_each);

% 目标函数一:不可逆时需要正则项扰动
% Sw = Sw + eye(dimension)*10^-6;
% target = Sw^-1 * Sb;

% 目标函数二:无正则项扰动,经典形式
target = Sw^-1 * Sb;

% 目标函数三:相减形式(也符合几何意义,即最大化Sb,最小化Sw)
% target = Sb - Sw;

% 目标函数四:NLDA 零空间LDA方法
% Q = null(Sw);
% target = Q*Q'*Sb*(Q*Q')';

% 求特征值、特征向量
[eigen_vectors, dianogol_matrix] = eig(target);
eigen_values = diag(dianogol_matrix);

% 对特征值、特征向量进行排序
[sorted_eigen_values, index] = sort(eigen_values, 'descend');
eigen_vectors = eigen_vectors(:, index);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 识别与可视化

index = 1;
X = [];
Y = [];
for i=1:5:101

    % 投影矩阵
    project_matrix = eigen_vectors(:,1:i);
    projected_train_data = project_matrix' * (train_data - all_mean);
    projected_test_data = project_matrix' * (test_data - all_mean);

    % KNN的k值
    K=1;

    % 用于保存最小的k个值的矩阵
    % 用于保存最小k个值对应的人标签的矩阵
    minimun_k_values = zeros(K,1);
    label_of_minimun_k_values = zeros(K,1);

    % 测试脸的数量
    test_face_number = size(projected_test_data, 2);

    % 识别正确数量
    correct_predict_number = 0;

    % 遍历每一个待测试人脸
    for each_test_face_index = 1:test_face_number

        each_test_face = projected_test_data(:,each_test_face_index);

        % 先把k个值填满,避免在迭代中反复判断
        for each_train_face_index = 1:K
            minimun_k_values(each_train_face_index,1) = norm(each_test_face - projected_train_data(:,each_train_face_index));
            label_of_minimun_k_values(each_train_face_index,1) = floor((train_data_index(1,each_train_face_index) - 1) / pic_num_of_each) + 1;
        end

        % 找出k个值中最大值及其下标
        [max_value, index_of_max_value] = max(minimun_k_values);

        % 计算与剩余每一个已知人脸的距离
        for each_train_face_index = K+1:size(projected_train_data,2)

            % 计算距离
            distance = norm(each_test_face - projected_train_data(:,each_train_face_index));

            % 遇到更小的距离就更新距离和标签
            if (distance < max_value)
                minimun_k_values(index_of_max_value,1) = distance;
                label_of_minimun_k_values(index_of_max_value,1) = floor((train_data_index(1,each_train_face_index) - 1) / pic_num_of_each) + 1;
                [max_value, index_of_max_value] = max(minimun_k_values);
            end
        end

        % 最终得到距离最小的k个值以及对应的标签
        % 取出出现次数最多的值,为预测的人脸标签
        predict_label = mode(label_of_minimun_k_values);
        real_label = floor((test_data_index(1,each_test_face_index) - 1) / pic_num_of_each)+1;

        if (predict_label == real_label)
            %fprintf("预测值:%d,实际值:%d,正确\n",predict_label,real_label);
            correct_predict_number = correct_predict_number + 1;
        else
            %fprintf("预测值:%d,实际值:%d,错误\n",predict_label,real_label);
        end
    end

    correct_rate = correct_predict_number/test_face_number;

    X = [X i];
    Y = [Y correct_rate];

    fprintf("k=%d,i=%d,总测试样本:%d,正确数:%d,正确率:%1f\n", K, i,test_face_number,correct_predict_number,correct_rate);

    if (i == 101)
        waitfor(plot(X,Y));
    end
end

% 二三维可视化
class_num_to_show = 3;
pic_num_in_a_class = test_pic_num_of_each;
pic_to_show = class_num_to_show * pic_num_in_a_class;
for i=[2 3]

    % 取出相应数量特征脸
    project_matrix = eigen_vectors(:,1:i);

    % 投影
    projected_test_data = project_matrix' * (test_data - all_mean);
    projected_test_data = projected_test_data(:,1:pic_to_show);

    color = [];
    for j=1:pic_to_show
        color = [color floor((j-1)/pic_num_in_a_class)*20];
    end

    % 显示
    if (i == 2)
        subplot(1, 7, [1, 2, 3, 4]);
        scatter(projected_test_data(1, :), projected_test_data(2, :), [], color, 'filled');
        for j=1:3
            subplot(1, 7, j+4);
            fig = show_face(test_data(:,floor((j - 1) * pic_num_in_a_class) + 1), row, column);
        end
        waitfor(fig);
    else
        subplot(1, 7, [1, 2, 3, 4]);
        scatter3(projected_test_data(1, :), projected_test_data(2, :), projected_test_data(3, :), [], color, 'filled');
        for j=1:3
            subplot(1, 7, j+4);
            fig = show_face(test_data(:,floor((j - 1) * pic_num_in_a_class) + 1), row, column);
        end
        waitfor(fig);
    end
end

% 输入向量,显示脸
function fig = show_face(vector, row, column)
    fig = imshow(mat2gray(reshape(vector, [row, column])));
end

>> show_face
错误: 文件:show_face.m 行:6 列:16
输入字符不是 MATLAB 语句或表达式中的有效字符。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

相关帖子
热门教程
站长推荐
快速回复 返回顶部 返回列表