clc; clear all; % 路径设置 dataPath = 'D:\cxdownload\ORL人脸识别数据集'; files = dir(fullfile(dataPath, '*')); % 获取子目录列表 numPersons = length(files); % 总人数 (40人) imgPerPerson = 10; % 每个人有几张照片 (每人10张) allImages = []; % 存储全部拉直后的图像矩阵 labels = []; % 标签数组初始化 for i = 1:numPersons % 对每个人循环处理 personFolder = fullfile(dataPath, files(i).name); images = dir(fullfile(personFolder, '*.pgm')); for j = 1:imgPerPerson % 加载每个人的每一幅图像 imgFile = fullfile(personFolder, images{j}.name); img = imread(imgFile); % 读取PGM文件 if isempty(allImages) % 如果是第一次,则直接赋值 [h,w] = size(img); allImages = reshape(double(img), h*w, 1); else % 否则拼接到已有矩阵上 allImages = [allImages, reshape(double(img), h*w, 1)]; end labels = [labels; i]; % 添加对应标签 end end disp('已成功导入所有人脸数据.'); %% 数据预处理 - 归一化 & 分割训练/测试集合 trainIdx = randperm(numPersons*imgPerPerson) <= numPersons * floor(9 / 10 * imgPerPerson); testIdx = ~trainIdx; X_train = allImages(:, trainIdx)'; y_train = labels(trainIdx); X_test = allImages(:, testIdx)'; y_test = labels(testIdx); %% 执行PCA降维 [mu, coeff] = pca(X_train'); explainedVariance = cumsum(coeff.DiagonalValues)/sum(coeff.DiagonalValues)*100; optimalDim = find(explainedVariance >=85 ,1,'first'); % 只保留能解释超过85%方差的部分维度数 reducedTrainData = X_train * coeff(:,1:optimalDim); reducedTestData = X_test * coeff(:,1:optimalDim); %% 训练 SVM 并预测 model = fitcsvm(reducedTrainData,y_train,'KernelFunction','linear'); predictedLabels = predict(model,reducedTestData); accuracy = sum(predictedLabels == y_test)./length(y_test)*100; fprintf('本次实验的人脸识别准确率为 %.2f %% \n', accuracy); 元胞内容引用自非元胞数组对象。 出错 Untitled6 (line 18) imgFile = fullfile(personFolder, images{j}.name);
时间: 2025-06-25 08:18:52 浏览: 16
从代码和错误提示来看,您正在尝试加载 ORL 人脸识别数据集,并通过 PCA 和 SVM 实现人脸识别任务。以下是您的问题分析及解决方案:
---
### 错误原因
错误信息 `元胞内容引用自非元胞数组对象` 提示我们在第18行代码中存在问题:
```matlab
imgFile = fullfile(personFolder, images{j}.name);
```
此处的变量 `images` 应该是一个包含文件名结构体的**元胞数组**,但如果它不是元胞数组而是一般的结构体数组(即 `dir()` 返回的结果),那么访问其成员需要使用点语法 `.name` 而不是大括号 `{}`。
因此,应该将 `images{j}.name` 修改为 `images(j).name`。
---
### 解决方案
修改第17到19行代码如下:
```matlab
for j = 1:imgPerPerson % 加载每个人的每一幅图像
imgFile = fullfile(personFolder, images(j).name); % 正确的方式:使用 .name 访问字段
img = imread(imgFile); % 读取PGM文件
if isempty(allImages) % 如果是第一次,则直接赋值
[h,w] = size(img);
allImages = reshape(double(img), h*w, 1);
else % 否则拼接到已有矩阵上
allImages = [allImages, reshape(double(img), h*w, 1)];
end
labels = [labels; i]; % 添加对应标签
end
```
---
### 进一步优化建议
虽然修复上述错误可以让程序正常运行,但仍有一些地方可以改进以提高代码鲁棒性和效率:
#### 1. **检查是否存在指定路径**
在加载图片之前,先验证路径是否有效以及是否有足够数量的图片。例如:
```matlab
if length(images) < imgPerPerson || ~isfolder(personFolder)
error(['目录 ', personFolder, ' 下缺少足够的图片']);
end
```
#### 2. **避免动态增长矩阵**
当前代码每次迭代都会增加矩阵大小 (`[allImages,...`),这可能导致内存开销较大并影响性能。可以用预分配代替:
```matlab
totalImages = numPersons * imgPerPerson;
[h, w] = size(imread(fullfile(dataPath, files(1).name, images(1).name))); % 假设所有图像是统一尺寸
allImages = zeros(h*w, totalImages);
labels = zeros(totalImages, 1);
cnt = 1;
for i = 1:numPersons
personFolder = fullfile(dataPath, files(i).name);
images = dir(fullfile(personFolder, '*.pgm'));
for j = 1:min(length(images), imgPerPerson)
imgFile = fullfile(personFolder, images(j).name);
img = imread(imgFile);
allImages(:, cnt) = reshape(double(img), [], 1);
labels(cnt) = i;
cnt = cnt + 1;
end
end
```
#### 3. **SVM 的超参数调节**
您可以尝试不同的核函数或调整正则化参数 C 来进一步提升模型效果:
```matlab
model = fitcsvm(reducedTrainData, y_train, 'KernelFunction', 'rbf', 'BoxConstraint', 1);
```
---
###
阅读全文
相关推荐

















